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 RUSTUP_TOOLCHAIN: &str = "1.91.1";
27pub const MU_MSVM: &str = "25.1.9";
28pub const NEXTEST: &str = "0.9.101";
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.12.52.4";
34pub const OPENHCL_KERNEL_STABLE_VERSION: &str = "6.12.52.4";
35pub const OPENVMM_DEPS: &str = "0.1.0-20250403.3";
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, PathBuf),
44        /// Override protoc with a local path
45        LocalProtoc(PathBuf),
46        /// Override kernel with local paths (kernel binary, modules directory)
47        LocalKernel {
48            arch: CommonArch,
49            kernel: PathBuf,
50            modules: PathBuf,
51        },
52    }
53}
54
55new_flow_node!(struct Node);
56
57impl FlowNode for Node {
58    type Request = Request;
59
60    fn imports(ctx: &mut ImportCtx<'_>) {
61        ctx.import::<crate::resolve_openhcl_kernel_package::Node>();
62        ctx.import::<crate::resolve_openvmm_deps::Node>();
63        ctx.import::<crate::download_uefi_mu_msvm::Node>();
64        ctx.import::<flowey_lib_common::download_azcopy::Node>();
65        ctx.import::<flowey_lib_common::download_cargo_fuzz::Node>();
66        ctx.import::<flowey_lib_common::download_cargo_nextest::Node>();
67        ctx.import::<flowey_lib_common::download_gh_cli::Node>();
68        ctx.import::<flowey_lib_common::download_mdbook_admonish::Node>();
69        ctx.import::<flowey_lib_common::download_mdbook_mermaid::Node>();
70        ctx.import::<flowey_lib_common::download_mdbook::Node>();
71        ctx.import::<flowey_lib_common::resolve_protoc::Node>();
72        ctx.import::<flowey_lib_common::install_azure_cli::Node>();
73        ctx.import::<flowey_lib_common::install_nodejs::Node>();
74        ctx.import::<flowey_lib_common::install_rust::Node>();
75    }
76
77    #[rustfmt::skip]
78    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
79        let mut local_openvmm_deps: BTreeMap<CommonArch, PathBuf> = BTreeMap::new();
80        let mut local_protoc: Option<PathBuf> = None;
81        let mut local_kernel: BTreeMap<CommonArch, (PathBuf, PathBuf)> = BTreeMap::new();
82
83        for req in requests {
84            match req {
85                Request::Init => {
86                    // No-op, just ensures the node runs with defaults
87                }
88                Request::LocalOpenvmmDeps(arch, path) => {
89                    // Check that for every arch that shows up, the path is always the same
90                    if let Some(existing_path) = local_openvmm_deps.get(&arch) {
91                        if existing_path != &path {
92                            anyhow::bail!(
93                                "OpenvmmDepsPath for {:?} must be consistent across requests",
94                                arch
95                            );
96                        }
97                    } else {
98                        local_openvmm_deps.insert(arch, path);
99                    }
100                }
101                Request::LocalProtoc(path) => {
102                    same_across_all_reqs("ProtocPath", &mut local_protoc, path)?;
103                }
104                Request::LocalKernel { arch, kernel, modules } => {
105                    let paths = (kernel, modules);
106                    if let Some(existing) = local_kernel.get(&arch) {
107                        if existing != &paths {
108                            anyhow::bail!(
109                                "LocalKernel for {:?} must be consistent across requests",
110                                arch
111                            );
112                        }
113                    } else {
114                        local_kernel.insert(arch, paths);
115                    }
116                }
117            }
118        }
119
120        // Track whether we have local paths for openvmm_deps and protoc
121        let has_local_openvmm_deps = !local_openvmm_deps.is_empty();
122        let has_local_protoc = local_protoc.is_some();
123        let has_local_kernel = !local_kernel.is_empty();
124
125        // Set up local paths for openvmm_deps if provided
126        for (arch, path) in local_openvmm_deps {
127            let openvmm_deps_arch = match arch {
128                CommonArch::X86_64 => crate::resolve_openvmm_deps::OpenvmmDepsArch::X86_64,
129                CommonArch::Aarch64 => crate::resolve_openvmm_deps::OpenvmmDepsArch::Aarch64,
130            };
131
132            ctx.req(crate::resolve_openvmm_deps::Request::LocalPath(
133                openvmm_deps_arch,
134                path,
135            ));
136        }
137
138        // Set up local path for protoc if provided
139        if let Some(protoc_path) = local_protoc {
140            ctx.req(flowey_lib_common::resolve_protoc::Request::LocalPath(
141                protoc_path,
142            ));
143        }
144
145        // Set up local paths for kernel if provided
146        for (arch, (kernel, modules)) in local_kernel {
147            let kernel_arch = match arch {
148                CommonArch::X86_64 => crate::resolve_openhcl_kernel_package::OpenhclKernelPackageArch::X86_64,
149                CommonArch::Aarch64 => crate::resolve_openhcl_kernel_package::OpenhclKernelPackageArch::Aarch64,
150            };
151            ctx.req(crate::resolve_openhcl_kernel_package::Request::SetLocal {
152                arch: kernel_arch,
153                kernel,
154                modules,
155            });
156        }
157
158        // Only set kernel versions if we don't have local paths
159        // (versions are only needed for downloading)
160        if !has_local_kernel {
161            ctx.req(crate::resolve_openhcl_kernel_package::Request::SetVersion(OpenhclKernelPackageKind::Dev, OPENHCL_KERNEL_DEV_VERSION.into()));
162            ctx.req(crate::resolve_openhcl_kernel_package::Request::SetVersion(OpenhclKernelPackageKind::Main, OPENHCL_KERNEL_STABLE_VERSION.into()));
163            ctx.req(crate::resolve_openhcl_kernel_package::Request::SetVersion(OpenhclKernelPackageKind::Cvm, OPENHCL_KERNEL_STABLE_VERSION.into()));
164            ctx.req(crate::resolve_openhcl_kernel_package::Request::SetVersion(OpenhclKernelPackageKind::CvmDev, OPENHCL_KERNEL_DEV_VERSION.into()));
165        }
166        if !has_local_openvmm_deps {
167            ctx.req(crate::resolve_openvmm_deps::Request::Version(OPENVMM_DEPS.into()));
168        }
169        ctx.req(crate::download_uefi_mu_msvm::Request::Version(MU_MSVM.into()));
170        ctx.req(flowey_lib_common::download_azcopy::Request::Version(AZCOPY.into()));
171        ctx.req(flowey_lib_common::download_cargo_fuzz::Request::Version(FUZZ.into()));
172        ctx.req(flowey_lib_common::download_cargo_nextest::Request::Version(NEXTEST.into()));
173        ctx.req(flowey_lib_common::download_gh_cli::Request::Version(GH_CLI.into()));
174        ctx.req(flowey_lib_common::download_mdbook::Request::Version(MDBOOK.into()));
175        ctx.req(flowey_lib_common::download_mdbook_admonish::Request::Version(MDBOOK_ADMONISH.into()));
176        ctx.req(flowey_lib_common::download_mdbook_mermaid::Request::Version(MDBOOK_MERMAID.into()));
177        if !has_local_protoc {
178            ctx.req(flowey_lib_common::resolve_protoc::Request::Version(PROTOC.into()));
179        }
180        ctx.req(flowey_lib_common::install_azure_cli::Request::Version(AZURE_CLI.into()));
181        ctx.req(flowey_lib_common::install_nodejs::Request::Version(NODEJS.into()));
182        ctx.req(flowey_lib_common::install_rust::Request::Version(RUSTUP_TOOLCHAIN.into()));
183        Ok(())
184    }
185}