WIP compilation, docker, cargo, etc

This commit is contained in:
tahahawa 2025-06-12 00:48:49 -04:00
parent edf96780e7
commit f5c07acf88
3 changed files with 257 additions and 234 deletions

309
Cargo.lock generated
View File

@ -195,28 +195,6 @@ dependencies = [
"wait-timeout", "wait-timeout",
] ]
[[package]]
name = "async-stream"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476"
dependencies = [
"async-stream-impl",
"futures-core",
"pin-project-lite",
]
[[package]]
name = "async-stream-impl"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.88" version = "0.1.88"
@ -240,53 +218,6 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "axum"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f"
dependencies = [
"async-trait",
"axum-core",
"bytes",
"futures-util",
"http 1.3.1",
"http-body 1.0.1",
"http-body-util",
"itoa",
"matchit",
"memchr",
"mime",
"percent-encoding",
"pin-project-lite",
"rustversion",
"serde",
"sync_wrapper 1.0.2",
"tower 0.5.2",
"tower-layer",
"tower-service",
]
[[package]]
name = "axum-core"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199"
dependencies = [
"async-trait",
"bytes",
"futures-util",
"http 1.3.1",
"http-body 1.0.1",
"http-body-util",
"mime",
"pin-project-lite",
"rustversion",
"sync_wrapper 1.0.2",
"tower-layer",
"tower-service",
]
[[package]] [[package]]
name = "backtrace" name = "backtrace"
version = "0.3.75" version = "0.3.75"
@ -415,26 +346,48 @@ dependencies = [
] ]
[[package]] [[package]]
name = "bon" name = "bollard"
version = "2.3.0" version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97493a391b4b18ee918675fb8663e53646fd09321c58b46afa04e8ce2499c869" checksum = "af706e9dc793491dd382c99c22fde6e9934433d4cc0d6a4b34eb2cdc57a5c917"
dependencies = [ dependencies = [
"bon-macros", "base64 0.22.1",
"rustversion", "bollard-stubs",
"bytes",
"futures-core",
"futures-util",
"hex",
"http 1.3.1",
"http-body-util",
"hyper 1.6.0",
"hyper-named-pipe",
"hyper-util",
"hyperlocal",
"log",
"pin-project-lite",
"serde",
"serde_derive",
"serde_json",
"serde_repr",
"serde_urlencoded",
"thiserror 2.0.12",
"tokio",
"tokio-util",
"tower-service",
"url",
"winapi",
] ]
[[package]] [[package]]
name = "bon-macros" name = "bollard-stubs"
version = "2.3.0" version = "1.48.2-rc.28.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a2af3eac944c12cdf4423eab70d310da0a8e5851a18ffb192c0a5e3f7ae1663" checksum = "79cdf0fccd5341b38ae0be74b74410bdd5eceeea8876dc149a13edfe57e3b259"
dependencies = [ dependencies = [
"darling", "serde",
"ident_case", "serde_json",
"proc-macro2", "serde_repr",
"quote", "serde_with",
"syn",
] ]
[[package]] [[package]]
@ -1104,6 +1057,12 @@ dependencies = [
"windows-sys 0.59.0", "windows-sys 0.59.0",
] ]
[[package]]
name = "current_platform"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a74858bcfe44b22016cb49337d7b6f04618c58e5dbfdef61b06b8c434324a0bc"
[[package]] [[package]]
name = "curve25519-dalek" name = "curve25519-dalek"
version = "4.1.3" version = "4.1.3"
@ -1286,17 +1245,6 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]]
name = "docker_utils"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66a64876aa646872a68ad74a6dba097f35a6641530767cb7c74a74d7a58099f3"
dependencies = [
"bon",
"tokio",
"wait_utils",
]
[[package]] [[package]]
name = "dockerfile_builder" name = "dockerfile_builder"
version = "0.1.5" version = "0.1.5"
@ -2835,10 +2783,12 @@ name = "harmony_composer"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"assert_cmd", "assert_cmd",
"bollard",
"cargo", "cargo",
"clap", "clap",
"docker_utils", "current_platform",
"env_logger", "env_logger",
"futures-util",
"inquire", "inquire",
"log", "log",
"tokio", "tokio",
@ -3171,6 +3121,21 @@ dependencies = [
"tower-service", "tower-service",
] ]
[[package]]
name = "hyper-named-pipe"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278"
dependencies = [
"hex",
"hyper 1.6.0",
"hyper-util",
"pin-project-lite",
"tokio",
"tower-service",
"winapi",
]
[[package]] [[package]]
name = "hyper-rustls" name = "hyper-rustls"
version = "0.27.5" version = "0.27.5"
@ -3252,6 +3217,21 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "hyperlocal"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "986c5ce3b994526b3cd75578e62554abd09f0899d6206de48b3e96ab34ccc8c7"
dependencies = [
"hex",
"http-body-util",
"hyper 1.6.0",
"hyper-util",
"pin-project-lite",
"tokio",
"tower-service",
]
[[package]] [[package]]
name = "iana-time-zone" name = "iana-time-zone"
version = "0.1.63" version = "0.1.63"
@ -3433,6 +3413,7 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"hashbrown 0.12.3", "hashbrown 0.12.3",
"serde",
] ]
[[package]] [[package]]
@ -3443,6 +3424,7 @@ checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown 0.15.3", "hashbrown 0.15.3",
"serde",
] ]
[[package]] [[package]]
@ -3720,7 +3702,7 @@ dependencies = [
"thiserror 2.0.12", "thiserror 2.0.12",
"tokio", "tokio",
"tokio-util", "tokio-util",
"tower 0.5.2", "tower",
"tower-http", "tower-http",
"tracing", "tracing",
] ]
@ -3934,12 +3916,6 @@ dependencies = [
"regex-automata 0.1.10", "regex-automata 0.1.10",
] ]
[[package]]
name = "matchit"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
[[package]] [[package]]
name = "maybe-async" name = "maybe-async"
version = "0.2.10" version = "0.2.10"
@ -4206,7 +4182,7 @@ dependencies = [
"serde_urlencoded", "serde_urlencoded",
"snafu", "snafu",
"tokio", "tokio",
"tower 0.5.2", "tower",
"tower-http", "tower-http",
"tracing", "tracing",
"url", "url",
@ -4783,29 +4759,6 @@ dependencies = [
"parking_lot", "parking_lot",
] ]
[[package]]
name = "prost"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5"
dependencies = [
"bytes",
"prost-derive",
]
[[package]]
name = "prost-derive"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d"
dependencies = [
"anyhow",
"itertools 0.14.0",
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "punycode" name = "punycode"
version = "0.4.1" version = "0.4.1"
@ -5071,7 +5024,7 @@ dependencies = [
"tokio", "tokio",
"tokio-native-tls", "tokio-native-tls",
"tokio-util", "tokio-util",
"tower 0.5.2", "tower",
"tower-service", "tower-service",
"url", "url",
"wasm-bindgen", "wasm-bindgen",
@ -5621,6 +5574,17 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "serde_repr"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "serde_spanned" name = "serde_spanned"
version = "0.6.9" version = "0.6.9"
@ -5654,6 +5618,23 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "serde_with"
version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa"
dependencies = [
"base64 0.22.1",
"chrono",
"hex",
"indexmap 1.9.3",
"indexmap 2.9.0",
"serde",
"serde_derive",
"serde_json",
"time",
]
[[package]] [[package]]
name = "serde_yaml" name = "serde_yaml"
version = "0.9.34+deprecated" version = "0.9.34+deprecated"
@ -6320,69 +6301,6 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
[[package]]
name = "tonic"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52"
dependencies = [
"async-stream",
"async-trait",
"axum",
"base64 0.22.1",
"bytes",
"h2 0.4.10",
"http 1.3.1",
"http-body 1.0.1",
"http-body-util",
"hyper 1.6.0",
"hyper-timeout",
"hyper-util",
"percent-encoding",
"pin-project",
"prost",
"socket2",
"tokio",
"tokio-stream",
"tower 0.4.13",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tonic-health"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1eaf34ddb812120f5c601162d5429933c9b527d901ab0e7f930d3147e33a09b2"
dependencies = [
"async-stream",
"prost",
"tokio",
"tokio-stream",
"tonic",
]
[[package]]
name = "tower"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
dependencies = [
"futures-core",
"futures-util",
"indexmap 1.9.3",
"pin-project",
"pin-project-lite",
"rand 0.8.5",
"slab",
"tokio",
"tokio-util",
"tower-layer",
"tower-service",
"tracing",
]
[[package]] [[package]]
name = "tower" name = "tower"
version = "0.5.2" version = "0.5.2"
@ -6415,7 +6333,7 @@ dependencies = [
"iri-string", "iri-string",
"mime", "mime",
"pin-project-lite", "pin-project-lite",
"tower 0.5.2", "tower",
"tower-layer", "tower-layer",
"tower-service", "tower-service",
"tracing", "tracing",
@ -6712,17 +6630,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "wait_utils"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b85a9ad6d6ec47dbc18c38417377a5dc3de1587fbb2b92a2e33c0ae0c6aea9"
dependencies = [
"tokio",
"tonic",
"tonic-health",
]
[[package]] [[package]]
name = "walkdir" name = "walkdir"
version = "2.5.0" version = "2.5.0"

View File

@ -13,4 +13,6 @@ tokio.workspace = true
env_logger.workspace = true env_logger.workspace = true
log.workspace = true log.workspace = true
cargo = "0.88.0" cargo = "0.88.0"
docker_utils = "0.2.3" bollard = "0.19.0"
current_platform = "0.2.0"
futures-util = "0.3.31"

View File

@ -1,17 +1,28 @@
use bollard::models::ContainerCreateBody;
use bollard::query_parameters::{
AttachContainerOptions, CreateContainerOptionsBuilder, ListContainersOptionsBuilder,
RemoveContainerOptions, StartContainerOptions, WaitContainerOptions,
};
use bollard::secret::HostConfig;
use clap::{Args, Parser, Subcommand};
use futures_util::StreamExt;
use log::info;
use std::collections::HashMap;
use std::path::Path; use std::path::Path;
use std::process::Command; use std::process::Command;
use clap::builder::ArgPredicate;
use clap::{Args, Parser, Subcommand};
use inquire::Confirm;
use log::{debug, info, warn};
#[derive(Parser)] #[derive(Parser)]
#[command(version, about, long_about = None, flatten_help = true, propagate_version = true)] #[command(version, about, long_about = None, flatten_help = true, propagate_version = true)]
struct GlobalArgs { struct GlobalArgs {
#[arg(long, default_value = "harmony")] #[arg(long, default_value = "harmony")]
harmony_path: String, harmony_path: String,
#[arg(long)]
compile_method: Option<CompileMethod>,
#[arg(long)]
compile_platform: Option<String>,
#[command(subcommand)] #[command(subcommand)]
command: Option<Commands>, command: Option<Commands>,
} }
@ -60,7 +71,8 @@ struct AllArgs {
deploy: DeployArgs, deploy: DeployArgs,
} }
fn main() { #[tokio::main]
async fn main() {
env_logger::init(); env_logger::init();
let cli_args = GlobalArgs::parse(); let cli_args = GlobalArgs::parse();
@ -69,28 +81,36 @@ fn main() {
.expect("couldn't check if path exists"); .expect("couldn't check if path exists");
match harmony_path { match harmony_path {
true => compile_harmony(cli_args.harmony_path.clone()), true => compile_harmony(cli_args.compile_method, None, cli_args.harmony_path.clone()).await,
false => todo!("implement autodetect code"), false => todo!("implement autodetect code"),
} }
match cli_args.command { match cli_args.command {
Some(command) => match command { Some(command) => match command {
Commands::Check(args) => { Commands::Check(args) => {
let check_script = match Path::new(&format!( let check_script_str =
"{}/{}", format!("{}/{}", cli_args.harmony_path, args.check_script_path);
cli_args.harmony_path, args.check_script_path
)) let check_script = Path::new(&check_script_str);
match check_script
.try_exists() .try_exists()
.expect("couldn't check if path exists")
{ {
Ok(path) => path, true => (),
Err(_) => todo!("implement logic when couldn't find check script"), false => todo!("implement couldn't find path logic"),
}; };
let check_output = Command::new("sh") let check_output = Command::new("sh")
.arg("-c") .arg("-c")
.arg(check_script.to_string()) .arg(check_script)
.output() .output()
.expect("failed to run check script"); .expect("failed to run check script");
info!(
"check stdout: {}, check stderr: {}",
String::from_utf8(check_output.stdout).expect("couldn't parse from utf8"),
String::from_utf8(check_output.stderr).expect("couldn't parse from utf8")
);
} }
Commands::Package(args) => { Commands::Package(args) => {
if args.publish { if args.publish {
@ -108,7 +128,7 @@ fn main() {
} }
todo!("implement deployment logic"); todo!("implement deployment logic");
} }
Commands::All(args) => todo!( Commands::All(_args) => todo!(
"take all previous match arms and turn them into separate functions, and call them all one after the other" "take all previous match arms and turn them into separate functions, and call them all one after the other"
), ),
}, },
@ -116,11 +136,45 @@ fn main() {
} }
} }
fn compile_harmony(harmony_location: String) { #[derive(Clone, Debug, clap::ValueEnum)]
enum CompileMethod {
LocalCargo,
Docker,
}
async fn compile_harmony(
method: Option<CompileMethod>,
platform: Option<String>,
harmony_location: String,
) {
let platform = match platform {
Some(p) => p,
None => current_platform::CURRENT_PLATFORM.to_string(),
};
let gctx = cargo::util::context::GlobalContext::default().unwrap(); let gctx = cargo::util::context::GlobalContext::default().unwrap();
let cargo_exists = gctx.cargo_exe().unwrap().exists(); let cargo_exists = gctx.cargo_exe().unwrap().exists();
let method = match method {
Some(m) => m,
None => {
if cargo_exists { if cargo_exists {
compile_cargo(gctx, harmony_location).await;
return;
} else {
compile_docker(platform, harmony_location).await;
return;
}
}
};
match method {
CompileMethod::LocalCargo => compile_cargo(gctx, harmony_location).await,
CompileMethod::Docker => compile_docker(platform, harmony_location).await,
};
}
async fn compile_cargo(gctx: cargo::util::context::GlobalContext, harmony_location: String) {
let _cargo_build = cargo::ops::compile( let _cargo_build = cargo::ops::compile(
&cargo::core::Workspace::new( &cargo::core::Workspace::new(
&Path::new(&format!("{}/Cargo.toml", harmony_location)) &Path::new(&format!("{}/Cargo.toml", harmony_location))
@ -129,14 +183,74 @@ fn compile_harmony(harmony_location: String) {
&gctx, &gctx,
) )
.unwrap(), .unwrap(),
&cargo::ops::CompileOptions::new(&gctx, cargo::core::compiler::CompileMode::Build) &cargo::ops::CompileOptions::new(&gctx, cargo::core::compiler::CompileMode::Build).unwrap(),
.unwrap(),
) )
.expect("build didn't go successfully"); .expect("build didn't go successfully");
return; return;
}
async fn compile_docker(platform: String, harmony_location: String) {
let docker_client =
bollard::Docker::connect_with_local_defaults().expect("couldn't connect to docker");
let mut filters = HashMap::new();
filters.insert(String::from("name"), vec![String::from("harmony_build")]);
let list_containers_options = ListContainersOptionsBuilder::new()
.all(true)
.filters(&filters)
.build();
let containers = &docker_client
.list_containers(Some(list_containers_options))
.await
.expect("list containers failed");
if containers.len() > 0 {
docker_client
.remove_container("harmony_build", None::<RemoveContainerOptions>)
.await
.expect("failed to remove container");
} }
let _docker_util = docker_utils::DockerUtil::new().expect("Failed to create DockerUtil"); let options = Some(
CreateContainerOptionsBuilder::new()
.name("harmony_build")
.build(),
);
todo!("implement docker build container"); let config = ContainerCreateBody {
image: Some("docker.io/rust:1.87.0".to_string()),
working_dir: Some("/mnt".to_string()),
entrypoint: Some(vec![
"cargo".to_string(),
"build".to_string(),
format!("--target={}", platform),
"--release".to_string(),
]),
host_config: Some(HostConfig {
binds: Some(vec![format!("{}:/mnt", harmony_location)]),
..Default::default()
}),
..Default::default()
};
docker_client
.create_container(options, config)
.await
.expect("couldn't create container");
docker_client
.start_container("harmony_build", None::<StartContainerOptions>)
.await
.expect("couldn't start container");
let wait_options = WaitContainerOptions {
condition: "not-running".to_string(),
};
let mut wait = docker_client
.wait_container("harmony_build", Some(wait_options))
.boxed();
// wait until container is no longer running
while let Some(_) = wait.next().await {}
} }