flowey_lib_common/
run_cargo_nextest_archive.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Build and archive cargo-nextest tests (for cross-job execution).
5//!
6//! Respects common cargo flags specified by the `cfg_cargo_common_flags` node.
7
8use crate::run_cargo_nextest_run::build_params::NextestBuildParams;
9use flowey::node::prelude::*;
10
11flowey_request! {
12    pub struct Request {
13        /// Friendly label for this request that shows up in logs.
14        pub friendly_label: String,
15        /// Directory to run `cargo nextest archive` within
16        pub working_dir: ReadVar<PathBuf>,
17        /// Build parameters to use when compiling the tests.
18        pub build_params: NextestBuildParams,
19        /// Wait for specified side-effects to resolve before building / running any
20        /// tests. (e.g: to allow for some ambient packages / dependencies to
21        /// get installed).
22        pub pre_run_deps: Vec<ReadVar<SideEffect>>,
23        /// Resulting nextest archive file
24        pub archive_file: WriteVar<PathBuf>,
25    }
26}
27
28new_flow_node!(struct Node);
29
30impl FlowNode for Node {
31    type Request = Request;
32
33    fn imports(ctx: &mut ImportCtx<'_>) {
34        ctx.import::<crate::cfg_cargo_common_flags::Node>();
35        ctx.import::<crate::download_cargo_nextest::Node>();
36        ctx.import::<crate::install_rust::Node>();
37    }
38
39    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
40        let cargo_flags = ctx.reqv(crate::cfg_cargo_common_flags::Request::GetFlags);
41
42        let nextest_installed = ctx.reqv(crate::download_cargo_nextest::Request::InstallWithCargo);
43
44        let rust_toolchain = ctx.reqv(crate::install_rust::Request::GetRustupToolchain);
45
46        for Request {
47            friendly_label,
48            working_dir,
49            build_params:
50                NextestBuildParams {
51                    packages,
52                    features,
53                    no_default_features,
54                    unstable_panic_abort_tests,
55                    target,
56                    profile,
57                    extra_env,
58                },
59            pre_run_deps,
60            archive_file,
61        } in requests
62        {
63            ctx.req(crate::install_rust::Request::InstallTargetTriple(
64                target.clone(),
65            ));
66
67            ctx.emit_rust_step(
68                format!("build + archive '{friendly_label}' nextests"),
69                |ctx| {
70                    pre_run_deps.claim(ctx);
71                    nextest_installed.clone().claim(ctx);
72                    let cargo_flags = cargo_flags.clone().claim(ctx);
73                    let rust_toolchain = rust_toolchain.clone().claim(ctx);
74                    let working_dir = working_dir.claim(ctx);
75                    let archive_file = archive_file.claim(ctx);
76                    let packages = packages.claim(ctx);
77                    let extra_env = extra_env.claim(ctx);
78                    move |rt| {
79                        let cargo_flags = rt.read(cargo_flags);
80                        let working_dir = rt.read(working_dir);
81                        let rust_toolchain = rt.read(rust_toolchain);
82                        let packages = rt.read(packages);
83                        let extra_env = rt.read(extra_env);
84
85                        let rust_toolchain = rust_toolchain.map(|s| format!("+{s}"));
86                        let (build_args, build_env) =
87                            crate::run_cargo_nextest_run::cargo_nextest_build_args_and_env(
88                                cargo_flags,
89                                profile,
90                                target,
91                                packages,
92                                features,
93                                unstable_panic_abort_tests,
94                                no_default_features,
95                                extra_env,
96                            );
97
98                        let sh = xshell::Shell::new()?;
99
100                        let out_archive_file = sh.current_dir().absolute()?.join("archive.tar.zst");
101
102                        sh.change_dir(working_dir);
103                        let mut cmd = xshell::cmd!(
104                            sh,
105                            "cargo {rust_toolchain...} nextest archive
106                                {build_args...}
107                                --archive-file {out_archive_file}
108                            "
109                        );
110
111                        // if running in CI, no need to waste time with incremental
112                        // build artifacts
113                        if !matches!(rt.backend(), FlowBackend::Local) {
114                            cmd = cmd.env("CARGO_INCREMENTAL", "0");
115                        }
116
117                        for (k, v) in build_env {
118                            cmd = cmd.env(k, v);
119                        }
120
121                        cmd.run()?;
122
123                        rt.write(archive_file, &out_archive_file);
124
125                        Ok(())
126                    }
127                },
128            );
129        }
130
131        Ok(())
132    }
133}