feat: with working main
Some checks failed
continuous-integration/drone/push Build is failing

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
Kasper Juul Hermansen 2023-08-03 23:31:53 +02:00
parent 8ee05136df
commit 34417f77bc
Signed by: kjuulh
GPG Key ID: 9AA7BC13CE474394
8 changed files with 178 additions and 55 deletions

1
Cargo.lock generated
View File

@ -261,6 +261,7 @@ dependencies = [
"clap", "clap",
"color-eyre", "color-eyre",
"dagger-sdk", "dagger-sdk",
"dotenv",
"eyre", "eyre",
"futures", "futures",
"tokio", "tokio",

View File

@ -13,3 +13,4 @@ tokio = "1"
clap = {version = "4", features = ["derive"]} clap = {version = "4", features = ["derive"]}
futures = "0.3.28" futures = "0.3.28"
async-scoped = { version = "0.7.1", features = ["tokio", "use-tokio"] } async-scoped = { version = "0.7.1", features = ["tokio", "use-tokio"] }
dotenv.workspace = true

View File

@ -2,19 +2,21 @@ use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use build::build_and_deploy;
use clap::Args; use clap::Args;
use clap::Parser; use clap::Parser;
use clap::Subcommand; use clap::Subcommand;
use clap::ValueEnum; use clap::ValueEnum;
use dagger_sdk::ContainerId;
use dagger_sdk::ContainerPublishOpts;
use dagger_sdk::Platform; use dagger_sdk::Platform;
use dagger_sdk::QueryContainerOpts; use dagger_sdk::QueryContainerOpts;
use futures::StreamExt; use futures::StreamExt;
use tokio::sync::Mutex;
use tokio::task::JoinHandle;
use crate::please_release::run_release_please;
#[derive(Parser, Clone)] #[derive(Parser, Clone)]
#[command(author, version, about, long_about = None, subcommand_required = true)] #[command(author, version, about, long_about = None, subcommand_required = true)]
@ -101,6 +103,7 @@ pub struct GlobalArgs {
#[tokio::main] #[tokio::main]
async fn main() -> eyre::Result<()> { async fn main() -> eyre::Result<()> {
let _ = dotenv::dotenv();
let _ = color_eyre::install(); let _ = color_eyre::install();
let client = dagger_sdk::connect().await?; let client = dagger_sdk::connect().await?;
@ -113,23 +116,34 @@ async fn main() -> eyre::Result<()> {
profile: _, profile: _,
bin_name, bin_name,
} => { } => {
let base_image = let base_image = base_rust_image(
base_rust_image(client.clone(), &cli.global, &None, &bin_name.clone()).await?; client.clone(),
&cli.global,
&None,
&bin_name.clone(),
&"release".into(),
)
.await?;
let prod_image = get_base_debian_image(client.clone(), &cli.global, None).await?; let prod_image = get_base_debian_image(client.clone(), &cli.global, None).await?;
build::execute( build::execute(
client, client,
&cli.global, &cli.global,
&base_image, &base_image,
&prod_image, &prod_image,
bin_name, &bin_name,
&None, &None,
) )
.await?; .await?;
} }
LocalCommands::Test => { LocalCommands::Test => {
let base_image = let base_image = base_rust_image(
base_rust_image(client.clone(), &cli.global, &None, &"cuddle-please".into()) client.clone(),
.await?; &cli.global,
&None,
&"cuddle-please".into(),
&"debug".into(),
)
.await?;
test::execute(client, &cli.global, base_image).await?; test::execute(client, &cli.global, base_image).await?;
} }
LocalCommands::DockerImage { LocalCommands::DockerImage {
@ -137,11 +151,11 @@ async fn main() -> eyre::Result<()> {
image, image,
bin_name, 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::PleaseRelease => todo!(),
LocalCommands::BuildDocs {} => { LocalCommands::BuildDocs {} => {
let _image = docs::execute( let image = docs::execute(
client.clone(), client.clone(),
&cli.global, &cli.global,
&Some("linux/amd64".to_string()), &Some("linux/amd64".to_string()),
@ -158,10 +172,11 @@ async fn main() -> eyre::Result<()> {
async fn test(client: Arc<dagger_sdk::Query>, cli: &Command, bin_name: &String) { async fn test(client: Arc<dagger_sdk::Query>, cli: &Command, bin_name: &String) {
let args = &cli.global; let args = &cli.global;
let base_image = base_rust_image(client.clone(), args, &None, bin_name) let base_image =
.await base_rust_image(client.clone(), &args, &None, bin_name, &"debug".into())
.unwrap(); .await
test::execute(client.clone(), args, base_image) .unwrap();
test::execute(client.clone(), &args, base_image)
.await .await
.unwrap(); .unwrap();
} }
@ -174,14 +189,21 @@ async fn main() -> eyre::Result<()> {
) { ) {
let args = &cli.global; 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<dagger_sdk::Query>, cli: &Command) {
run_release_please(client.clone(), &cli.global)
.await .await
.unwrap(); .unwrap();
} }
tokio::join!( tokio::join!(
test(client.clone(), &cli, bin_name), test(client.clone(), &cli, &bin_name),
build(client.clone(), &cli, bin_name, image, tag) build(client.clone(), &cli, &bin_name, &image, &tag),
cuddle_please(client.clone(), &cli)
); );
} }
Commands::Release => todo!(), Commands::Release => todo!(),
@ -190,6 +212,97 @@ async fn main() -> eyre::Result<()> {
Ok(()) 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<dagger_sdk::Query>,
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 { mod docs {
use std::sync::Arc; use std::sync::Arc;
@ -212,7 +325,7 @@ mod docs {
pub async fn execute( pub async fn execute(
client: Arc<dagger_sdk::Query>, client: Arc<dagger_sdk::Query>,
args: &GlobalArgs, args: &GlobalArgs,
_platform: &Option<String>, platform: &Option<String>,
) -> eyre::Result<Container> { ) -> eyre::Result<Container> {
let mkdocs_container = client.container().from( let mkdocs_container = client.container().from(
args.mkdocs_image args.mkdocs_image
@ -275,9 +388,9 @@ mod build {
use dagger_sdk::Container; 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}; use crate::{base_rust_image, get_base_debian_image, GlobalArgs};
@ -299,17 +412,18 @@ mod build {
let container = base_rust_image( let container = base_rust_image(
client.clone(), client.clone(),
args, &args,
&Some("linux/amd64".to_string()), &Some("linux/amd64".to_string()),
&bin_name.clone(), &bin_name.clone(),
&"release".into(),
) )
.await?; .await?;
let build_image = execute( let build_image = execute(
client.clone(), client.clone(),
args, &args,
&container, &container,
&base_image, &base_image,
bin_name, &bin_name,
&Some("linux/amd64".to_string()), &Some("linux/amd64".to_string()),
) )
.await?; .await?;
@ -352,7 +466,7 @@ mod build {
rust_target, rust_target,
"--release", "--release",
"-p", "-p",
bin_name, &bin_name,
]); ]);
let final_image = base_image let final_image = base_image
@ -363,7 +477,7 @@ mod build {
.id() .id()
.await?, .await?,
) )
.with_exec(vec![bin_name, "--help"]); .with_exec(vec![&bin_name, "--help"]);
let output = final_image.stdout().await?; let output = final_image.stdout().await?;
println!("{output}"); println!("{output}");
@ -458,12 +572,12 @@ pub async fn get_rust_dep_src(
.build()?, .build()?,
); );
Ok(directory) return Ok(directory);
} }
pub async fn get_rust_skeleton_files( pub async fn get_rust_skeleton_files(
client: Arc<dagger_sdk::Query>, client: Arc<dagger_sdk::Query>,
_args: &GlobalArgs, args: &GlobalArgs,
) -> eyre::Result<(dagger_sdk::Directory, Vec<String>)> { ) -> eyre::Result<(dagger_sdk::Directory, Vec<String>)> {
let mut rust_crates = vec![PathBuf::from("ci")]; let mut rust_crates = vec![PathBuf::from("ci")];
let mut dirs = tokio::fs::read_dir("crates").await?; 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() { if let Some(file_name) = rust_crate.file_name() {
crate_names.push(file_name.to_str().unwrap().to_string()); 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)) Ok((directory, crate_names))
@ -516,6 +630,7 @@ pub async fn base_rust_image(
args: &GlobalArgs, args: &GlobalArgs,
platform: &Option<String>, platform: &Option<String>,
bin_name: &String, bin_name: &String,
profile: &String,
) -> eyre::Result<dagger_sdk::Container> { ) -> eyre::Result<dagger_sdk::Container> {
let dep_src = get_rust_dep_src(client.clone(), args).await?; let dep_src = get_rust_dep_src(client.clone(), args).await?;
let (skeleton_files, crates) = get_rust_skeleton_files(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]); .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 let rust_prebuild = rust_build_image
.with_workdir("/mnt/src") .with_workdir("/mnt/src")
.with_directory("/mnt/src", dep_src.id().await?) .with_directory("/mnt/src", dep_src.id().await?)
.with_directory("/mnt/src/", skeleton_files.id().await?) .with_directory("/mnt/src/", skeleton_files.id().await?)
.with_exec(vec![ .with_exec(build_options)
"cargo",
"build",
"--target",
rust_target,
"--release",
"-p",
bin_name,
])
.with_mounted_cache("/mnt/src/target/", target_cache.id().await?); .with_mounted_cache("/mnt/src/target/", target_cache.id().await?);
let exclude = crates let exclude = crates
.iter() .iter()
.filter(|c| **c != "ci") .filter(|c| **c != "ci")
.map(|c| format!("**/*{}*", c.replace('-', "_"))) .map(|c| format!("**/*{}*", c.replace("-", "_")))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let exclude = exclude.iter().map(|c| c.as_str()).collect(); let exclude = exclude.iter().map(|c| c.as_str()).collect();
@ -581,12 +692,7 @@ pub async fn base_rust_image(
"/usr/local/cargo", "/usr/local/cargo",
rust_prebuild.directory("/usr/local/cargo").id().await?, rust_prebuild.directory("/usr/local/cargo").id().await?,
) )
.with_directory( .with_directory("target", incremental_dir.id().await?)
//format!("/mnt/src/target/{}/release/build", rust_target),
"target",
//rust_prebuild.id().await?,
incremental_dir.id().await?,
)
.with_directory("/mnt/src/", src.id().await?); .with_directory("/mnt/src/", src.id().await?);
Ok(rust_with_src) Ok(rust_with_src)

View File

@ -120,7 +120,8 @@ impl Command {
current_dir: Option<&Path>, current_dir: Option<&Path>,
) -> anyhow::Result<(PleaseConfig, VcsClient, DynRemoteGitClient)> { ) -> anyhow::Result<(PleaseConfig, VcsClient, DynRemoteGitClient)> {
let config = self.build_config(current_dir)?; 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 gitea_client = self.get_gitea_client(&config);
let filter = match self.global.log_level { let filter = match self.global.log_level {
@ -160,7 +161,7 @@ impl Command {
Ok(config) Ok(config)
} }
fn get_git(&self, config: &PleaseConfig) -> anyhow::Result<VcsClient> { fn get_git(&self, config: &PleaseConfig, token: String) -> anyhow::Result<VcsClient> {
if self.global.no_vcs { if self.global.no_vcs {
Ok(VcsClient::new_noop()) Ok(VcsClient::new_noop())
} else { } else {
@ -168,6 +169,7 @@ impl Command {
config.get_source(), config.get_source(),
config.settings.git_username.clone(), config.settings.git_username.clone(),
config.settings.git_email.clone(), config.settings.git_email.clone(),
token,
) )
} }
} }

View File

@ -7,6 +7,7 @@ pub enum VcsClient {
source: PathBuf, source: PathBuf,
username: String, username: String,
email: String, email: String,
token: String,
}, },
} }
@ -19,6 +20,7 @@ impl VcsClient {
path: &Path, path: &Path,
git_username: Option<impl Into<String>>, git_username: Option<impl Into<String>>,
git_email: Option<impl Into<String>>, git_email: Option<impl Into<String>>,
git_token: String,
) -> anyhow::Result<VcsClient> { ) -> anyhow::Result<VcsClient> {
if !path.to_path_buf().join(".git").exists() { if !path.to_path_buf().join(".git").exists() {
anyhow::bail!("git directory not found in: {}", path.display().to_string()) anyhow::bail!("git directory not found in: {}", path.display().to_string())
@ -32,6 +34,7 @@ impl VcsClient {
email: git_email email: git_email
.map(|e| e.into()) .map(|e| e.into())
.unwrap_or("bot@cuddle.sh".to_string()), .unwrap_or("bot@cuddle.sh".to_string()),
token: git_token,
}) })
} }
@ -56,10 +59,15 @@ impl VcsClient {
source, source,
username, username,
email, email,
token,
} => { } => {
let checkout_branch = std::process::Command::new("git") let checkout_branch = std::process::Command::new("git")
.current_dir(source.as_path()) .current_dir(source.as_path())
.args([ .args([
"-c",
&format!("http.extraHeader='Authorization: token {}'", token),
"-c",
&format!("http.extraHeader='Sudo: kjuulh'"),
"-c", "-c",
&format!("user.name={}", username), &format!("user.name={}", username),
"-c", "-c",

View File

@ -13,6 +13,7 @@ fn get_base_args<'a>() -> Vec<&'a str> {
"list", "list",
"--no-vcs", "--no-vcs",
"--engine=local", "--engine=local",
"--token=something",
] ]
} }

View File

@ -17,7 +17,8 @@ fn exec_git_into_branch() {
add_commit(tempdir.path(), "second").unwrap(); add_commit(tempdir.path(), "second").unwrap();
add_tag(tempdir.path(), "1.0.1").unwrap(); add_tag(tempdir.path(), "1.0.1").unwrap();
let vcs = VcsClient::new_git(tempdir.path(), None::<String>, None::<String>).unwrap(); let vcs =
VcsClient::new_git(tempdir.path(), None::<String>, None::<String>, "".into()).unwrap();
vcs.checkout_branch().unwrap(); vcs.checkout_branch().unwrap();
let output = std::process::Command::new("git") let output = std::process::Command::new("git")
@ -48,7 +49,8 @@ fn add_files_to_commit() {
add_commit(tempdir.path(), "first").unwrap(); add_commit(tempdir.path(), "first").unwrap();
add_tag(tempdir.path(), "1.0.0").unwrap(); add_tag(tempdir.path(), "1.0.0").unwrap();
let vcs = VcsClient::new_git(tempdir.path(), None::<String>, None::<String>).unwrap(); let vcs =
VcsClient::new_git(tempdir.path(), None::<String>, None::<String>, "".into()).unwrap();
vcs.checkout_branch().unwrap(); vcs.checkout_branch().unwrap();
std::fs::File::create(tempdir.path().join("changelog")).unwrap(); std::fs::File::create(tempdir.path().join("changelog")).unwrap();
@ -76,7 +78,8 @@ fn reset_branch() {
add_commit(tempdir.path(), "first").unwrap(); add_commit(tempdir.path(), "first").unwrap();
add_tag(tempdir.path(), "1.0.0").unwrap(); add_tag(tempdir.path(), "1.0.0").unwrap();
let vcs = VcsClient::new_git(tempdir.path(), None::<String>, None::<String>).unwrap(); let vcs =
VcsClient::new_git(tempdir.path(), None::<String>, None::<String>, "".into()).unwrap();
vcs.checkout_branch().unwrap(); vcs.checkout_branch().unwrap();
std::fs::File::create(tempdir.path().join("changelog-first")).unwrap(); std::fs::File::create(tempdir.path().join("changelog-first")).unwrap();

View File

@ -16,13 +16,14 @@ fn test_vcs_get_noop() {
#[traced_test] #[traced_test]
fn test_vcs_get_git_found() { fn test_vcs_get_git_found() {
let testdata = get_test_data_path("git-found"); let testdata = get_test_data_path("git-found");
let git = VcsClient::new_git(&testdata, None::<String>, None::<String>).unwrap(); let git = VcsClient::new_git(&testdata, None::<String>, None::<String>, "".into()).unwrap();
assert_eq!( assert_eq!(
git, git,
VcsClient::Git { VcsClient::Git {
source: testdata, source: testdata,
username: "cuddle-please".into(), username: "cuddle-please".into(),
email: "bot@cuddle.sh".into() email: "bot@cuddle.sh".into(),
token: "".into(),
} }
) )
} }