Skip to content

Commit 43d5bee

Browse files
fix: implement dynamic version fetching for RAPID_LATEST_VERSION
1 parent b705720 commit 43d5bee

2 files changed

Lines changed: 63 additions & 4 deletions

File tree

crates/rapid-cli/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@ regex = "1.9.3"
2727
log = "0.4.19"
2828
pretty_env_logger = "0.5.0"
2929
requestty = "0.5.0"
30+
reqwest = { version = "0.11", features = ["blocking", "json"] }
3031
rust-embed = "6.4.2"
3132
serde = { version = "1.0", features = ["derive"] }
33+
serde_json = "1.0"
3234
spinach = "2.1.0"
3335
strum = "0.24.1"
3436
strum_macros = "0.24.3"

crates/rapid-cli/src/cli.rs

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,50 @@ use crate::{
44
};
55
use clap::{command, crate_version, ArgMatches, Command};
66
use colorful::Colorful;
7+
use reqwest::blocking::Client;
8+
use serde_json::Value;
79
use std::{
810
env::{current_dir, current_exe},
911
path::PathBuf,
1012
process::exit,
13+
sync::OnceLock,
14+
time::Duration,
1115
};
1216

1317
pub type App = Command;
1418

15-
// This should 100% pull from a GCP storage bucket or something that gets updataed in CI when we trigger releases
16-
// TODO: eventually, we should use this to tell the user that they need to update their CLI version
17-
// (we could detect this by comparing this value with the crate_version!() macro value)
18-
pub const RAPID_LATEST_VERSION: &str = "v0.4.3";
19+
// Fetch the latest version from GitHub API
20+
static LATEST_VERSION: OnceLock<String> = OnceLock::new();
21+
22+
/// Fetches the latest version from GitHub API
23+
/// Falls back to a default version if the API request fails
24+
fn fetch_latest_version() -> String {
25+
let client = Client::new();
26+
27+
// Try to fetch from GitHub API
28+
let result = client
29+
.get("https://api.github.com/repos/DarrenBaldwin07/rapid/releases/latest")
30+
.timeout(Duration::from_secs(2))
31+
.header("User-Agent", format!("rapid-cli/{}", crate_version!()))
32+
.send()
33+
.and_then(|res| res.json::<Value>())
34+
.ok();
35+
36+
if let Some(json) = result {
37+
if let Some(tag_name) = json["tag_name"].as_str() {
38+
return tag_name.to_string();
39+
}
40+
}
41+
42+
// Fall back to hardcoded version if API call fails
43+
"v0.6.0".to_string()
44+
}
45+
46+
/// Get the latest Rapid version
47+
/// Uses a static OnceLock to ensure we only fetch it once per CLI execution
48+
pub fn rapid_latest_version() -> &'static str {
49+
LATEST_VERSION.get_or_init(fetch_latest_version).as_str()
50+
}
1951

2052
/// Returns what the current working directory of the user is
2153
pub fn current_directory() -> PathBuf {
@@ -92,9 +124,34 @@ impl RapidCLI {
92124
exit(64);
93125
}
94126

127+
// Check if there's a newer version available
128+
self.check_for_updates();
129+
95130
// This outputs only when a command succeeds (would be cool to capture analytics here at some point)
96131
Ok(())
97132
}
133+
134+
fn check_for_updates(&self) {
135+
let current_version = crate_version!();
136+
let latest_version = rapid_latest_version();
137+
138+
// Remove 'v' prefix from latest_version for comparison if it exists
139+
let latest_version_str = if latest_version.starts_with('v') {
140+
&latest_version[1..]
141+
} else {
142+
latest_version
143+
};
144+
145+
if latest_version_str != current_version {
146+
println!(
147+
"\n{} A new version of Rapid is available: {} (you have {})",
148+
"⚠️".yellow(),
149+
latest_version.green().bold(),
150+
current_version.yellow()
151+
);
152+
println!(" Run 'cargo install rapid-cli@{}' to update", latest_version_str);
153+
}
154+
}
98155
}
99156

100157
// TODO: update this to actually be a legit health template

0 commit comments

Comments
 (0)