diff --git a/src/commands/system/deploy.rs b/src/commands/system/deploy.rs deleted file mode 100644 index b5d1bdb..0000000 --- a/src/commands/system/deploy.rs +++ /dev/null @@ -1,354 +0,0 @@ -use crate::client::Client; -use crate::client::ClientEvent; -use crate::client::Player; -use crate::commands::Command; -use crate::commands::argument::{ArgumentSpec, ParsedArguments}; - -use async_trait::async_trait; -use std::io::{BufRead, BufReader, Read}; -use std::process::{Child, Command as SysCommand, Stdio}; -use std::process::{ChildStderr, ChildStdout}; -use std::sync::Arc; -use tokio::sync::Mutex; -use tokio::task; - -pub struct DeployCommand { - running: Arc>>, -} - -impl DeployCommand { - pub fn new() -> Self { - DeployCommand { - running: Arc::new(Mutex::new(None)), - } - } -} - -#[async_trait] -impl Command for DeployCommand { - fn name(&self) -> &'static str { - "deploy" - } - fn aliases(&self) -> &[&'static str] { - &["redeploy", "update"] - } - fn category(&self) -> &'static str { - "system" - } - fn description(&self) -> &'static str { - "Pulls, builds, and restarts copper via systemctl." - } - fn argument_spec(&self) -> &'static [ArgumentSpec] { - &[] - } - async fn constructed(&mut self, _: Client) {} - async fn event(&mut self, _: Client, _: ClientEvent) {} - - async fn execute(&mut self, client: Client, player: Player, _args: ParsedArguments) { - let admin_id = "3bff3f33e6dc0410fdc61d13"; - if player._id != admin_id { - client.message("You are not authorized to deploy.").await; - return; - } - - client.message("Starting deploy sequence...").await; - - client.message("Running `git pull`...").await; - let git_pull = SysCommand::new("git") - .arg("pull") - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn(); - - match git_pull { - Ok(mut child) => { - let stdout = child.stdout.take().unwrap(); - let stderr = child.stderr.take().unwrap(); - let mut reader = BufReader::new(stdout); - let mut err_reader = BufReader::new(stderr); - - let mut output = String::new(); - let mut err_output = String::new(); - - reader.read_to_string(&mut output).unwrap_or(0); - err_reader.read_to_string(&mut err_output).unwrap_or(0); - - client - .message(format!("git pull output:\n{}", output)) - .await; - if !err_output.is_empty() { - client - .message(format!("git pull error:\n{}", err_output)) - .await; - } - - let status = child.wait().unwrap(); - if !status.success() { - client.message("git pull failed. Aborting.").await; - return; - } - } - Err(e) => { - client - .message(format!("Failed to run git pull: {}", e)) - .await; - return; - } - } - - client.message("Running `cargo run --release`...").await; - - let client_clone = client.clone(); - let client_clone2 = client.clone(); - let found_connected = Arc::new(Mutex::new(false)); - let found_connected_cargo = found_connected.clone(); - - // Spawn cargo run --release in a separate blocking task - let running_arc = self.running.clone(); - let cargo_task = task::spawn_blocking(async move || { - let mut cargo_child = match SysCommand::new("cargo") - .arg("run") - .arg("--release") - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn() - { - Ok(child) => child, - Err(e) => { - let _ = client_clone.message(format!("Failed to start cargo run: {}", e)); - return; - } - }; - let cargo_stdout: ChildStdout; - let cargo_stderr: ChildStderr; - // Save the child handle for later killing - { - let mut running = running_arc.blocking_lock(); - cargo_stdout = cargo_child.stdout.take().unwrap(); - cargo_stderr = cargo_child.stderr.take().unwrap(); - *running = Some(cargo_child); - } - - // stdout handler - let client_clone_stdout = client_clone.clone(); - let found_connected_cargo_stdout = found_connected_cargo.clone(); - let stdout_handle = std::thread::spawn(async move || { - let reader = BufReader::new(cargo_stdout); - for line in reader.lines() { - match line { - Ok(l) => { - let msg = format!("cargo: {}", l); - let _ = client_clone_stdout.message(msg).await; - if l.contains("[CONNECTED]") { - let mut found = found_connected_cargo_stdout.blocking_lock(); - *found = true; - break; - } - } - Err(_) => break, - } - } - }); - - // stderr handler - let client_clone_stderr = client_clone2.clone(); - let stderr_handle = std::thread::spawn(move || { - let reader = BufReader::new(cargo_stderr); - for line in reader.lines() { - match line { - Ok(l) => { - let msg = format!("cargo stderr: {}", l); - let _ = client_clone_stderr.message(msg); - } - Err(_) => break, - } - } - }); - - let _ = stdout_handle.join(); - let _ = stderr_handle.join(); - - //let _ = cargo_child.wait(); - }); - - // Wait for [CONNECTED] from cargo run --release - loop { - { - let found = found_connected.lock().await; - if *found { - break; - } - } - tokio::time::sleep(std::time::Duration::from_millis(100)).await; - } - - client - .message( - "Detected [CONNECTED] from cargo run --release. Proceeding to systemctl restart.", - ) - .await; - - client.message("Running `systemctl daemon-reload`...").await; - let daemon_reload = SysCommand::new("systemctl") - .arg("daemon-reload") - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn(); - - match daemon_reload { - Ok(mut child) => { - let stdout = child.stdout.take().unwrap(); - let stderr = child.stderr.take().unwrap(); - let mut reader = BufReader::new(stdout); - let mut err_reader = BufReader::new(stderr); - - let mut output = String::new(); - let mut err_output = String::new(); - - reader.read_to_string(&mut output).unwrap_or(0); - err_reader.read_to_string(&mut err_output).unwrap_or(0); - - client - .message(format!("daemon-reload output:\n{}", output)) - .await; - if !err_output.is_empty() { - client - .message(format!("daemon-reload error:\n{}", err_output)) - .await; - } - - let status = child.wait().unwrap(); - if !status.success() { - client - .message("systemctl daemon-reload failed. Aborting.") - .await; - return; - } - } - Err(e) => { - client - .message(format!("Failed to run systemctl daemon-reload: {}", e)) - .await; - return; - } - } - - client - .message("Running `systemctl restart copper`...") - .await; - let restart_copper = SysCommand::new("systemctl") - .arg("restart") - .arg("copper") - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn(); - - match restart_copper { - Ok(mut child) => { - let stdout = child.stdout.take().unwrap(); - let stderr = child.stderr.take().unwrap(); - let mut reader = BufReader::new(stdout); - let mut err_reader = BufReader::new(stderr); - - let mut output = String::new(); - let mut err_output = String::new(); - - reader.read_to_string(&mut output).unwrap_or(0); - err_reader.read_to_string(&mut err_output).unwrap_or(0); - - client - .message(format!("restart copper output:\n{}", output)) - .await; - if !err_output.is_empty() { - client - .message(format!("restart copper error:\n{}", err_output)) - .await; - } - - let status = child.wait().unwrap(); - if !status.success() { - client - .message("systemctl restart copper failed. Aborting.") - .await; - return; - } - } - Err(e) => { - client - .message(format!("Failed to run systemctl restart copper: {}", e)) - .await; - return; - } - } - - // Step 5: Wait for [CONNECTED] from systemctl copper - client - .message("Waiting for [CONNECTED] from systemctl copper...") - .await; - let copper_status = SysCommand::new("journalctl") - .arg("-u") - .arg("copper") - .arg("-n") - .arg("50") - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn(); - - match copper_status { - Ok(mut child) => { - let stdout = child.stdout.take().unwrap(); - let reader = BufReader::new(stdout); - - let mut found = false; - for line in reader.lines() { - match line { - Ok(l) => { - let msg = format!("copper log: {}", l); - client.message(msg.clone()).await; - if l.contains("[CONNECTED]") { - found = true; - break; - } - } - Err(_) => break, - } - } - if found { - client - .message("Detected [CONNECTED] from systemctl copper.") - .await; - } else { - client - .message("Did not detect [CONNECTED] from systemctl copper.") - .await; - } - let _ = child.wait(); - } - Err(e) => { - client - .message(format!("Failed to read copper logs: {}", e)) - .await; - } - } - - // Step 6: Kill cargo run --release - client.message("Killing cargo run --release...").await; - let mut running = self.running.lock().await; - if let Some(child) = running.as_mut() { - match child.kill() { - Ok(_) => { - client.message("cargo run --release killed.").await; - } - Err(e) => { - client - .message(format!("Failed to kill cargo run: {}", e)) - .await; - } - } - } else { - client.message("No running cargo process found.").await; - } - - client.message("Deploy sequence complete.").await; - } -} diff --git a/src/commands/system/mod.rs b/src/commands/system/mod.rs index 7f1f6cb..661db96 100644 --- a/src/commands/system/mod.rs +++ b/src/commands/system/mod.rs @@ -1,3 +1,3 @@ use crate::submods; -submods!(follow, help, launch, test, translate, about, deploy); +submods!(follow, help, launch, test, translate, about); diff --git a/src/main.rs b/src/main.rs index d10169e..00989a6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -93,7 +93,6 @@ async fn main() -> Result<(), Box> { LaunchCommand, FollowCommand::new(), TestCommand::new(), - DeployCommand::new(), BalanceCommand::new(arc_pool.clone()), InventoryCommand::new(arc_pool.clone()), FishCommand::new(arc_pool.clone()),