Skip to main content

flowey_lib_hvlite/_jobs/
cfg_versions.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! An amalgamated configuration node that streamlines the process of resolving
5//! version configuration requests required by various dependencies in OpenVMM
6//! pipelines.
7
8use crate::common::CommonArch;
9use crate::resolve_openhcl_kernel_package::OpenhclKernelPackageKind;
10use flowey::node::prelude::*;
11use std::collections::BTreeMap;
12
13// FUTURE: instead of hard-coding these values in-code, we might want to make
14// our own nuget-esque `packages.config` file, that we can read at runtime to
15// resolve all Version requests.
16//
17// This would require nodes that currently accept a `Version(String)` to accept
18// a `Version(ReadVar<String>)`, but that shouldn't be a serious blocker.
19pub const AZCOPY: &str = "10.27.1";
20pub const AZURE_CLI: &str = "2.56.0";
21pub const CARGO_HACK: &str = "0.6.45";
22pub const CARGO_LLVM_COV: &str = "0.8.5";
23pub const DOTNET: &str = "8.0";
24pub const FUZZ: &str = "0.12.0";
25pub const GH_CLI: &str = "2.52.0";
26pub const MDBOOK: &str = "0.4.40";
27pub const MDBOOK_ADMONISH: &str = "1.18.0";
28pub const MDBOOK_MERMAID: &str = "0.14.0";
29pub const MU_MSVM: &str = "26.0.44";
30pub const NEXTEST: &str = "0.9.133";
31pub const NODEJS: &str = "24.x";
32// None disables hcl-dev builds and tests; Some(version) enables them.
33pub const OPENHCL_KERNEL_DEV_VERSION: Option<&str> = None;
34pub const OPENHCL_KERNEL_STABLE_VERSION: &str = "6.18.37.7";
35pub const OPENVMM_DEPS: &str = "0.3.0-185";
36pub const OPENVMM_MSHV_TEST_KERNEL: &str = "0.3.0-161";
37pub const PROTOC: &str = "27.1";
38
39flowey_request! {
40    pub enum Request {
41        /// Initialize the node, defaults to downloading everything
42        Init,
43        /// Override openvmm_deps with a local path for this architecture
44        LocalOpenvmmDeps(CommonArch, ReadVar<PathBuf>),
45        /// Override protoc with a local path
46        LocalProtoc(ReadVar<PathBuf>),
47        /// Override kernel with local paths (kernel binary, modules directory)
48        LocalKernel {
49            arch: CommonArch,
50            kernel: ReadVar<PathBuf>,
51            modules: ReadVar<PathBuf>,
52        },
53        /// Override UEFI mu_msvm with a local MSVM.fd path for this architecture
54        LocalUefi(CommonArch, ReadVar<PathBuf>),
55    }
56}
57
58new_flow_node!(struct Node);
59
60impl FlowNode for Node {
61    type Request = Request;
62
63    fn imports(ctx: &mut ImportCtx<'_>) {
64        ctx.import::<crate::resolve_openhcl_kernel_package::Node>();
65        ctx.import::<crate::resolve_openvmm_deps::Node>();
66        ctx.import::<crate::resolve_openvmm_qemu::Node>();
67        ctx.import::<crate::resolve_openvmm_test_initrd::Node>();
68        ctx.import::<crate::resolve_openvmm_test_linux_kernel::Node>();
69        ctx.import::<crate::resolve_openvmm_test_virtio_win::Node>();
70        ctx.import::<crate::download_uefi_mu_msvm::Node>();
71        ctx.import::<crate::cfg_rustup_version::Node>();
72        ctx.import::<flowey_lib_common::download_azcopy::Node>();
73        ctx.import::<flowey_lib_common::download_cargo_fuzz::Node>();
74        ctx.import::<flowey_lib_common::download_cargo_nextest::Node>();
75        ctx.import::<flowey_lib_common::download_gh_cli::Node>();
76        ctx.import::<flowey_lib_common::download_mdbook_admonish::Node>();
77        ctx.import::<flowey_lib_common::download_mdbook_mermaid::Node>();
78        ctx.import::<flowey_lib_common::download_mdbook::Node>();
79        ctx.import::<flowey_lib_common::resolve_protoc::Node>();
80        ctx.import::<flowey_lib_common::install_azure_cli::Node>();
81        ctx.import::<flowey_lib_common::install_cargo_hack::Node>();
82        ctx.import::<flowey_lib_common::install_cargo_llvm_cov::Node>();
83        ctx.import::<flowey_lib_common::install_dotnet_cli::Node>();
84        ctx.import::<flowey_lib_common::install_nodejs::Node>();
85    }
86
87    #[rustfmt::skip]
88    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
89        let mut local_openvmm_deps: BTreeMap<CommonArch, ReadVar<PathBuf>> = BTreeMap::new();
90        let mut local_protoc: Option<ReadVar<PathBuf>> = None;
91        let mut local_kernel: BTreeMap<CommonArch, (ReadVar<PathBuf>, ReadVar<PathBuf>)> = BTreeMap::new();
92        let mut local_uefi: BTreeMap<CommonArch, ReadVar<PathBuf>> = BTreeMap::new();
93
94        for req in requests {
95            match req {
96                Request::Init => {
97                    // No-op, just ensures the node runs with defaults
98                }
99                Request::LocalOpenvmmDeps(arch, path) => {
100                    if local_openvmm_deps.contains_key(&arch) {
101                        anyhow::bail!(
102                            "OpenvmmDepsPath for {:?} must not be specified multiple times",
103                            arch
104                        );
105                    }
106                    local_openvmm_deps.insert(arch, path);
107                }
108                Request::LocalProtoc(path) => {
109                    if local_protoc.is_some() {
110                        anyhow::bail!("ProtocPath must not be specified multiple times");
111                    }
112                    local_protoc = Some(path);
113                }
114                Request::LocalKernel { arch, kernel, modules } => {
115                    if local_kernel.contains_key(&arch) {
116                        anyhow::bail!(
117                            "LocalKernel for {:?} must not be specified multiple times",
118                            arch
119                        );
120                    }
121                    local_kernel.insert(arch, (kernel, modules));
122                }
123                Request::LocalUefi(arch, path) => {
124                    if local_uefi.contains_key(&arch) {
125                        anyhow::bail!(
126                            "LocalUefi for {:?} must not be specified multiple times",
127                            arch
128                        );
129                    }
130                    local_uefi.insert(arch, path);
131                }
132            }
133        }
134
135        // Track whether we have local paths for openvmm_deps and protoc
136        let has_local_openvmm_deps = !local_openvmm_deps.is_empty();
137        let has_local_protoc = local_protoc.is_some();
138        let has_local_kernel = !local_kernel.is_empty();
139        let has_local_uefi = !local_uefi.is_empty();
140
141        // Set up local paths for openvmm_deps if provided
142        if !local_openvmm_deps.is_empty() {
143            let deps_local_paths = local_openvmm_deps
144                .into_iter()
145                .map(|(arch, path)| (arch, ConfigVar(path)))
146                .collect();
147            ctx.config(crate::resolve_openvmm_deps::Config {
148                local_paths: deps_local_paths,
149                ..Default::default()
150            });
151        }
152
153        // Set up local path for protoc if provided
154        if let Some(protoc_path) = local_protoc {
155            ctx.config(flowey_lib_common::resolve_protoc::Config {
156                local_path: Some(ConfigVar(protoc_path)),
157                ..Default::default()
158            });
159        }
160
161        // Set up local paths for kernel if provided
162        if !local_kernel.is_empty() {
163            let kernel_local_paths = local_kernel
164                .into_iter()
165                .map(|(arch, (kernel, modules))| {
166                    (arch, (ConfigVar(kernel), ConfigVar(modules)))
167                })
168                .collect();
169            ctx.config(crate::resolve_openhcl_kernel_package::Config {
170                local_paths: kernel_local_paths,
171                ..Default::default()
172            });
173        }
174
175        // Set up local paths for UEFI if provided
176        if !local_uefi.is_empty() {
177            let uefi_local_paths = local_uefi
178                .into_iter()
179                .map(|(arch, path)| (arch, ConfigVar(path)))
180                .collect();
181            ctx.config(crate::download_uefi_mu_msvm::Config {
182                local_paths: uefi_local_paths,
183                ..Default::default()
184            });
185        }
186
187        // Only set kernel versions if we don't have local paths
188        // (versions are only needed for downloading)
189        if !has_local_kernel {
190            let mut versions = BTreeMap::from([
191                (
192                    OpenhclKernelPackageKind::Main,
193                    OPENHCL_KERNEL_STABLE_VERSION.into(),
194                ),
195                (
196                    OpenhclKernelPackageKind::Cvm,
197                    OPENHCL_KERNEL_STABLE_VERSION.into(),
198                ),
199            ]);
200            if let Some(version) = OPENHCL_KERNEL_DEV_VERSION {
201                versions.insert(OpenhclKernelPackageKind::Dev, version.into());
202                versions.insert(OpenhclKernelPackageKind::CvmDev, version.into());
203            }
204            ctx.config(crate::resolve_openhcl_kernel_package::Config {
205                versions,
206                ..Default::default()
207            });
208        }
209        if !has_local_openvmm_deps {
210            ctx.config(crate::resolve_openvmm_deps::Config {
211                version: Some(OPENVMM_DEPS.into()),
212                ..Default::default()
213            });
214        }
215        // The test Linux kernel and shared test initrd are always pulled
216        // from the openvmm-deps GitHub release; `LocalOpenvmmDeps` only
217        // overrides the (non-kernel/initrd) openvmm-deps tarball, since the
218        // 0.3.0 split moved the kernel and initrd into their own artifacts.
219        ctx.config(crate::resolve_openvmm_test_linux_kernel::Config {
220            version: Some(OPENVMM_DEPS.into()),
221            mshv_version: Some(OPENVMM_MSHV_TEST_KERNEL.into()),
222            ..Default::default()
223        });
224        ctx.config(crate::resolve_openvmm_test_initrd::Config {
225            version: Some(OPENVMM_DEPS.into()),
226            ..Default::default()
227        });
228        ctx.config(crate::resolve_openvmm_test_virtio_win::Config {
229            version: Some(OPENVMM_DEPS.into()),
230            ..Default::default()
231        });
232        ctx.config(crate::resolve_openvmm_qemu::Config {
233            version: Some(OPENVMM_DEPS.into()),
234            ..Default::default()
235        });
236        if !has_local_uefi {
237            ctx.config(crate::download_uefi_mu_msvm::Config {
238                version: Some(MU_MSVM.into()),
239                ..Default::default()
240            });
241        }
242        ctx.config(flowey_lib_common::download_azcopy::Config {
243            version: Some(AZCOPY.into()),
244        });
245        ctx.config(flowey_lib_common::download_cargo_fuzz::Config {
246            version: Some(FUZZ.into()),
247        });
248        ctx.config(flowey_lib_common::install_cargo_hack::Config {
249            version: Some(CARGO_HACK.into()),
250        });
251        ctx.config(flowey_lib_common::install_cargo_llvm_cov::Config {
252            version: Some(CARGO_LLVM_COV.into()),
253        });
254        ctx.config(flowey_lib_common::download_cargo_nextest::Config {
255            version: Some(NEXTEST.into()),
256        });
257        ctx.config(flowey_lib_common::download_gh_cli::Config {
258            version: Some(GH_CLI.into()),
259        });
260        ctx.config(flowey_lib_common::download_mdbook::Config {
261            version: Some(MDBOOK.into()),
262        });
263        ctx.config(flowey_lib_common::download_mdbook_admonish::Config {
264            version: Some(MDBOOK_ADMONISH.into()),
265        });
266        ctx.config(flowey_lib_common::download_mdbook_mermaid::Config {
267            version: Some(MDBOOK_MERMAID.into()),
268        });
269        if !has_local_protoc {
270            ctx.config(flowey_lib_common::resolve_protoc::Config {
271                version: Some(PROTOC.into()),
272                ..Default::default()
273            });
274        }
275        ctx.config(flowey_lib_common::install_azure_cli::Config {
276            version: Some(AZURE_CLI.into()),
277            ..Default::default()
278        });
279        ctx.config(flowey_lib_common::install_dotnet_cli::Config {
280            version: Some(DOTNET.into()),
281            ..Default::default()
282        });
283        ctx.config(flowey_lib_common::install_nodejs::Config {
284            version: Some(NODEJS.into()),
285            ..Default::default()
286        });
287        ctx.req(crate::cfg_rustup_version::Request::Init);
288        Ok(())
289    }
290}