diff --git a/Cargo.lock b/Cargo.lock index d19cf6f..838f373 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -261,6 +261,7 @@ dependencies = [ "clap", "color-eyre", "dagger-sdk", + "dotenv", "eyre", "futures", "tokio", diff --git a/ci/Cargo.toml b/ci/Cargo.toml index 8ed23a8..52e906e 100644 --- a/ci/Cargo.toml +++ b/ci/Cargo.toml @@ -13,3 +13,4 @@ tokio = "1" clap = {version = "4", features = ["derive"]} futures = "0.3.28" async-scoped = { version = "0.7.1", features = ["tokio", "use-tokio"] } +dotenv.workspace = true diff --git a/ci/src/main.rs b/ci/src/main.rs index f308556..70db67d 100644 --- a/ci/src/main.rs +++ b/ci/src/main.rs @@ -2,19 +2,21 @@ use std::path::Path; use std::path::PathBuf; use std::sync::Arc; - +use build::build_and_deploy; use clap::Args; use clap::Parser; use clap::Subcommand; use clap::ValueEnum; - - +use dagger_sdk::ContainerId; +use dagger_sdk::ContainerPublishOpts; use dagger_sdk::Platform; use dagger_sdk::QueryContainerOpts; use futures::StreamExt; +use tokio::sync::Mutex; +use tokio::task::JoinHandle; - +use crate::please_release::run_release_please; #[derive(Parser, Clone)] #[command(author, version, about, long_about = None, subcommand_required = true)] @@ -101,6 +103,7 @@ pub struct GlobalArgs { #[tokio::main] async fn main() -> eyre::Result<()> { + let _ = dotenv::dotenv(); let _ = color_eyre::install(); let client = dagger_sdk::connect().await?; @@ -113,23 +116,34 @@ async fn main() -> eyre::Result<()> { profile: _, bin_name, } => { - let base_image = - base_rust_image(client.clone(), &cli.global, &None, &bin_name.clone()).await?; + let base_image = base_rust_image( + client.clone(), + &cli.global, + &None, + &bin_name.clone(), + &"release".into(), + ) + .await?; let prod_image = get_base_debian_image(client.clone(), &cli.global, None).await?; build::execute( client, &cli.global, &base_image, &prod_image, - bin_name, + &bin_name, &None, ) .await?; } LocalCommands::Test => { - let base_image = - base_rust_image(client.clone(), &cli.global, &None, &"cuddle-please".into()) - .await?; + let base_image = base_rust_image( + client.clone(), + &cli.global, + &None, + &"cuddle-please".into(), + &"debug".into(), + ) + .await?; test::execute(client, &cli.global, base_image).await?; } LocalCommands::DockerImage { @@ -137,11 +151,11 @@ async fn main() -> eyre::Result<()> { image, bin_name, } => { - build::build_and_deploy(client, &cli.global, bin_name, image, tag).await?; + build::build_and_deploy(client, &cli.global, &bin_name, &image, &tag).await?; } LocalCommands::PleaseRelease => todo!(), LocalCommands::BuildDocs {} => { - let _image = docs::execute( + let image = docs::execute( client.clone(), &cli.global, &Some("linux/amd64".to_string()), @@ -158,10 +172,11 @@ async fn main() -> eyre::Result<()> { async fn test(client: Arc, cli: &Command, bin_name: &String) { let args = &cli.global; - let base_image = base_rust_image(client.clone(), args, &None, bin_name) - .await - .unwrap(); - test::execute(client.clone(), args, base_image) + let base_image = + base_rust_image(client.clone(), &args, &None, bin_name, &"debug".into()) + .await + .unwrap(); + test::execute(client.clone(), &args, base_image) .await .unwrap(); } @@ -174,14 +189,21 @@ async fn main() -> eyre::Result<()> { ) { let args = &cli.global; - build::build_and_deploy(client.clone(), args, bin_name, image, tag) + build::build_and_deploy(client.clone(), &args, bin_name, image, tag) + .await + .unwrap(); + } + + async fn cuddle_please(client: Arc, cli: &Command) { + run_release_please(client.clone(), &cli.global) .await .unwrap(); } tokio::join!( - test(client.clone(), &cli, bin_name), - build(client.clone(), &cli, bin_name, image, tag) + test(client.clone(), &cli, &bin_name), + build(client.clone(), &cli, &bin_name, &image, &tag), + cuddle_please(client.clone(), &cli) ); } Commands::Release => todo!(), @@ -190,6 +212,97 @@ async fn main() -> eyre::Result<()> { Ok(()) } +mod please_release { + + use std::sync::Arc; + + use dagger_sdk::Container; + + use crate::{base_rust_image, build, get_base_debian_image, get_rust_dep_src, GlobalArgs}; + + pub async fn run_release_please( + client: Arc, + args: &GlobalArgs, + ) -> eyre::Result<()> { + let base_image = base_rust_image( + client.clone(), + args, + &Some("linux/amd64".to_string()), + &"cuddle-please".to_string(), + &"release".into(), + ) + .await?; + + let build_image = base_image.with_exec(vec![ + "cargo", + "install", + "--target", + "x86_64-unknown-linux-gnu", + "--path=crates/cuddle-please", + ]); + + let src = client + .git_opts( + "https://git.front.kjuulh.io/kjuulh/cuddle-please", + dagger_sdk::QueryGitOpts { + experimental_service_host: None, + keep_git_dir: Some(true), + }, + ) + .branch("main") + .tree(); + + let res = build_image + .with_secret_variable( + "CUDDLE_PLEASE_TOKEN", + client + .set_secret("CUDDLE_PLEASE_TOKEN", std::env::var("CUDDLE_PLEASE_TOKEN")?) + .id() + .await?, + ) + .with_workdir("/mnt/app") + .with_directory(".", src.id().await?) + .with_exec(vec![ + "git", + "remote", + "set-url", + "origin", + &format!( + "https://git:{}@git.front.kjuulh.io/kjuulh/cuddle-please.git", + std::env::var("CUDDLE_PLEASE_TOKEN")? + ), + ]) + .with_exec(vec![ + "git", + "config", + "http.extraheader", + "'Authorization: token b52c18cab8a95d33f34b0d081440f77a2b156886'", + ]) + .with_exec(vec![ + "cuddle-please", + "release", + "--engine=gitea", + "--owner=kjuulh", + "--repo=cuddle-please", + "--branch=main", + "--api-url=https://git.front.kjuulh.io", + "--log-level=debug", + ]); + + let exit_code = res.exit_code().await?; + if exit_code != 0 { + eyre::bail!("failed to run cuddle-please"); + } + + let please_out = res.stdout().await?; + println!("{please_out}"); + let please_out = res.stderr().await?; + println!("{please_out}"); + + Ok(()) + } +} + mod docs { use std::sync::Arc; @@ -212,7 +325,7 @@ mod docs { pub async fn execute( client: Arc, args: &GlobalArgs, - _platform: &Option, + platform: &Option, ) -> eyre::Result { let mkdocs_container = client.container().from( args.mkdocs_image @@ -275,9 +388,9 @@ mod build { use dagger_sdk::Container; - - - + use futures::StreamExt; + use tokio::sync::Mutex; + use tokio::task::JoinHandle; use crate::{base_rust_image, get_base_debian_image, GlobalArgs}; @@ -299,17 +412,18 @@ mod build { let container = base_rust_image( client.clone(), - args, + &args, &Some("linux/amd64".to_string()), &bin_name.clone(), + &"release".into(), ) .await?; let build_image = execute( client.clone(), - args, + &args, &container, &base_image, - bin_name, + &bin_name, &Some("linux/amd64".to_string()), ) .await?; @@ -352,7 +466,7 @@ mod build { rust_target, "--release", "-p", - bin_name, + &bin_name, ]); let final_image = base_image @@ -363,7 +477,7 @@ mod build { .id() .await?, ) - .with_exec(vec![bin_name, "--help"]); + .with_exec(vec![&bin_name, "--help"]); let output = final_image.stdout().await?; println!("{output}"); @@ -458,12 +572,12 @@ pub async fn get_rust_dep_src( .build()?, ); - Ok(directory) + return Ok(directory); } pub async fn get_rust_skeleton_files( client: Arc, - _args: &GlobalArgs, + args: &GlobalArgs, ) -> eyre::Result<(dagger_sdk::Directory, Vec)> { let mut rust_crates = vec![PathBuf::from("ci")]; let mut dirs = tokio::fs::read_dir("crates").await?; @@ -505,7 +619,7 @@ pub async fn get_rust_skeleton_files( if let Some(file_name) = rust_crate.file_name() { crate_names.push(file_name.to_str().unwrap().to_string()); } - directory = create_skeleton_files(directory, rust_crate)?; + directory = create_skeleton_files(directory, &rust_crate)?; } Ok((directory, crate_names)) @@ -516,6 +630,7 @@ pub async fn base_rust_image( args: &GlobalArgs, platform: &Option, bin_name: &String, + profile: &String, ) -> eyre::Result { let dep_src = get_rust_dep_src(client.clone(), args).await?; let (skeleton_files, crates) = get_rust_skeleton_files(client.clone(), args).await?; @@ -541,27 +656,23 @@ pub async fn base_rust_image( ) .with_exec(vec!["rustup", "target", "add", rust_target]); - let target_cache = client.cache_volume("rust_target"); + let target_cache = client.cache_volume(format!("rust_target_{}", profile)); + let mut build_options = vec!["cargo", "build", "--target", rust_target, "-p", &bin_name]; + if profile == "release" { + build_options.push("--release"); + } let rust_prebuild = rust_build_image .with_workdir("/mnt/src") .with_directory("/mnt/src", dep_src.id().await?) .with_directory("/mnt/src/", skeleton_files.id().await?) - .with_exec(vec![ - "cargo", - "build", - "--target", - rust_target, - "--release", - "-p", - bin_name, - ]) + .with_exec(build_options) .with_mounted_cache("/mnt/src/target/", target_cache.id().await?); let exclude = crates .iter() .filter(|c| **c != "ci") - .map(|c| format!("**/*{}*", c.replace('-', "_"))) + .map(|c| format!("**/*{}*", c.replace("-", "_"))) .collect::>(); let exclude = exclude.iter().map(|c| c.as_str()).collect(); @@ -581,12 +692,7 @@ pub async fn base_rust_image( "/usr/local/cargo", rust_prebuild.directory("/usr/local/cargo").id().await?, ) - .with_directory( - //format!("/mnt/src/target/{}/release/build", rust_target), - "target", - //rust_prebuild.id().await?, - incremental_dir.id().await?, - ) + .with_directory("target", incremental_dir.id().await?) .with_directory("/mnt/src/", src.id().await?); Ok(rust_with_src) diff --git a/crates/cuddle-please-commands/src/command.rs b/crates/cuddle-please-commands/src/command.rs index 3079e64..5913f58 100644 --- a/crates/cuddle-please-commands/src/command.rs +++ b/crates/cuddle-please-commands/src/command.rs @@ -120,7 +120,8 @@ impl Command { current_dir: Option<&Path>, ) -> anyhow::Result<(PleaseConfig, VcsClient, DynRemoteGitClient)> { let config = self.build_config(current_dir)?; - let git_client = self.get_git(&config)?; + let git_client = + self.get_git(&config, self.global.token.clone().expect("token to be set"))?; let gitea_client = self.get_gitea_client(&config); let filter = match self.global.log_level { @@ -160,7 +161,7 @@ impl Command { Ok(config) } - fn get_git(&self, config: &PleaseConfig) -> anyhow::Result { + fn get_git(&self, config: &PleaseConfig, token: String) -> anyhow::Result { if self.global.no_vcs { Ok(VcsClient::new_noop()) } else { @@ -168,6 +169,7 @@ impl Command { config.get_source(), config.settings.git_username.clone(), config.settings.git_email.clone(), + token, ) } } diff --git a/crates/cuddle-please-misc/src/git_client.rs b/crates/cuddle-please-misc/src/git_client.rs index 1207155..b1aec7d 100644 --- a/crates/cuddle-please-misc/src/git_client.rs +++ b/crates/cuddle-please-misc/src/git_client.rs @@ -7,6 +7,7 @@ pub enum VcsClient { source: PathBuf, username: String, email: String, + token: String, }, } @@ -19,6 +20,7 @@ impl VcsClient { path: &Path, git_username: Option>, git_email: Option>, + git_token: String, ) -> anyhow::Result { if !path.to_path_buf().join(".git").exists() { anyhow::bail!("git directory not found in: {}", path.display().to_string()) @@ -32,6 +34,7 @@ impl VcsClient { email: git_email .map(|e| e.into()) .unwrap_or("bot@cuddle.sh".to_string()), + token: git_token, }) } @@ -56,10 +59,15 @@ impl VcsClient { source, username, email, + token, } => { let checkout_branch = std::process::Command::new("git") .current_dir(source.as_path()) .args([ + "-c", + &format!("http.extraHeader='Authorization: token {}'", token), + "-c", + &format!("http.extraHeader='Sudo: kjuulh'"), "-c", &format!("user.name={}", username), "-c", diff --git a/crates/cuddle-please/tests/config.rs b/crates/cuddle-please/tests/config.rs index 50b62ba..31e0cf7 100644 --- a/crates/cuddle-please/tests/config.rs +++ b/crates/cuddle-please/tests/config.rs @@ -13,6 +13,7 @@ fn get_base_args<'a>() -> Vec<&'a str> { "list", "--no-vcs", "--engine=local", + "--token=something", ] } diff --git a/crates/cuddle-please/tests/git.rs b/crates/cuddle-please/tests/git.rs index 60de0b3..0184031 100644 --- a/crates/cuddle-please/tests/git.rs +++ b/crates/cuddle-please/tests/git.rs @@ -17,7 +17,8 @@ fn exec_git_into_branch() { add_commit(tempdir.path(), "second").unwrap(); add_tag(tempdir.path(), "1.0.1").unwrap(); - let vcs = VcsClient::new_git(tempdir.path(), None::, None::).unwrap(); + let vcs = + VcsClient::new_git(tempdir.path(), None::, None::, "".into()).unwrap(); vcs.checkout_branch().unwrap(); let output = std::process::Command::new("git") @@ -48,7 +49,8 @@ fn add_files_to_commit() { add_commit(tempdir.path(), "first").unwrap(); add_tag(tempdir.path(), "1.0.0").unwrap(); - let vcs = VcsClient::new_git(tempdir.path(), None::, None::).unwrap(); + let vcs = + VcsClient::new_git(tempdir.path(), None::, None::, "".into()).unwrap(); vcs.checkout_branch().unwrap(); std::fs::File::create(tempdir.path().join("changelog")).unwrap(); @@ -76,7 +78,8 @@ fn reset_branch() { add_commit(tempdir.path(), "first").unwrap(); add_tag(tempdir.path(), "1.0.0").unwrap(); - let vcs = VcsClient::new_git(tempdir.path(), None::, None::).unwrap(); + let vcs = + VcsClient::new_git(tempdir.path(), None::, None::, "".into()).unwrap(); vcs.checkout_branch().unwrap(); std::fs::File::create(tempdir.path().join("changelog-first")).unwrap(); diff --git a/crates/cuddle-please/tests/vcs.rs b/crates/cuddle-please/tests/vcs.rs index 13265be..8e23650 100644 --- a/crates/cuddle-please/tests/vcs.rs +++ b/crates/cuddle-please/tests/vcs.rs @@ -16,13 +16,14 @@ fn test_vcs_get_noop() { #[traced_test] fn test_vcs_get_git_found() { let testdata = get_test_data_path("git-found"); - let git = VcsClient::new_git(&testdata, None::, None::).unwrap(); + let git = VcsClient::new_git(&testdata, None::, None::, "".into()).unwrap(); assert_eq!( git, VcsClient::Git { source: testdata, username: "cuddle-please".into(), - email: "bot@cuddle.sh".into() + email: "bot@cuddle.sh".into(), + token: "".into(), } ) }