Compare commits
9 Commits
45f2bb64b0
...
8a35904c79
Author | SHA1 | Date | |
---|---|---|---|
|
8a35904c79 | ||
|
c55ccf005b | ||
|
b6a234a833 | ||
|
2a0dee78a7 | ||
|
b67242d0ea | ||
|
7b8e613058 | ||
|
74006af796 | ||
|
d608fe6b50 | ||
|
3cfbc2a656 |
37
.woodpecker.yml
Normal file
37
.woodpecker.yml
Normal file
@ -0,0 +1,37 @@
|
||||
# https://woodpecker-ci.org/docs/usage/intro
|
||||
pipeline:
|
||||
|
||||
build_and_test:
|
||||
image: rust
|
||||
commands:
|
||||
- cargo test
|
||||
- cargo build --release
|
||||
|
||||
gitea_on_release:
|
||||
# http://plugins.drone.io/drone-plugins/drone-gitea-release/
|
||||
image: plugins/gitea-release
|
||||
files: target/release/reel-moby
|
||||
secrets: [gitea_release_api_key, gitea_release_base_url]
|
||||
when:
|
||||
event: tag
|
||||
tag: v*
|
||||
|
||||
github_on_release:
|
||||
# http://plugins.drone.io/drone-plugins/drone-github-release/
|
||||
image: plugins/github-release
|
||||
files: target/release/reel-moby
|
||||
secrets: [github_release_api_key]
|
||||
when:
|
||||
event: tag
|
||||
tag: v*
|
||||
|
||||
notify_when_failure:
|
||||
# http://plugins.drone.io/appleboy/drone-discord/
|
||||
image: appleboy/drone-discord
|
||||
secrets: [ discord_webhook_id, discord_webhook_token]
|
||||
message: "build {{build.number}} or release failed. Fix me please."
|
||||
when:
|
||||
status: failure
|
||||
|
||||
|
||||
# http://plugins.drone.io/drone-plugins/drone-github-release/
|
@ -1,7 +1,7 @@
|
||||
|
||||
[package]
|
||||
name = "reel-moby"
|
||||
version = "0.10.0"
|
||||
version = "0.11.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
@ -7,4 +7,4 @@ search for new docker tags and update them in your docker-compose file
|
||||
Searches the current folder for a docker-compose.(yml|yaml) file and opens it when it found one. Then it is possible to select a image line. The program then shows the found repository and shows the latest tags. The tags can be scrolled and selected, which updates the opened file.
|
||||
From that point save the file and pull the new image with `docker-compose up -d` or `docker-compse pull`.
|
||||
|
||||
[screenshot](./screenshot.png)
|
||||
![screenshot](./screenshot.png)
|
||||
|
BIN
screenshot.png
BIN
screenshot.png
Binary file not shown.
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 41 KiB |
@ -15,7 +15,7 @@ pub struct Opt {
|
||||
|
||||
/// A custom path to a docker-compose file
|
||||
#[structopt(short, long, parse(from_os_str))]
|
||||
config: Option<PathBuf>,
|
||||
file: Option<PathBuf>,
|
||||
|
||||
/// Give a Repository identifier, e.g. library/nginx
|
||||
#[structopt(short, long, parse(from_str))]
|
||||
|
@ -2,24 +2,16 @@ use std::fmt;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
// use crate::common;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Error {
|
||||
// Conversion,
|
||||
// Empty,
|
||||
NoTagFound,
|
||||
// InvalidChar,
|
||||
MisformedInput,
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
// Error::Conversion => write!(f, "Conversion error"),
|
||||
// Error::Empty => write!(f, "Input is empty"),
|
||||
Error::NoTagFound => write!(f, "Expected a tag"),
|
||||
// Error::InvalidChar => write!(f, "Invalid character found"),
|
||||
Error::MisformedInput => write!(f, "Unexpected input"),
|
||||
}
|
||||
}
|
||||
|
60
src/tags.rs
60
src/tags.rs
@ -7,7 +7,6 @@ use serde::Deserialize;
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
struct ImageDetails {
|
||||
architecture: String,
|
||||
// os: String,
|
||||
size: usize,
|
||||
}
|
||||
|
||||
@ -25,6 +24,30 @@ pub struct Images {
|
||||
last_updated: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for Images {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
//architecture infos
|
||||
let mut arch = String::new();
|
||||
for image in self.images.iter().take(1) {
|
||||
arch.push_str(&format!("{}", image));
|
||||
}
|
||||
for image in self.images.iter().skip(1) {
|
||||
arch.push_str(&format!(", {}", image));
|
||||
}
|
||||
|
||||
let now = chrono::Utc::now();
|
||||
let rfc3339 = DateTime::parse_from_rfc3339(&self.last_updated).unwrap();
|
||||
let dif = now - rfc3339.with_timezone(&chrono::Utc);
|
||||
write!(
|
||||
f,
|
||||
"{} vor {} [{}]",
|
||||
self.tag_name,
|
||||
format_time_nice(dif),
|
||||
arch
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Tags {
|
||||
count: usize,
|
||||
@ -41,7 +64,6 @@ pub enum Error {
|
||||
Converting(String),
|
||||
/// invalid repos show a valid json with 0 tags
|
||||
NoTagsFound,
|
||||
NoNextPage,
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
@ -49,7 +71,6 @@ impl fmt::Display for Error {
|
||||
match self {
|
||||
Error::Fetching(s) => write!(f, "Fetching error: {}", s),
|
||||
Error::Converting(s) => write!(f, "Converting error: {}", s),
|
||||
Error::NoNextPage => write!(f, "No next page available"),
|
||||
Error::NoTagsFound => write!(f, "Given Repo has 0 tags. Is it valid?"),
|
||||
}
|
||||
}
|
||||
@ -98,38 +119,17 @@ impl Tags {
|
||||
}
|
||||
|
||||
/// returns tags of next page
|
||||
pub fn next_page(&self) -> Result<Self, Error> {
|
||||
pub fn next_page(&self) -> Option<Self> {
|
||||
match &self.next_page {
|
||||
Some(url) => Self::with_url(url),
|
||||
None => Err(Error::NoNextPage),
|
||||
Some(url) => match Self::with_url(url) {
|
||||
Ok(tags) => Some(tags),
|
||||
Err(_) => None,
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Images {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
//architecture infos
|
||||
let mut arch = String::new();
|
||||
for image in self.images.iter().take(1) {
|
||||
arch.push_str(&format!("{}", image));
|
||||
}
|
||||
for image in self.images.iter().skip(1) {
|
||||
arch.push_str(&format!(", {}", image));
|
||||
}
|
||||
|
||||
let now = chrono::Utc::now();
|
||||
let rfc3339 = DateTime::parse_from_rfc3339(&self.last_updated).unwrap();
|
||||
let dif = now - rfc3339.with_timezone(&chrono::Utc);
|
||||
write!(
|
||||
f,
|
||||
"{} vor {} [{}]",
|
||||
self.tag_name,
|
||||
format_time_nice(dif),
|
||||
arch
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// converts a given duration to a readable string
|
||||
fn format_time_nice(time: chrono::Duration) -> String {
|
||||
if time.num_weeks() == 52 {
|
||||
|
@ -54,7 +54,7 @@ impl Ui {
|
||||
state: State::SelectService,
|
||||
repo: repo_entry::RepoEntry::new(repo_id),
|
||||
tags: tag_list::TagList::with_status("Tags are empty"),
|
||||
services: service_switcher::ServiceSwitcher::new(&opt.config).unwrap(),
|
||||
services: service_switcher::ServiceSwitcher::new(&opt.file).unwrap(),
|
||||
info: info::Info::new("Select image of edit Repository"),
|
||||
};
|
||||
|
||||
@ -122,6 +122,7 @@ impl Ui {
|
||||
State::SelectTag => {
|
||||
let mut repo = ui.repo.get();
|
||||
let tag = match ui.tags.get_selected() {
|
||||
Err(tag_list::Error::NextPageSelected) => continue,
|
||||
Err(e) => {
|
||||
ui.info.set_info(&format!("{}", e));
|
||||
continue;
|
||||
|
@ -10,7 +10,7 @@ use termion::input::TermRead;
|
||||
use crate::widget::service_switcher;
|
||||
|
||||
pub fn create_ui(opt: &Opt) {
|
||||
let service_result = service_switcher::ServiceSwitcher::new(&opt.config);
|
||||
let service_result = service_switcher::ServiceSwitcher::new(&opt.file);
|
||||
match service_result {
|
||||
None => no_yaml::NoYaml::run(opt),
|
||||
Some(_) => default::Ui::run(opt),
|
||||
|
@ -11,7 +11,7 @@ impl Info {
|
||||
Self {
|
||||
info: String::from(info),
|
||||
keys: String::from(
|
||||
"Tab Cycle widgets C-s Save C-r Reload C-q Quit ↑ ↓ Select tags or image line",
|
||||
"Tab Cycle widgets C-s Save C-r Reload C-q Quit ↑ ↓ Select tags or image line Return Select current selection",
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -68,8 +68,8 @@ impl TagList {
|
||||
.collect();
|
||||
|
||||
match tags.next_page() {
|
||||
Err(_) => (),
|
||||
Ok(new_tags) => {
|
||||
None => (),
|
||||
Some(new_tags) => {
|
||||
lines.push(Line::NextPage(String::from("load more tags")));
|
||||
tags = new_tags;
|
||||
}
|
||||
@ -149,8 +149,8 @@ impl TagList {
|
||||
fn load_next_page(&mut self) {
|
||||
match &self.tags {
|
||||
Some(tags) => match tags.next_page() {
|
||||
Err(_) => (),
|
||||
Ok(new_tags) => {
|
||||
None => (),
|
||||
Some(new_tags) => {
|
||||
//load new tags object
|
||||
self.tags = Some(new_tags);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user