diff --git a/Cargo.lock b/Cargo.lock index f28b12d..c591d9a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1220,7 +1220,7 @@ checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "coman" -version = "0.8.7" +version = "0.8.8" dependencies = [ "anyhow", "aws-sdk-s3", diff --git a/coman/.config/config.toml b/coman/.config/config.toml index 098257d..775f594 100644 --- a/coman/.config/config.toml +++ b/coman/.config/config.toml @@ -1,3 +1,5 @@ +update_check_interval_hours = 24 + [cscs] # check https://docs.cscs.ch/access/firecrest/#firecrest-deployment-on-alps for possible system and platform combinations current_system = "daint" # what system/cluster to execute commands on diff --git a/coman/Cargo.toml b/coman/Cargo.toml index 46063d2..9639be2 100644 --- a/coman/Cargo.toml +++ b/coman/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "coman" -version = "0.8.7" +version = "0.8.8" edition = "2024" description = "Compute Manager for managing HPC compute" authors = ["Ralf Grubenmann "] diff --git a/coman/src/cli/app.rs b/coman/src/cli/app.rs index 6d94e92..e3573e1 100644 --- a/coman/src/cli/app.rs +++ b/coman/src/cli/app.rs @@ -1,9 +1,11 @@ use std::{error::Error, path::PathBuf, str::FromStr, thread}; +use chrono::{DateTime, Local, TimeDelta}; use clap::{Args, Command, Parser, Subcommand, ValueHint, builder::TypedValueParser}; use clap_complete::{ArgValueCompleter, CompletionCandidate, Generator, Shell, generate}; use color_eyre::{Report, Result}; use itertools::Itertools; +use self_update::cargo_crate_version; use strum::VariantNames; use tokio::sync::mpsc; @@ -568,3 +570,42 @@ fn is_bare_string(value_str: &str) -> bool { pub fn print_completions(generator: G, cmd: &mut Command) { generate(generator, cmd, cmd.get_name().to_string(), &mut std::io::stdout()); } + +pub fn update() -> Result<()> { + let status = self_update::backends::github::Update::configure() + .repo_owner("SwissDataScienceCenter") + .repo_name("coman") + .bin_name("coman") + .bin_path_in_archive("coman") + .show_download_progress(true) + .current_version(cargo_crate_version!()) + .build()? + .update()?; + if status.updated() { + println!("Successfully updated to version: `{}`", status.version()); + } else { + println!("Already up to date at version: `{}`", status.version()); + } + Ok(()) +} + +pub async fn check_update() -> Result<()> { + let config = Config::new()?; + let data_dir = get_data_dir(); + let stamp_path = data_dir.join("selfupdate.stamp"); + let Ok(update_stamp) = std::fs::read_to_string(&stamp_path) else { + std::fs::write(&stamp_path, Local::now().to_rfc3339()).unwrap(); + return Ok(()); + }; + let update_stamp = DateTime::parse_from_rfc3339(&update_stamp)?; + + let now = Local::now(); + if now.naive_local() - update_stamp.naive_local() + > TimeDelta::hours(config.values.update_check_interval_hours as i64) + { + println!("checking for updates"); + update()?; + std::fs::write(&stamp_path, Local::now().to_rfc3339())?; + } + Ok(()) +} diff --git a/coman/src/config.rs b/coman/src/config.rs index 48689eb..e4b1147 100644 --- a/coman/src/config.rs +++ b/coman/src/config.rs @@ -83,6 +83,8 @@ pub struct ComanConfig { #[serde(default)] pub coman_squash_path: Option, #[serde(default)] + pub update_check_interval_hours: u64, + #[serde(default)] pub cscs: CscsConfig, } diff --git a/coman/src/main.rs b/coman/src/main.rs index 0aecf6f..0759cc9 100644 --- a/coman/src/main.rs +++ b/coman/src/main.rs @@ -4,7 +4,6 @@ use clap::{CommandFactory, Parser}; use clap_complete::CompleteEnv; use color_eyre::Result; use keyring::set_global_service_name; -use self_update::cargo_crate_version; use tokio::{runtime::Handle, sync::mpsc}; use tuirealm::{ Application, EventListenerCfg, PollStrategy, Sub, SubClause, SubEventClause, Update, @@ -22,7 +21,7 @@ use crate::{ cli::{ app::{ Cli, CliCommands, ConfigCommands, CscsCommands, CscsFileCommands, CscsJobCommands, CscsSystemCommands, - get_config, print_completions, set_config, version, + check_update, get_config, print_completions, set_config, update, version, }, exec::cli_exec_command, proxy::cli_proxy_command, @@ -64,6 +63,12 @@ async fn main() -> Result<()> { set_global_service_name(env!("CARGO_PKG_NAME")); crate::logging::init()?; CompleteEnv::with_factory(Cli::command).complete(); + + // check self-update + if let Err(e) = check_update().await { + println!("Couldn't check for updates: {}", e); + } + let args = Cli::parse(); match args.command { Some(command) => match command { @@ -379,21 +384,3 @@ fn popup_exclusion_clause() -> SubClause { SubClause::IsMounted(Id::SystemSelectPopup), ]))) } - -fn update() -> Result<()> { - let status = self_update::backends::github::Update::configure() - .repo_owner("SwissDataScienceCenter") - .repo_name("coman") - .bin_name("coman") - .bin_path_in_archive("coman") - .show_download_progress(true) - .current_version(cargo_crate_version!()) - .build()? - .update()?; - if status.updated() { - println!("Successfully updated to version: `{}`", status.version()); - } else { - println!("Already up to date at version: `{}`", status.version()); - } - Ok(()) -}