-
Notifications
You must be signed in to change notification settings - Fork 85
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add automatic version checking to pre-run
- Loading branch information
1 parent
f16e6b8
commit 0361f50
Showing
7 changed files
with
124 additions
and
32 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,19 @@ | ||
use ansi_term::Colour::Cyan; | ||
use serde::Serialize; | ||
use structopt::StructOpt; | ||
|
||
use crate::command::RoverStdout; | ||
use crate::{Result, PKG_VERSION}; | ||
use crate::{utils::version, Result}; | ||
|
||
use semver::Version; | ||
|
||
use rover_client::releases::get_latest_release; | ||
use houston as config; | ||
|
||
#[derive(Debug, Serialize, StructOpt)] | ||
pub struct Check { | ||
// TODO: support prerelease check through flag | ||
// future: support prerelease check through flag --prerelease | ||
} | ||
|
||
impl Check { | ||
pub fn run(&self) -> Result<RoverStdout> { | ||
let latest = get_latest_release()?; | ||
let update_available = needs_update(&latest, PKG_VERSION)?; | ||
|
||
if update_available { | ||
eprintln!( | ||
"There is a newer version of Rover available for download: {} (currently running v{})\n\nFor instructions on how to install the latest version of Rover, see {}", | ||
Cyan.normal().paint(format!("v{}", latest)), | ||
PKG_VERSION, | ||
Cyan.normal().paint("https://go.apollo.dev/r/start") | ||
); | ||
} else { | ||
eprintln!("Rover is up to date!"); | ||
} | ||
|
||
pub fn run(&self, config: config::Config) -> Result<RoverStdout> { | ||
version::check_for_update(config, true)?; | ||
Ok(RoverStdout::None) | ||
} | ||
} | ||
|
||
fn needs_update(latest: &str, running: &str) -> Result<bool> { | ||
let latest = Version::parse(latest)?; | ||
let running = Version::parse(running)?; | ||
Ok(latest > running) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,3 +6,4 @@ pub mod parsers; | |
pub mod pkg; | ||
pub mod stringify; | ||
pub mod telemetry; | ||
pub mod version; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
use std::{fs, path::PathBuf, time::SystemTime}; | ||
|
||
use rover_client::releases::get_latest_release; | ||
|
||
use ansi_term::Colour::Cyan; | ||
use semver::Version; | ||
|
||
use crate::{Result, PKG_VERSION}; | ||
|
||
use houston as config; | ||
|
||
const ONE_HOUR: u64 = 60 * 60; | ||
const ONE_DAY: u64 = ONE_HOUR * 24; | ||
|
||
/// check for newer versions of rover. | ||
/// | ||
/// If this fn is run explicitly from a user-facing command, we pass `force` to | ||
/// check for newer versions, even if we recently checked for updates. | ||
/// | ||
/// If `force` is not passed, we check for updates every day at most | ||
pub fn check_for_update(config: config::Config, force: bool) -> Result<()> { | ||
let version_file = config.home.join("version.toml"); | ||
let current_time = SystemTime::now(); | ||
// if we don't end up checking, we don't want to overwrite the last checked time | ||
let mut checked = false; | ||
|
||
// check fs for last check time | ||
let last_checked_time = get_last_checked_time_from_disk(&version_file); | ||
|
||
match last_checked_time { | ||
Some(last_checked_time) => { | ||
let time_since_check = current_time.duration_since(last_checked_time)?.as_secs(); | ||
tracing::debug!( | ||
"Time since last update check: {:?}h", | ||
time_since_check / ONE_HOUR | ||
); | ||
|
||
if force || time_since_check > ONE_DAY { | ||
do_update_check(&mut checked)?; | ||
} else { | ||
tracing::debug!( | ||
"No need to check for updates. Automatic checks happen once per day" | ||
); | ||
} | ||
} | ||
// we haven't checked for updates before -- check now :) | ||
None => { | ||
do_update_check(&mut checked)?; | ||
} | ||
} | ||
|
||
if checked { | ||
tracing::debug!("Checked for available updates. Writing current time to disk"); | ||
fs::write(&version_file, toml::to_string(¤t_time)?)?; | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
fn do_update_check(checked: &mut bool) -> Result<()> { | ||
let latest = get_latest_release()?; | ||
let update_available = is_latest_newer(&latest, PKG_VERSION)?; | ||
|
||
if update_available { | ||
eprintln!( | ||
"There is a newer version of Rover available for download: {} (currently running v{})\n\nFor instructions on how to install the latest version of Rover, see {}", | ||
Cyan.normal().paint(format!("v{}", latest)), | ||
PKG_VERSION, | ||
Cyan.normal().paint("https://go.apollo.dev/r/start") | ||
); | ||
} else { | ||
eprintln!("Rover is up to date!"); | ||
} | ||
|
||
*checked = true; | ||
Ok(()) | ||
} | ||
|
||
fn get_last_checked_time_from_disk(version_file: &PathBuf) -> Option<SystemTime> { | ||
match fs::read_to_string(&version_file) { | ||
Ok(contents) => match toml::from_str(&contents) { | ||
Ok(last_checked_version) => Some(last_checked_version), | ||
Err(_) => { | ||
tracing::debug!("Failed to parse last update check time from version file"); | ||
None | ||
} | ||
}, | ||
Err(_) => { | ||
tracing::debug!("Failed to read version file containing last update check time"); | ||
None | ||
} | ||
} | ||
} | ||
|
||
fn is_latest_newer(latest: &str, running: &str) -> Result<bool> { | ||
let latest = Version::parse(latest)?; | ||
let running = Version::parse(running)?; | ||
Ok(latest > running) | ||
} |