1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use std::{path::PathBuf, sync::Arc};

use crate::{build::RustVersion, source::RustSource};

pub struct RustTest {
    client: Arc<dagger_sdk::Query>,
    registry: Option<String>,
}

impl RustTest {
    pub fn new(client: Arc<dagger_sdk::Query>) -> Self {
        Self {
            client,
            registry: None,
        }
    }

    pub async fn test(
        &self,
        source_path: Option<impl Into<PathBuf>>,
        rust_version: impl AsRef<RustVersion>,
        crates: &[&str],
        extra_deps: &[&str],
    ) -> eyre::Result<()> {
        let rust_version = rust_version.as_ref();
        let source_path = source_path.map(|s| s.into());
        let source = source_path.clone().unwrap_or(PathBuf::from("."));

        let rust_source = RustSource::new(self.client.clone());
        let (src, dep_src) = rust_source
            .get_rust_src(source_path, crates.to_vec())
            .await?;
        let mut deps = vec!["apt", "install", "-y"];
        deps.extend(extra_deps);

        let rust_build_image = self
            .client
            .container()
            .from(rust_version.to_string())
            .with_exec(vec!["apt", "update"])
            .with_exec(deps);

        let target_cache = self.client.cache_volume(format!("rust_target_test",));

        let build_options = vec!["cargo", "build", "--workspace"];
        let rust_prebuild = rust_build_image
            .with_workdir("/mnt/src")
            .with_directory("/mnt/src", dep_src.id().await?)
            .with_exec(build_options)
            .with_mounted_cache("/mnt/src/target/", target_cache.id().await?);

        let incremental_dir = rust_source
            .get_rust_target_src(&source, rust_prebuild.clone(), crates.to_vec())
            .await?;

        let rust_with_src = rust_build_image
            .with_workdir("/mnt/src")
            .with_directory(
                "/usr/local/cargo",
                rust_prebuild.directory("/usr/local/cargo").id().await?,
            )
            .with_directory("/mnt/src/target", incremental_dir.id().await?)
            .with_directory("/mnt/src/", src.id().await?);

        let test = rust_with_src.with_exec(vec!["cargo", "test"]);

        let stdout = test.stdout().await?;
        let stderr = test.stderr().await?;
        println!("stdout: {}, stderr: {}", stdout, stderr);

        if 0 != test.exit_code().await? {
            eyre::bail!("failed rust:test");
        }

        Ok(())
    }
}