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