use std::path::PathBuf; use async_trait::async_trait; use dagger_rust::source::RustSource; use dagger_sdk::Container; use crate::{ cli, rust_service::architecture::{Architecture, Os}, rust_workspace, MainAction, PullRequestAction, }; #[derive(Clone)] pub struct RustLib { client: dagger_sdk::Query, base_image: Option, source: Option, crates: Vec, arch: Option, os: Option, } impl RustLib { pub fn new(value: dagger_sdk::Query) -> Self { Self { client: value.pipeline("rust-lib"), source: None, crates: Vec::new(), arch: None, os: None, base_image: None, } } pub fn with_source(&mut self, path: impl Into) -> &mut Self { self.source = Some(path.into()); self } pub fn with_base_image(&mut self, base: dagger_sdk::Container) -> &mut Self { self.base_image = Some(base); self } pub fn with_crates( &mut self, crates: impl IntoIterator>, ) -> &mut Self { self.crates = crates.into_iter().map(|c| c.into()).collect(); self } pub async fn with_workspace_crates(&mut self) -> &mut Self { if let Ok(Some(file)) = rust_workspace::File::read_file().await { if let Some(members) = file.get_workspace_members() { return self.with_crates(members); } } self } pub fn with_arch(&mut self, arch: Architecture) -> &mut Self { self.arch = Some(arch); self } pub fn with_os(&mut self, os: Os) -> &mut Self { self.os = Some(os); self } fn get_src(&self) -> PathBuf { self.source .clone() .unwrap_or(std::env::current_dir().unwrap()) } pub async fn build_base(&self) -> eyre::Result { let rust_src = RustSource::new(self.client.clone()); let (src, dep_src) = rust_src .get_rust_src(Some(&self.get_src()), self.crates.clone()) .await?; let base_image = self .base_image .clone() .unwrap_or(self.client.container().from("rustlang/rust:nightly")); let cache = self.client.cache_volume("rust_target_cache"); let rust_prebuild = base_image .with_workdir("/mnt/src") .with_directory("/mnt/src", dep_src) .with_exec(vec!["cargo", "build", "--tests", "--workspace"]) .with_mounted_cache("/mnt/src/target/", cache); let incremental_dir = rust_src .get_rust_target_src(&self.get_src(), rust_prebuild.clone(), self.crates.clone()) .await?; let rust_with_src = base_image .with_workdir("/mnt/src") .with_directory( "/usr/local/cargo", rust_prebuild.directory("/usr/local/cargo"), ) .with_directory("/mnt/src/target", incremental_dir) .with_directory("/mnt/src/", src); Ok(rust_with_src) } pub async fn build_test(&self) -> eyre::Result<()> { let base = self.build_base().await?; base.with_exec(vec!["cargo", "test", "--tests", "--workspace"]) .sync() .await?; Ok(()) } } #[async_trait] impl PullRequestAction for RustLib { async fn execute_pull_request(&self, _ctx: &mut cli::Context) -> eyre::Result<()> { self.build_test().await?; Ok(()) } } #[async_trait] impl MainAction for RustLib { async fn execute_main(&self, _ctx: &mut cli::Context) -> eyre::Result<()> { self.build_test().await?; Ok(()) } }