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