From 99e9aad6879a90477833429be99184f047b5f864 Mon Sep 17 00:00:00 2001 From: tahahawa Date: Fri, 13 Jun 2025 00:25:23 -0400 Subject: [PATCH] deploy and docker logs works ??? --- Cargo.lock | 1 + harmony_composer/Cargo.toml | 1 + harmony_composer/src/main.rs | 134 ++++++++++++++++++++++++++--------- 3 files changed, 103 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 34c8441..15fa2e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2791,6 +2791,7 @@ dependencies = [ "futures-util", "inquire", "log", + "serde_json", "tokio", ] diff --git a/harmony_composer/Cargo.toml b/harmony_composer/Cargo.toml index 9554e96..c2dd2ce 100644 --- a/harmony_composer/Cargo.toml +++ b/harmony_composer/Cargo.toml @@ -16,3 +16,4 @@ cargo = "0.88.0" bollard = "0.19.0" current_platform = "0.2.0" futures-util = "0.3.31" +serde_json = "1.0.140" diff --git a/harmony_composer/src/main.rs b/harmony_composer/src/main.rs index 910d4f3..3a4418f 100644 --- a/harmony_composer/src/main.rs +++ b/harmony_composer/src/main.rs @@ -1,15 +1,17 @@ use bollard::models::ContainerCreateBody; use bollard::query_parameters::{ - CreateContainerOptionsBuilder, ListContainersOptionsBuilder, RemoveContainerOptions, - StartContainerOptions, WaitContainerOptions, + CreateContainerOptionsBuilder, ListContainersOptionsBuilder, LogsOptions, + RemoveContainerOptions, StartContainerOptions, WaitContainerOptions, }; use bollard::secret::HostConfig; use clap::{Args, Parser, Subcommand}; -use futures_util::StreamExt; +use futures_util::{StreamExt, TryStreamExt}; use log::info; use std::collections::HashMap; -use std::path::Path; +use std::fmt::format; +use std::path::{Path, PathBuf}; use std::process::Command; +use tokio::fs; #[derive(Parser)] #[command(version, about, long_about = None, flatten_help = true, propagate_version = true)] @@ -30,7 +32,6 @@ struct GlobalArgs { #[derive(Subcommand, Clone, Debug)] enum Commands { Check(CheckArgs), - Package(PackageArgs), Deploy(DeployArgs), All(AllArgs), } @@ -41,12 +42,6 @@ struct CheckArgs { check_script_path: String, } -#[derive(Args, Clone, Debug)] -struct PackageArgs { - #[arg(long, default_value_t = false)] - publish: bool, -} - #[derive(Args, Clone, Debug)] struct DeployArgs { #[arg(long, default_value_t = false)] @@ -64,9 +59,6 @@ struct AllArgs { #[command(flatten)] check: CheckArgs, - #[command(flatten)] - package: PackageArgs, - #[command(flatten)] deploy: DeployArgs, } @@ -80,8 +72,12 @@ async fn main() { .try_exists() .expect("couldn't check if path exists"); + let harmony_bin_path: PathBuf; match harmony_path { - true => compile_harmony(cli_args.compile_method, None, cli_args.harmony_path.clone()).await, + true => { + harmony_bin_path = + compile_harmony(cli_args.compile_method, None, cli_args.harmony_path.clone()).await + } false => todo!("implement autodetect code"), } @@ -112,12 +108,6 @@ async fn main() { String::from_utf8(check_output.stderr).expect("couldn't parse from utf8") ); } - Commands::Package(args) => { - if args.publish { - todo!("implement publish logic"); - } - todo!("implement packaging logic"); - } Commands::Deploy(args) => { if args.staging { todo!("implement staging deployment"); @@ -126,7 +116,15 @@ async fn main() { if args.prod { todo!("implement prod deployment"); } - todo!("implement deployment logic"); + let deploy_output = Command::new(harmony_bin_path) + .arg("-y") + .arg("-a") + .output() + .expect("failed to run harmony deploy"); + println!( + "deploy output: {}", + String::from_utf8(deploy_output.stdout).expect("couldn't parse from utf8") + ); } Commands::All(_args) => todo!( "take all previous match arms and turn them into separate functions, and call them all one after the other" @@ -146,7 +144,7 @@ async fn compile_harmony( method: Option, platform: Option, harmony_location: String, -) { +) -> PathBuf { let platform = match platform { Some(p) => p, None => current_platform::CURRENT_PLATFORM.to_string(), @@ -159,23 +157,24 @@ async fn compile_harmony( Some(m) => m, None => { if cargo_exists { - compile_cargo(gctx, harmony_location).await; - return; + return compile_cargo(gctx, harmony_location).await; } else { - compile_docker(platform, harmony_location).await; - return; + return compile_docker(platform, harmony_location).await; } } }; match method { - CompileMethod::LocalCargo => compile_cargo(gctx, harmony_location).await, - CompileMethod::Docker => compile_docker(platform, harmony_location).await, + CompileMethod::LocalCargo => return compile_cargo(gctx, harmony_location).await, + CompileMethod::Docker => return compile_docker(platform, harmony_location).await, }; } -async fn compile_cargo(gctx: cargo::util::context::GlobalContext, harmony_location: String) { - let _cargo_build = cargo::ops::compile( +async fn compile_cargo( + gctx: cargo::util::context::GlobalContext, + harmony_location: String, +) -> PathBuf { + let cargo_build = cargo::ops::compile( &cargo::core::Workspace::new( &Path::new(&format!("{}/Cargo.toml", harmony_location)) .canonicalize() @@ -186,10 +185,24 @@ async fn compile_cargo(gctx: cargo::util::context::GlobalContext, harmony_locati &cargo::ops::CompileOptions::new(&gctx, cargo::core::compiler::CompileMode::Build).unwrap(), ) .expect("build didn't go successfully"); - return; + + let bin = cargo_build.binaries.first().expect("no binaries built"); + let bin_out; + if let Some(ext) = bin.path.extension() { + bin_out = PathBuf::from(format!( + "{}/harmony.{}", + harmony_location, + ext.to_str().expect("couldn't convert OsStr to str") + )); + let _copy_res = fs::copy(bin.path.clone(), bin_out.clone()).await; + } else { + bin_out = PathBuf::from(format!("{}/harmony", harmony_location)); + let _copy_res = fs::copy(bin.path.clone(), bin_out.clone()).await; + } + return bin_out; } -async fn compile_docker(platform: String, harmony_location: String) { +async fn compile_docker(platform: String, harmony_location: String) -> PathBuf { let docker_client = bollard::Docker::connect_with_local_defaults().expect("couldn't connect to docker"); @@ -226,6 +239,7 @@ async fn compile_docker(platform: String, harmony_location: String) { "build".to_string(), format!("--target={}", platform), "--release".to_string(), + "--message-format=json".to_string(), ]), host_config: Some(HostConfig { binds: Some(vec![format!("{}:/mnt", harmony_location)]), @@ -251,6 +265,60 @@ async fn compile_docker(platform: String, harmony_location: String) { .wait_container("harmony_build", Some(wait_options)) .boxed(); + let mut logs_stream = docker_client.logs( + "harmony_build", + Some(LogsOptions { + follow: true, + stdout: true, + stderr: true, + tail: "all".to_string(), + ..Default::default() + }), + ); + + let mut bin_out = PathBuf::from(format!("{}/harmony", harmony_location)); + + while let Some(l) = logs_stream.next().await { + let l_str = l.expect("couldn't unwrap logoutput").to_string(); + println!("{}", l_str); + + let l_json: Option = + serde_json::from_str(l_str.as_str()).unwrap_or(None); + + match l_json { + Some(j) => match j.get("manifest_path") { + Some(p) => { + if p == "/mnt/Cargo.toml" { + let bin = PathBuf::from(format!( + "{}/{}", + harmony_location, + j.get("executable") + .expect("couldn't get json executable") + .as_str() + .expect("couldn't get json executable as str") + .replacen("/mnt/", "", 1) + )); + if let Some(ext) = bin.extension() { + bin_out = PathBuf::from(format!( + "{}/harmony.{}", + harmony_location, + ext.to_str().expect("couldn't convert OsStr to str") + )); + let _copy_res = fs::copy(bin.clone(), bin_out.clone()).await; + } else { + bin_out = PathBuf::from(format!("{}/harmony", harmony_location)); + let _copy_res = fs::copy(bin.clone(), bin_out.clone()).await; + } + } + } + None => (), + }, + None => (), + }; + } + // wait until container is no longer running while let Some(_) = wait.next().await {} + + return bin_out; }