Repository navigation
ci: build the Linux OpenVMM VMM tests once for the KVM and MSHV jobs - #708
Open
Pedro Henrique Penna (ppenna) wants to merge 2 commits into
Open
Pedro Henrique Penna (ppenna) wants to merge 2 commits into
Pedro Henrique Penna (ppenna) wants to merge 2 commits into
Conversation
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Windows manifest paths can escape the content directory; cross-runner execution also still needs end-to-end CI validation.
1 open issue
What changed in this PR
Builds Linux OpenVMM VMM tests once for KVM and MSHV, reducing duplicate CI work while retaining the combined WHP job.
Changes:
- Adds build-only and prebuilt-content CLI commands.
- Splits Linux CI into a producer and backend consumers, updating required and publishing gates.
- Adds handoff validation tests and documentation.
| File | Description |
|---|---|
| scripts/test_nvx_tools.py | Tests CLI, manifests, handoffs, and workflow gates. |
| scripts/nvx.py | Exposes build-only and content-consumer options. |
| scripts/nvx_tools/ci.py | Implements content production, validation, and execution. |
| doc/usage.md | Documents new command options. |
| doc/ci.md | Explains job dependencies and artifact handoffs. |
| .github/workflows/ci.yml | Shares Linux test builds and updates gating. |
Review effort: Balanced
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/build-vmm-tests-once
branch
from
October 21, 2026 15:27
3673a50 to
9432843
Compare
This was referenced Oct 21, 2026
test-openvmm built OpenVMM's VMM tests and ran them in one command, so every CI job that ran a backend's tests also built them: the KVM and MSHV jobs built the same Linux tests, and each job waited for the guest artifacts before it started its build, although only the tests boot the NVX kernel and initramfs. build-openvmm-tests builds the tests of one or more backends of the host's operating system into a test content directory without running them. It runs OpenVMM's vmm-tests-run in build-only mode on the union of the backends' filters, which writes the nextest archive, OpenVMM, the guest agents, the test firmware and kernels, and the flowey_hvlite that runs vmm-tests-run-target. It then reads that runner and its options from the run script that the build writes, and records them in nvx-openvmm-tests.json with the OpenVMM revision and whether its checkout was clean, the Rust release, each backend's filter, and every file's size and executable bit, so the content names what it holds and the inputs that built it. The run script is parsed strictly: it must run vmm-tests-run-target on the built filter in its own directory, with a runner inside it and only the options that the pinned flowey writes, so that a change of its format fails the build instead of running other tests. test-openvmm --content runs one backend's filter from such a directory with vmm-tests-run-target, which needs neither the OpenVMM checkout nor a build, only the guest artifacts: the microVM TTRPC test reads the NVX kernel and initramfs from its environment when it runs. It refuses content built from another OpenVMM revision than the gitlink or for another filter than the backend's, and content that lacks a file or holds a truncated one, and it restores the executable bits that an artifact download drops. Without --content, test-openvmm builds and runs the tests as before. Like it, the build links with /Brepro on Windows. doc/usage.md describes both commands, including that the pinned vmm-tests-run-target checks for Hyper-V on Windows whatever tests it runs. Tests cover the union filter, both run script formats and every rejection of a script, the build's commands, environment, and manifest, the refusal of another OS's backends and of used directories, the consumer's command, environment, and restored executable bits, and the refusal of foreign, malformed, and incomplete content. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Each Linux leg of openvmm-vmm-tests built the same x86_64-unknown-linux-gnu tests before it ran its backend's filter, and every leg waited for the guest artifacts before it started its build. In reference run 39585909588, the KVM and MSHV legs each spent about five minutes on that build, and their logs resolve the same artifacts and lay out the same test content. build-openvmm-vmm-tests-linux now builds the KVM and MSHV tests once, with build-openvmm-tests, on a general KVM runner, whose sccache holds that build, and hands the content to the two openvmm-vmm-tests-linux legs as the one-day openvmm-vmm-tests-linux artifact. The build boots no guest, so it starts with the OpenVMM binary producers instead of waiting for the guest artifacts, and it takes over the vmm-tests input and Cargo caches. Each leg downloads the content and the guest artifacts and runs its backend's own filter with test-openvmm --content, without checking out or building OpenVMM, and it uploads its diagnostics under the same openvmm-vmm-tests-<os>-<backend>-<run-id>-<run-attempt> name, now from the content's test_results. The upload keeps the hidden .config/nextest.toml and replaces an earlier attempt's content, so a rerun of the build replaces it and a rerun of a failed leg reuses it. The WHP tests stay in openvmm-vmm-tests-windows, which still builds and runs them in one job: on Windows, the pinned vmm-tests-run-target requires Hyper-V whatever tests it runs, through Get-VM and two registry values or administrator rights, and the WHP runners run jobs as Network Service. A Windows build job can follow once vmm-tests-run-target checks only what the tests of its build need. The build runs exactly when its test jobs do: whenever the change selects the VMM tests, since the classifier then also selects the guest artifacts that they boot, or when the change detector fails. It therefore reads run-openvmm-vmm-tests alone. check-required-ci expects it with them, and the development release and performance persistence, which accepted any skipped VMM-test job, now require the three jobs to succeed, or all three to be skipped because openvmm-changes selected no VMM tests, so that a failed or unexpectedly skipped build or test blocks them. Fork, draft, and path-filter gating, cancellation, and the cache saves stay as they were. Tests cover the build and test jobs, their runners, needs, and conditions, the change detector's outputs that they and the two gates read, the artifact's name, path, hidden files, overwrite, and retention, the order of the downloads and the tests, the diagnostics of both operating systems, the required-check policy, the release and persistence gate, the cache keys, and the derivation of the VMM tests' inputs from every job that builds or runs them. doc/ci.md describes the build, its consumers, and the handoff. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/build-vmm-tests-once
branch
from
October 21, 2026 23:05
9432843 to
2f85af8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Part of #690.
Part of #430.
Summary
The KVM and MSHV legs of
openvmm-vmm-testseach built the same Linux OpenVMM VMM tests before running their backend's filter, and every leg waited for the guest artifacts before it started building. This PR builds the Linux tests once, in a build-only producer that starts beside the guest-artifact build, and hands the test content to two backend consumers that only run their existing filters with OpenVMM'svmm-tests-run-target.The WHP tests can't move yet: at the pinned OpenVMM revision,
vmm-tests-run-targetrequires Hyper-V on Windows whatever tests it runs, which the WHP runners can't provide (see WHP below). The WHP job therefore still builds and runs its tests in one job, unchanged, under the new job IDopenvmm-vmm-tests-windows.Why
Resolved selectionsline: thex86_64-unknown-linux-gnunextest archive, OpenVMM,openvmm_vhost, the musl pipette,guest_test_uefi, the test kernel, initrd, bzImage, and UEFI firmware) and lay out the same test content.devpushes from 2026-10-20 18:13 to 2026-10-21 13:32 UTC (runs and data on #690), the Linux legs took a median 15.6 (KVM) and 9.9 (MSHV) minutes, 25.6 Linux runner-minutes per run, and all three legs started only after the guest artifacts, which ran cold in 9 of the 14 runs for a median 5.3 minutes.Changes
nvx.py build-openvmm-testsandtest-openvmm --content(first commit)build-openvmm-tests --backend B [--backend B ...] --output DIRrunscargo xflowey vmm-tests-run --build-onlyon the union of the backends' filters ((<kvm>) | (<mshv>)), which writes the nextest archive, OpenVMM, the guest agents, the test firmware and kernels, and aflowey_hvlitethat runsvmm-tests-run-target. It parses the run script that the build writes strictly (runner inside the directory,--dir ., the built filter, and only the options that the pinned flowey writes), and writesnvx-openvmm-tests.json: the format, the OpenVMM revision and whether its checkout was clean, the Rust release, each backend's filter, the build filter, the runner and its options, and every file's size and executable bit.test-openvmm --backend B --content DIRruns backend B's own filter from such a directory with itsvmm-tests-run-target, without the OpenVMM checkout or a build. It refuses content of another OpenVMM revision than the gitlink, of another filter, or with a missing or truncated file, and it restores the executable bits that artifact downloads drop. It sets the sameOPENVMM_MICROVM_TEST_KERNEL/INITRD,RUSTUP_TOOLCHAIN, andXDG_CACHE_HOMEas before. Without--content,test-openvmmbuilds and runs the tests as before. On Windows, the build links with/Brepro, astest-openvmmdoes since ci: link the Windows OpenVMM test builds with /Brepro for sccache #714.CI (second commit)
build-openvmm-vmm-tests-linux(new)openvmm-changesonlybuild-openvmm-tests --backend kvm --backend mshv; uploads the one-dayopenvmm-vmm-tests-linuxartifact (include-hidden-filesfor.config/nextest.toml,overwrite: true); restores and, ondevpushes, saves thevmm-testsinput and Cargo cachesopenvmm-vmm-tests-linux(KVM, MSHV legs)artifactsand the buildtest-openvmm --content; no OpenVMM checkout, no caches, no sccacheopenvmm-vmm-tests-windowsartifactsopenvmm-vmm-tests-<os>-<backend>-<run-id>-<run-attempt>names; Linux now collects<runner-temp>/openvmm-vmm-tests/test_results.run-openvmm-vmm-testsis set, which the classifier of ci: classify microVM tests, benchmarks, and artifact builds separately #712 sets only together withrun-guest-artifacts, or when the change detector fails, so it runs exactly when its consumers do, andrun-openvmm-vmm-tests=falseskips producer and consumers together. It reads that output alone, as ci: classify microVM tests, benchmarks, and artifact builds separately #712's one-output-per-job test requires.check-required-ciexpects it with them.Publish development releaseandPersist performance baseline, which accepted any skipped VMM-test job, now needopenvmm-changesand require the three VMM jobs to succeed, or all three to be skipped because the change selected no VMM tests, so a failed or unexpectedly skipped producer or consumer blocks them. Fork, draft, and path-filter gating, cancellation, and the eight cache saves' keys and guards are unchanged.doc/ci.mdgains an OpenVMM VMM tests section on the producer, consumers, handoff, manifest, and WHP;doc/usage.mddocuments both commands.WHP
At the pinned OpenVMM revision,
9f04d05c5since #661, whoseflowey/is identical to that ofd0bdbed8f,vmm-tests-run-targethard-codeshyperv: truefor Windows targets (flowey/flowey_hvlite/src/pipelines/vmm_tests_run_target.rs), soinstall_vmm_tests_external_depsrequiresGet-VMto succeed and theAllowFirmwareLoadFromFileandEnableAdditionalComPortsvalues underHKLM\Software\Microsoft\Windows NT\CurrentVersion\Virtualization, or, with--install-missing-deps, runsDISM /Online, which needs elevation. The WHP runners run jobs as Network Service (validate-runnerenforcesS-1-5-20), which the runner setup doesn't add to Hyper-V Administrators, and the setup sets neither value. The combinedvmm-tests-runcomputeshypervfrom the selected tests, which is why the WHP job works today. Splitting WHP needsvmm-tests-run-targetto take the dependencies that the build resolved, for example the--needs-hypervand--needs-whpoptions of commit79eb62981on thecopilot/vmm-tests-run-target-depsbranch ofnanvix/openvmm, for which I found nomicrosoft/openvmmpull request, and then a pin promotion. The content format and the consumer here already cover a Windows producer.Tests
cd, pipeline, runner outside the directory, unknown option, missing value, other directory, missing--target).doc/usage.mdsections.Validation
scripts/test_nvx_tools.pymodule (500 tests, OK, after the rebase onto4f9e7cbd1);ruff check,ruff format --check;pyrightfor the Linux and Windows platforms;check_markdown_links.py;git diff --check.CiTests,CliTests,CiConfigurationTests, and the guest-artifact download test (132 tests, OK), which cover the Linux paths of the build and the consumer..github/actionlint.yaml:ci.ymlreports onlyunexpected key "queue" for "concurrency", which ci: queue the dev push runs instead of cancelling the waiting one #734 added and GitHub accepts; actionlint 1.7.7 predates the key.2f85af825, run 39691097674: every job passed, includingRequired status check, apart from the expected skips (the MSHV and WHP debug-kernel jobs on a pull request, the release, and the persistence). The producer built the same 214.7 MiB of content in 6.7 minutes, and the MSHV and KVM consumers ran the same 57 and 58 tests, all passing, in 4.8 and 10.3 minutes. Before the rebase, run 39625831399: the producer built the content (214.7 MiB, a 112.3 MiB artifact, uploaded in 6 seconds) in 7.0 minutes, and the MSHV and KVM consumers downloaded it in 8 and 6 seconds and ran 57 and 58 tests, all passing, with 50 and 49 skipped, exactly as before, in 4.6 and 10.5 minutes; every other job, includingRequired status check, passed.test-openvmmandtest-openvmm-unitcan't run locally.Expected effect
From the PR runs (details on #690):
flowey_hvlitebuild for the target, about 1.5 minutes, missed sccache on each of the three KVM runners that have run the producer so far, each for the first time, so the saving may grow as their caches warm.Post-merge verification
Interactions with other pull requests
This branch is rebased onto
4f9e7cbd1and adapted to the pull requests that merged since its first version:Publish development releaseandPersist performance baselinereadrun-openvmm-vmm-testsalone,check-required-ciexpects the build whenever the VMM tests are selected (the test jobs also need the guest artifacts), and ci: classify microVM tests, benchmarks, and artifact builds separately #712's tests map the build job to that output and accept the two gates' reads of it.openvmm-vmm-tests; the VMM-test inputs derive from the actions of all three jobs andartifacts, and don't include the host side ofnvx-rs.build-openvmm-testslinks with/Breproon Windows through_prepare_openvmm_test_environment, which a test now checks.9f04d05c5.Trial merges of this branch with the open siblings' heads as of 2026-10-21 23:10 UTC show what the pull request that merges second must change:
46da18e49): conflicts indoc/ci.mdandscripts/test_nvx_tools.py, andci.ymlmerges cleanly but leavesopenvmm-vmm-tests-linuxdownloading theguest-artifactsartifact that ci: build the guest-artifact components in parallel and download only what each job uses #711 removes. The Linux VMM-test jobs must downloadguest-kernelandguest-alpine(they already wait only forartifacts), ci: build the guest-artifact components in parallel and download only what each job uses #711's component test must listREQUIRED_CI_OPENVMM_ARTIFACT_TEST_JOBSinstead ofopenvmm-vmm-testsamong the consumers, and its command table must mapbuild-openvmm-tests, which reads no guest file; the build job downloads no component.289be9cb1): conflicts indoc/ci.mdand theREQUIRED_CI_*constants; keep both sides.7e3c899ac): conflicts in the job-graph paragraph ofdoc/ci.md; keep both sides.a904264bc) and ci: report nightly full-run failures #709 (f4b9ae82f) merge cleanly.