feat: add update command to CLI, relay, and client
This commit is contained in:
parent
835d20f734
commit
6345209538
9 changed files with 302 additions and 0 deletions
|
|
@ -11,6 +11,8 @@ use tokio_tungstenite::{connect_async_tls_with_config, tungstenite::Message, Con
|
|||
|
||||
use base64::Engine;
|
||||
use helios_common::{ClientMessage, ServerMessage};
|
||||
#[allow(unused_imports)]
|
||||
use reqwest;
|
||||
use helios_common::protocol::{is_valid_label, sanitize_label};
|
||||
|
||||
mod display;
|
||||
|
|
@ -661,6 +663,65 @@ async fn handle_message(
|
|||
}
|
||||
}
|
||||
|
||||
ServerMessage::UpdateRequest { request_id } => {
|
||||
display::cmd_start("🔄", "update", "downloading...");
|
||||
let exe = std::env::current_exe().ok();
|
||||
tokio::spawn(async move {
|
||||
// Give the response time to be sent before we restart
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(800)).await;
|
||||
let exe = match exe {
|
||||
Some(p) => p,
|
||||
None => {
|
||||
display::err("❌", "update: could not determine current exe path");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let url = "https://agent-helios.me/downloads/helios-remote/helios-remote-client-windows.exe";
|
||||
let bytes = match reqwest::get(url).await {
|
||||
Ok(r) => match r.bytes().await {
|
||||
Ok(b) => b,
|
||||
Err(e) => {
|
||||
display::err("❌", &format!("update: read body failed: {e}"));
|
||||
return;
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
display::err("❌", &format!("update: download failed: {e}"));
|
||||
return;
|
||||
}
|
||||
};
|
||||
// Write new binary to a temp path, then swap
|
||||
let tmp = exe.with_extension("update.exe");
|
||||
if let Err(e) = std::fs::write(&tmp, &bytes) {
|
||||
display::err("❌", &format!("update: write failed: {e}"));
|
||||
return;
|
||||
}
|
||||
// Rename current → .old, then tmp → current
|
||||
let old = exe.with_extension("old.exe");
|
||||
let _ = std::fs::remove_file(&old);
|
||||
if let Err(e) = std::fs::rename(&exe, &old) {
|
||||
display::err("❌", &format!("update: rename old failed: {e}"));
|
||||
return;
|
||||
}
|
||||
if let Err(e) = std::fs::rename(&tmp, &exe) {
|
||||
// Attempt rollback
|
||||
let _ = std::fs::rename(&old, &exe);
|
||||
display::err("❌", &format!("update: rename new failed: {e}"));
|
||||
return;
|
||||
}
|
||||
display::cmd_done("🔄", "update", "", true, "updated — restarting");
|
||||
// Restart
|
||||
let _ = std::process::Command::new(&exe).spawn();
|
||||
std::process::exit(0);
|
||||
});
|
||||
display::cmd_done("🔄", "update", "", true, "triggered");
|
||||
ClientMessage::UpdateResponse {
|
||||
request_id,
|
||||
success: true,
|
||||
message: "update triggered, client restarting...".into(),
|
||||
}
|
||||
}
|
||||
|
||||
ServerMessage::Ack { request_id } => {
|
||||
ClientMessage::Ack { request_id }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue