1use flowey::node::prelude::ReadVar;
7use flowey::pipeline::prelude::*;
8use flowey_lib_hvlite::build_openhcl_igvm_from_recipe::OpenhclIgvmRecipe;
9use flowey_lib_hvlite::build_openhcl_igvm_from_recipe::OpenhclKernelPackage;
10use flowey_lib_hvlite::run_cargo_build::common::CommonArch;
11use std::path::PathBuf;
12
13#[derive(clap::ValueEnum, Copy, Clone)]
14pub enum OpenhclRecipeCli {
15 Aarch64,
17 Aarch64Devkern,
19 X64Cvm,
21 X64CvmDevkern,
23 X64TestLinuxDirect,
26 X64TestLinuxDirectDevkern,
29 X64,
31 X64Devkern,
33}
34
35#[derive(clap::Args)]
37pub struct BuildIgvmCli<Recipe = OpenhclRecipeCli>
38where
39 Recipe: clap::ValueEnum + Clone + Send + Sync + 'static,
42{
43 pub recipe: Recipe,
52
53 #[clap(long)]
58 pub release: bool,
59
60 #[clap(long)]
63 pub release_cfg: bool,
64
65 #[clap(long)]
67 pub verbose: bool,
68
69 #[clap(long)]
71 pub locked: bool,
72
73 #[clap(long)]
75 pub install_missing_deps: bool,
76
77 #[clap(flatten)]
78 pub customizations: BuildIgvmCliCustomizations,
79}
80
81#[derive(clap::Args)]
82#[clap(next_help_heading = "Customizations")]
83pub struct BuildIgvmCliCustomizations {
84 #[clap(long, short = 'o')]
88 pub build_label: Option<String>,
89
90 #[clap(long)]
92 pub override_kernel_pkg: Option<KernelPackageKindCli>,
93
94 #[clap(long)]
96 pub override_openvmm_hcl_feature: Vec<String>,
97
98 #[clap(long)]
101 pub override_arch: Option<BuildIgvmArch>,
102
103 #[clap(long)]
106 pub override_manifest: Option<PathBuf>,
107
108 #[clap(long, requires = "release")]
114 pub with_perf_tools: bool,
115
116 #[clap(long)]
121 pub with_debuginfo: bool,
122
123 #[clap(long)]
125 pub custom_openvmm_hcl: Option<PathBuf>,
126
127 #[clap(long)]
129 pub custom_openhcl_boot: Option<PathBuf>,
130
131 #[clap(long)]
133 pub custom_uefi: Option<PathBuf>,
134
135 #[clap(long)]
138 pub custom_kernel: Option<PathBuf>,
139
140 #[clap(long)]
143 pub custom_kernel_modules: Option<PathBuf>,
144
145 #[clap(long)]
150 pub custom_vtl0_kernel: Option<PathBuf>,
151
152 #[clap(long)]
154 pub custom_layer: Vec<PathBuf>,
155
156 #[clap(long)]
158 pub custom_directory: Vec<PathBuf>,
159
160 #[clap(long)]
162 pub custom_extra_rootfs: Vec<PathBuf>,
163
164 #[clap(long)]
166 pub with_sidecar: bool,
167
168 #[clap(long, requires = "with_sidecar")]
171 pub custom_sidecar: Option<PathBuf>,
172}
173
174#[derive(clap::ValueEnum, Copy, Clone, PartialEq, Eq, Debug)]
175pub enum KernelPackageKindCli {
176 Main,
178 Cvm,
180 Dev,
182 CvmDev,
184}
185
186#[derive(clap::ValueEnum, Copy, Clone, PartialEq, Eq, Debug)]
187pub enum BuildIgvmArch {
188 X86_64,
189 Aarch64,
190}
191
192pub fn bail_if_running_in_ci() -> anyhow::Result<()> {
193 const OVERRIDE_ENV: &str = "I_HAVE_A_GOOD_REASON_TO_RUN_BUILD_IGVM_IN_CI";
194
195 if std::env::var(OVERRIDE_ENV).is_ok() {
196 return Ok(());
197 }
198
199 for ci_env in ["TF_BUILD", "GITHUB_ACTIONS"] {
200 if std::env::var(ci_env).is_ok() {
201 log::warn!("Detected that {ci_env} is set");
202 log::warn!("");
203 log::warn!("Do not use `build-igvm` in CI scripts!");
204 log::warn!(
205 "This is a local-only, inner-dev-loop tool to build IGVM files, with an UNSTABLE CLI."
206 );
207 log::warn!("");
208 log::warn!(
209 "Automated pipelines should use the underlying `flowey` nodes that power build-igvm directly, _without_ relying on its CLI!"
210 );
211 log::warn!("");
212 log::warn!(
213 "If you _really_ know what you're doing, you can set {OVERRIDE_ENV} to disable this error."
214 );
215 anyhow::bail!("attempted to run `build-igvm` in CI")
216 }
217 }
218
219 Ok(())
220}
221
222impl IntoPipeline for BuildIgvmCli {
223 fn into_pipeline(self, backend_hint: PipelineBackendHint) -> anyhow::Result<Pipeline> {
224 if !matches!(backend_hint, PipelineBackendHint::Local) {
225 anyhow::bail!("build-igvm is for local use only")
226 }
227
228 bail_if_running_in_ci()?;
229
230 let openvmm_repo = flowey_lib_common::git_checkout::RepoSource::ExistingClone(
231 ReadVar::from_static(crate::repo_root()),
232 );
233
234 let Self {
235 recipe,
236 release,
237 release_cfg,
238 verbose,
239 locked,
240 install_missing_deps,
241 customizations:
242 BuildIgvmCliCustomizations {
243 build_label,
244 override_kernel_pkg,
245 override_openvmm_hcl_feature,
246 override_arch,
247 override_manifest,
248 with_perf_tools,
249 with_debuginfo,
250 custom_openvmm_hcl,
251 custom_openhcl_boot,
252 custom_uefi,
253 custom_kernel,
254 custom_kernel_modules,
255 custom_vtl0_kernel,
256 custom_layer,
257 custom_directory,
258 with_sidecar,
259 custom_sidecar,
260 mut custom_extra_rootfs,
261 },
262 } = self;
263
264 if with_perf_tools {
265 custom_extra_rootfs.push(crate::repo_root().join("openhcl/perftoolsfs.config"));
266 }
267
268 let mut pipeline = Pipeline::new();
269
270 let (pub_out_dir, _) = pipeline.new_artifact("build-igvm");
271
272 pipeline
273 .new_job(
274 FlowPlatform::host(backend_hint),
275 FlowArch::host(backend_hint),
276 "build-igvm",
277 )
278 .dep_on(|_| flowey_lib_hvlite::_jobs::cfg_versions::Request {})
279 .dep_on(
280 |_| flowey_lib_hvlite::_jobs::cfg_hvlite_reposource::Params {
281 hvlite_repo_source: openvmm_repo,
282 },
283 )
284 .dep_on(|_| flowey_lib_hvlite::_jobs::cfg_common::Params {
285 local_only: Some(flowey_lib_hvlite::_jobs::cfg_common::LocalOnlyParams {
286 interactive: true,
287 auto_install: install_missing_deps,
288 force_nuget_mono: false, external_nuget_auth: false,
290 ignore_rust_version: true,
291 }),
292 verbose: ReadVar::from_static(verbose),
293 locked,
294 deny_warnings: false,
295 })
296 .dep_on(|ctx| flowey_lib_hvlite::_jobs::local_build_igvm::Params {
297 artifact_dir: ctx.publish_artifact(pub_out_dir),
298 done: ctx.new_done_handle(),
299
300 base_recipe: match recipe {
301 OpenhclRecipeCli::X64 => OpenhclIgvmRecipe::X64,
302 OpenhclRecipeCli::X64Devkern => OpenhclIgvmRecipe::X64Devkern,
303 OpenhclRecipeCli::X64TestLinuxDirect => OpenhclIgvmRecipe::X64TestLinuxDirect,
304 OpenhclRecipeCli::X64TestLinuxDirectDevkern => {
305 OpenhclIgvmRecipe::X64TestLinuxDirectDevkern
306 }
307 OpenhclRecipeCli::X64Cvm => OpenhclIgvmRecipe::X64Cvm,
308 OpenhclRecipeCli::X64CvmDevkern => OpenhclIgvmRecipe::X64CvmDevkern,
309 OpenhclRecipeCli::Aarch64 => OpenhclIgvmRecipe::Aarch64,
310 OpenhclRecipeCli::Aarch64Devkern => OpenhclIgvmRecipe::Aarch64Devkern,
311 },
312 release,
313 release_cfg,
314
315 customizations: flowey_lib_hvlite::_jobs::local_build_igvm::Customizations {
316 build_label,
317 override_arch: override_arch.map(|a| match a {
318 BuildIgvmArch::X86_64 => CommonArch::X86_64,
319 BuildIgvmArch::Aarch64 => CommonArch::Aarch64,
320 }),
321 with_perf_tools,
322 with_debuginfo,
323 override_kernel_pkg: override_kernel_pkg.map(|p| match p {
324 KernelPackageKindCli::Main => OpenhclKernelPackage::Main,
325 KernelPackageKindCli::Cvm => OpenhclKernelPackage::Cvm,
326 KernelPackageKindCli::Dev => OpenhclKernelPackage::Dev,
327 KernelPackageKindCli::CvmDev => OpenhclKernelPackage::CvmDev,
328 }),
329 with_sidecar,
330 custom_extra_rootfs,
331 override_openvmm_hcl_feature,
332 custom_sidecar,
333 override_manifest,
334 custom_openvmm_hcl,
335 custom_openhcl_boot,
336 custom_uefi,
337 custom_kernel,
338 custom_kernel_modules,
339 custom_vtl0_kernel,
340 custom_layer,
341 custom_directory,
342 },
343 })
344 .finish();
345
346 Ok(pipeline)
347 }
348}