Skip to content

Commit 6be9a43

Browse files
feat(l1): periodically check if there is a newer release available (#5322)
**Motivation** Periodically checking and informing the user if there is a newer version of ethrex available <!-- Why does this pull request exist? What are its goals? --> **Description** * Periodically query the latest relese of ethrex on GitHub and check against current running version, inform the user via log if there is a newer version available. <!-- A clear and concise general description of the changes this PR introduces --> <!-- Link to issues: Resolves #111, Resolves #222 --> --------- Co-authored-by: Tomás Grüner <47506558+MegaRedHand@users.noreply.github.com>
1 parent e08d7e4 commit 6be9a43

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

cmd/ethrex/ethrex.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@ use ethrex::{
55
utils::{NodeConfigFile, get_client_version, store_node_config_file},
66
};
77
use ethrex_p2p::{discv4::peer_table::PeerTable, types::NodeRecord};
8+
use serde::Deserialize;
89
use std::{path::Path, time::Duration};
910
use tokio::signal::unix::{SignalKind, signal};
1011
use tokio_util::sync::CancellationToken;
1112
use tracing::info;
1213

14+
const LATEST_VERSION_URL: &str = "https://api.github.com/repos/lambdaclass/ethrex/releases/latest";
15+
1316
#[cfg(all(feature = "jemalloc", not(target_env = "msvc")))]
1417
#[global_allocator]
1518
static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
@@ -45,6 +48,80 @@ async fn server_shutdown(
4548
info!("Server shutting down!");
4649
}
4750

51+
/// Fetches the latest release version on github
52+
/// Returns None if there was an error when requesting the latest version
53+
async fn latest_release_version() -> Option<String> {
54+
#[derive(Deserialize)]
55+
struct Release {
56+
tag_name: String,
57+
}
58+
let client = reqwest::Client::new();
59+
let response = client
60+
.get(LATEST_VERSION_URL)
61+
.header("User-Agent", "ethrex")
62+
.send()
63+
.await
64+
.ok()?;
65+
if !response.status().is_success() {
66+
None
67+
} else {
68+
Some(
69+
response
70+
.json::<Release>()
71+
.await
72+
.ok()?
73+
.tag_name
74+
.trim_start_matches("v")
75+
.to_string(),
76+
)
77+
}
78+
}
79+
80+
/// Reads current crate version
81+
fn current_version() -> &'static str {
82+
env!("CARGO_PKG_VERSION")
83+
}
84+
85+
/// Returns true if the received latest version is higher than the current ethrex version
86+
fn is_higher_than_current(latest_version: &str) -> bool {
87+
let current_version_numbers = current_version()
88+
.split(".")
89+
.map(|c| c.parse::<u64>().unwrap_or_default());
90+
let latest_version_numbers = latest_version
91+
.split(".")
92+
.map(|c| c.parse::<u64>().unwrap_or_default());
93+
for (current, latest) in current_version_numbers.zip(latest_version_numbers) {
94+
match current.cmp(&latest) {
95+
std::cmp::Ordering::Less => return true,
96+
std::cmp::Ordering::Equal => {}
97+
std::cmp::Ordering::Greater => return false,
98+
};
99+
}
100+
false
101+
}
102+
103+
/// Checks if the latest released version is higher than the current version and emits an info log
104+
/// Won't emit a log line if the current version is newer or equal, or if there was a problem reading either version
105+
async fn check_version_update() {
106+
if let Some(latest_version) = latest_release_version().await
107+
&& is_higher_than_current(&latest_version)
108+
{
109+
info!(
110+
"There is a newer ethrex version available, current version: {} vs latest version: {latest_version}",
111+
current_version()
112+
);
113+
}
114+
}
115+
116+
/// Checks if there is a newer ethrex verison available every hour
117+
async fn periodically_check_version_update() {
118+
let mut interval = tokio::time::interval(Duration::from_secs(60 * 60));
119+
loop {
120+
interval.tick().await;
121+
check_version_update().await;
122+
}
123+
}
124+
48125
#[tokio::main]
49126
async fn main() -> eyre::Result<()> {
50127
let CLI { opts, command } = CLI::parse();
@@ -61,6 +138,7 @@ async fn main() -> eyre::Result<()> {
61138
let log_filter_handler = init_tracing(&opts);
62139

63140
info!("ethrex version: {}", get_client_version());
141+
tokio::spawn(periodically_check_version_update());
64142

65143
let (datadir, cancel_token, peer_table, local_node_record) =
66144
init_l1(opts, Some(log_filter_handler)).await?;

0 commit comments

Comments
 (0)