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::resolve_openhcl_kernel_package::OpenhclKernelPackageKind;
9use crate::run_cargo_build::common::CommonArch;
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 FUZZ: &str = "0.12.0";
22pub const GH_CLI: &str = "2.52.0";
23pub const MDBOOK: &str = "0.4.40";
24pub const MDBOOK_ADMONISH: &str = "1.18.0";
25pub const MDBOOK_MERMAID: &str = "0.14.0";
26pub const MU_MSVM: &str = "25.1.11";
27pub const NEXTEST: &str = "0.9.101";
28pub const NODEJS: &str = "24.x";
29// N.B. Kernel version numbers for dev and stable branches are not directly
30//      comparable. They originate from separate branches, and the fourth digit
31//      increases with each release from the respective branch.
32pub const OPENHCL_KERNEL_DEV_VERSION: &str = "6.12.52.5";
33pub const OPENHCL_KERNEL_STABLE_VERSION: &str = "6.12.52.5";
34pub const OPENVMM_DEPS: &str = "0.1.0-20260319.1";
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::download_uefi_mu_msvm::Node>();
65        ctx.import::<crate::cfg_rustup_version::Node>();
66        ctx.import::<flowey_lib_common::download_azcopy::Node>();
67        ctx.import::<flowey_lib_common::download_cargo_fuzz::Node>();
68        ctx.import::<flowey_lib_common::download_cargo_nextest::Node>();
69        ctx.import::<flowey_lib_common::download_gh_cli::Node>();
70        ctx.import::<flowey_lib_common::download_mdbook_admonish::Node>();
71        ctx.import::<flowey_lib_common::download_mdbook_mermaid::Node>();
72        ctx.import::<flowey_lib_common::download_mdbook::Node>();
73        ctx.import::<flowey_lib_common::resolve_protoc::Node>();
74        ctx.import::<flowey_lib_common::install_azure_cli::Node>();
75        ctx.import::<flowey_lib_common::install_nodejs::Node>();
76    }
77
78    #[rustfmt::skip]
79    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
80        let mut local_openvmm_deps: BTreeMap<CommonArch, ReadVar<PathBuf>> = BTreeMap::new();
81        let mut local_protoc: Option<ReadVar<PathBuf>> = None;
82        let mut local_kernel: BTreeMap<CommonArch, (ReadVar<PathBuf>, ReadVar<PathBuf>)> = BTreeMap::new();
83        let mut local_uefi: BTreeMap<CommonArch, ReadVar<PathBuf>> = BTreeMap::new();
84
85        for req in requests {
86            match req {
87                Request::Init => {
88                    // No-op, just ensures the node runs with defaults
89                }
90                Request::LocalOpenvmmDeps(arch, path) => {
91                    if local_openvmm_deps.contains_key(&arch) {
92                        anyhow::bail!(
93                            "OpenvmmDepsPath for {:?} must not be specified multiple times",
94                            arch
95                        );
96                    }
97                    local_openvmm_deps.insert(arch, path);
98                }
99                Request::LocalProtoc(path) => {
100                    if local_protoc.is_some() {
101                        anyhow::bail!("ProtocPath must not be specified multiple times");
102                    }
103                    local_protoc = Some(path);
104                }
105                Request::LocalKernel { arch, kernel, modules } => {
106                    if local_kernel.contains_key(&arch) {
107                        anyhow::bail!(
108                            "LocalKernel for {:?} must not be specified multiple times",
109                            arch
110                        );
111                    }
112                    local_kernel.insert(arch, (kernel, modules));
113                }
114                Request::LocalUefi(arch, path) => {
115                    if local_uefi.contains_key(&arch) {
116                        anyhow::bail!(
117                            "LocalUefi for {:?} must not be specified multiple times",
118                            arch
119                        );
120                    }
121                    local_uefi.insert(arch, path);
122                }
123            }
124        }
125
126        // Track whether we have local paths for openvmm_deps and protoc
127        let has_local_openvmm_deps = !local_openvmm_deps.is_empty();
128        let has_local_protoc = local_protoc.is_some();
129        let has_local_kernel = !local_kernel.is_empty();
130        let has_local_uefi = !local_uefi.is_empty();
131
132        // Set up local paths for openvmm_deps if provided
133        for (arch, path) in local_openvmm_deps {
134            let openvmm_deps_arch = match arch {
135                CommonArch::X86_64 => crate::resolve_openvmm_deps::OpenvmmDepsArch::X86_64,
136                CommonArch::Aarch64 => crate::resolve_openvmm_deps::OpenvmmDepsArch::Aarch64,
137            };
138
139            ctx.req(crate::resolve_openvmm_deps::Request::LocalPath(
140                openvmm_deps_arch,
141                path,
142            ));
143        }
144
145        // Set up local path for protoc if provided
146        if let Some(protoc_path) = local_protoc {
147            ctx.req(flowey_lib_common::resolve_protoc::Request::LocalPath(
148                protoc_path,
149            ));
150        }
151
152        // Set up local paths for kernel if provided
153        for (arch, (kernel, modules)) in local_kernel {
154            let kernel_arch = match arch {
155                CommonArch::X86_64 => crate::resolve_openhcl_kernel_package::OpenhclKernelPackageArch::X86_64,
156                CommonArch::Aarch64 => crate::resolve_openhcl_kernel_package::OpenhclKernelPackageArch::Aarch64,
157            };
158            ctx.req(crate::resolve_openhcl_kernel_package::Request::SetLocal {
159                arch: kernel_arch,
160                kernel,
161                modules,
162            });
163        }
164
165        // Set up local paths for UEFI if provided
166        for (arch, path) in local_uefi {
167            let uefi_arch = match arch {
168                CommonArch::X86_64 => crate::download_uefi_mu_msvm::MuMsvmArch::X86_64,
169                CommonArch::Aarch64 => crate::download_uefi_mu_msvm::MuMsvmArch::Aarch64,
170            };
171            ctx.req(crate::download_uefi_mu_msvm::Request::LocalPath(uefi_arch, path));
172        }
173
174        // Only set kernel versions if we don't have local paths
175        // (versions are only needed for downloading)
176        if !has_local_kernel {
177            ctx.req(crate::resolve_openhcl_kernel_package::Request::SetVersion(OpenhclKernelPackageKind::Dev, OPENHCL_KERNEL_DEV_VERSION.into()));
178            ctx.req(crate::resolve_openhcl_kernel_package::Request::SetVersion(OpenhclKernelPackageKind::Main, OPENHCL_KERNEL_STABLE_VERSION.into()));
179            ctx.req(crate::resolve_openhcl_kernel_package::Request::SetVersion(OpenhclKernelPackageKind::Cvm, OPENHCL_KERNEL_STABLE_VERSION.into()));
180            ctx.req(crate::resolve_openhcl_kernel_package::Request::SetVersion(OpenhclKernelPackageKind::CvmDev, OPENHCL_KERNEL_DEV_VERSION.into()));
181        }
182        if !has_local_openvmm_deps {
183            ctx.req(crate::resolve_openvmm_deps::Request::Version(OPENVMM_DEPS.into()));
184        }
185        if !has_local_uefi {
186            ctx.req(crate::download_uefi_mu_msvm::Request::Version(MU_MSVM.into()));
187        }
188        ctx.req(flowey_lib_common::download_azcopy::Request::Version(AZCOPY.into()));
189        ctx.req(flowey_lib_common::download_cargo_fuzz::Request::Version(FUZZ.into()));
190        ctx.req(flowey_lib_common::download_cargo_nextest::Request::Version(NEXTEST.into()));
191        ctx.req(flowey_lib_common::download_gh_cli::Request::Version(GH_CLI.into()));
192        ctx.req(flowey_lib_common::download_mdbook::Request::Version(MDBOOK.into()));
193        ctx.req(flowey_lib_common::download_mdbook_admonish::Request::Version(MDBOOK_ADMONISH.into()));
194        ctx.req(flowey_lib_common::download_mdbook_mermaid::Request::Version(MDBOOK_MERMAID.into()));
195        if !has_local_protoc {
196            ctx.req(flowey_lib_common::resolve_protoc::Request::Version(PROTOC.into()));
197        }
198        ctx.req(flowey_lib_common::install_azure_cli::Request::Version(AZURE_CLI.into()));
199        ctx.req(flowey_lib_common::install_nodejs::Request::Version(NODEJS.into()));
200        ctx.req(crate::cfg_rustup_version::Request::Init);
201        Ok(())
202    }
203}