Repository navigation
ci: classify microVM tests, benchmarks, and artifact builds separately - #712
Merged
Pedro Henrique Penna (ppenna) merged 2 commits intoOct 21, 2026
Merged
Conversation
Closed
5 tasks
Contributor
There was a problem hiding this comment.
🔵 Needs a closer look
Cross-platform required checks and artifact dependencies warrant human review, and the development-push policy explicitly awaits maintainer confirmation.
No open issues 🎉
What changed in this PR
Refines NVX CI selection to reduce unnecessary jobs while preserving development-release and performance-history behavior.
Changes:
- Separates microVM tests, benchmarks, guest artifacts, and OpenVMM binary selection.
- Updates workflow gating, required-status validation, and regression tests.
- Excludes documentation from suite selection and documents the retained
dev-push policy.
| File | Description |
|---|---|
| scripts/test_nvx_tools.py | Tests classification, fallbacks, dependencies, and workflow wiring. |
| scripts/nvx.py | Accepts six required-status flags. |
| scripts/nvx_tools/ci.py | Implements separate selections and result expectations. |
| doc/usage.md | Updates CLI flags and selection behavior. |
| doc/distribution.md | Clarifies when platform packaging runs. |
| doc/contribute.md | Updates runner-selection guidance. |
| doc/ci.md | Documents classification and development-push policy. |
| .github/workflows/ci.yml | Wires job conditions to the new outputs. |
Review effort: Balanced
This was referenced Oct 21, 2026
The change classifier counted a documentation file as a suite input whenever its path matched the suite's pattern. A change only to scripts/setup/README.md therefore set run-tests and both OpenVMM suite outputs, although it skipped the workloads: it built OpenVMM on a KVM, an MSHV, and a WHP runner and ran the OpenVMM unit tests on an MSHV and a WHP runner, none of which reads the file. Beside any other change, a README in a test input directory also ran the NVX microVM tests and both OpenVMM suites. No suite builds, boots, or runs documentation, which the classifier already defines as every path under doc/ or ending in .md, and the GitHub-hosted jobs that check it, the Markdown link check and the CLI tests, run for every change. Select each suite only from the changed files that are not documentation, and cite only those in the job summary. A documentation-only change still skips the workloads, and an empty diff still runs them. The classifier tests now expect no suite for documentation in the runner setup, nvx-rs, and runtime adapter directories, alone or beside another change, and the summary test checks that a guest README is not cited as an input of the VMM tests. doc/ci.md and doc/usage.md state the rule. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The change classifier reported run-tests, which enabled the NVX microVM tests, and run-workloads, which enabled the guest artifacts, the three OpenVMM builds, and the platform jobs for every change but documentation. A change only to the performance tooling therefore ran every microVM job; a change only to a microVM scenario, the aci_edge_sandboxes crate, or the runtime adapter ran the platform jobs, which wait for their pool's single benchmark runner; and a change only to the CLI tests or the adversarial tooling built every artifact and ran the benchmarks. Replace the two outputs with four, beside the two OpenVMM suite outputs: - run-microvm-tests enables the microVM and debug-kernel jobs, from the inputs of those jobs and of every job that builds an artifact that they use. - run-benchmarks enables the platform jobs, which benchmark and package each backend, and so a pull request's regression gate, from the inputs of those jobs, the gate, and the jobs that build their artifacts, including the history and expected hosts in data/, VERSION, and LICENSE. - run-guest-artifacts and run-openvmm-binaries enable the jobs that build the guest artifacts and OpenVMM. Neither has a use of its own, so the classifier sets each exactly when a job that uses its artifacts runs. The guest artifacts thus follow the inputs of the OpenVMM VMM tests, which take only the guest binaries' inputs of nvx-rs. Both new suites take all of nvx-rs, whose CLI the microVM tests run and every package ships. Every CLI module is an input of both unless none of their jobs runs it, so a new module selects both. Only the microVM tests run microvm_tests.py and the modules and guest scripts that only it, nvx.py sandbox, and test-aci-edge-sandboxes use, and only the platform jobs run performance.py. benchmark.py, which microvm_tests.py imports, doctor.py, which every runner validation runs, and release.py, whose verify command the OpenVMM builds run, select both. The OpenVMM suites keep their inputs and no longer need run-tests, which every one of their inputs set. A dev push publishes its commit's development release and appends to the performance history, and both still require all three platform jobs to succeed, so a push that skipped them would publish nothing partial or stale but would leave its commit without a release, and download would install an older one. Pushes therefore keep running the platform jobs, and the jobs that build their artifacts, for every change but documentation, as before, and pull requests, which publish and persist nothing, run them only when one of their inputs changed. Of the 108 merges from October 10 to 21 that changed more than documentation, 10 changed no input of the platform jobs, whose pushes each still spend about 19 benchmark-runner minutes on them. An empty diff still runs the platform jobs, and the detector's fallbacks, the nightly and dispatched full runs, and the release, gate, and persistence conditions are unchanged. check-required-ci takes the six outputs and, like the job conditions, expects a job only when the jobs that build its artifacts run too. Replayed over the 124 completed pull-request runs of this repository's branches from October 15 to 21 that ran CI, the classifier skips the platform jobs in 8, the microVM tests in 3, and every artifact build in 5. Tests cover each path class for pull requests and pushes, nvx-rs's guest and host sides included, the artifact builds following the jobs that use them, the job summary, the CLI, the required-result policy for every output, the job condition that reads each output, and the detector's fallback when any output is missing or duplicated. The drift test now derives the inputs of the microVM tests and the platform jobs from those jobs and the jobs that build their artifacts: the reusable workflows and actions that these reach, the cache keys there and the files of the guest binaries' source identity, with which every image key ends, the CLI modules of the nvx.py commands that they run, which it maps from nvx.py's parser, with every module that those import and every file that those read beside them, and the nvx crate that the CLI jobs build. doc/ci.md and the other affected guides describe the outputs and the push rule. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/classify-ci-outputs-separately
branch
from
October 21, 2026 20:00
e4f61d2 to
7ccb8d5
Compare
2 tasks
Pedro Henrique Penna (ppenna)
deleted the
agents/classify-ci-outputs-separately
branch
October 21, 2026 22:40
This was referenced Oct 22, 2026
Track nightly CI reporter bugs: an issue that quotes the report marker is closed or overwritten
#741
Open
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.
Closes #698.
Part of #430.
Summary
The change classifier selected the CI jobs with two coarse outputs:
run-testsenabled the NVX microVM tests, andrun-workloadsenabled the guest artifacts, the three OpenVMM builds, and the platform jobs for every change but documentation. This PR replaces them with four outputs, beside the two OpenVMM suite outputs, so that a change runs only the jobs that its inputs affect:run-microvm-testsrun-benchmarksrun-guest-artifactsartifactsanddebug-kernelrun-openvmm-binariesbuild-openvmm-*producersrun-openvmm-unit-tests,run-openvmm-vmm-testsBoth new suites take all of
nvx-rs, whose CLI the microVM tests run and every package ships, while the VMM tests keep #710's narrower inputs, only the files that the guest binaries' build reads. It also stops documentation inside a suite's directory, such asscripts/setup/README.md, from selecting suites.Important
Decision for the maintainer to confirm:
devpushes keep running the platform jobs, and the jobs that build their artifacts, for every change but documentation, exactly as before. Every such commit therefore still publishes a complete development release and records a complete performance-history entry. Only pull requests skip the platform jobs when none of their inputs changed. The data and the alternative are under Dev pushes.Why
run-teststreated every file underscripts/nvx_tools/as a test input, so a change only to the performance tooling, such as Skip stale device-io.log from other suites during benchmark collection #508 and performance: keep results measured before a history reset out of the series #658 (performance.py), ran every microVM job.run-workloadswas true for every non-documentation change. A change only to a microVM scenario, theaci_edge_sandboxescrate, or the runtime adapter therefore ran the three platform jobs, which wait for their pool's singlebenchmarkrunner. A change only to the CLI tests or the GitHub-hosted checks built every artifact and ran the benchmarks too. Examples:scripts/setup/README.mdalone made the benchmark changes ci: record benchmark host provenance and storage telemetry #479 and ci: detect benchmark host changes before they enter the performance history #527 run both OpenVMM suites, about 37 WHP runner-minutes each.The issue's reference run is 39585909588.
Changes
ci: ignore documentation files when selecting the CI suites: no suite builds, boots, or runs documentation, so the classifier selects each suite only from the changed files that are not documentation.ci: classify microVM tests, benchmarks, and artifact builds separately:scripts/nvx_tools/ci.py: the six outputs.MICROVM_TEST_INPUT_PATHSandBENCHMARK_INPUT_PATHSreplaceCI_TEST_INPUT_PATHS, and both keep all ofnvx-rs/. Every CLI module is an input of both unless none of that suite's jobs runs it, so a new module selects both until someone excludes it. Only the microVM tests runmicrovm_tests.pyand the modules and guest scripts that only it,nvx.py sandbox, andtest-aci-edge-sandboxesuse. Only the platform jobs runperformance.py.benchmark.py, whichmicrovm_tests.pyimports,doctor.py, which every runner validation runs, andrelease.py, whoseverifythe OpenVMM builds run, select both. The two producer outputs follow their consumers, so no job ever waits for an artifact that its run skipped. The job summary explains each output, andcheck-required-cimirrors the job conditions: it expects a job only when the jobs that build its artifacts run too.scripts/nvx.py:check-required-citakes the six flags..github/workflows/ci.yml: the detector emits, checks, and falls back on the six outputs. Each job's condition reads its own output, andRequired status checkpasses all six. The release, gate, and persistence conditions are unchanged.doc/ci.md(Change classification, and a new Development releases and performance history section),doc/usage.md,doc/distribution.md, anddoc/contribute.md.The detector's fallbacks to the full matrix are unchanged: a missing base or commit, a failed diff or classifier, or a missing, duplicated, or malformed output. Nightly and dispatched runs still select everything before classification.
Dev pushes: what they package, publish, and persist
A
devpush publishes its commit's development release and appends the platform results todata/.Publish development releaseandPersist performance baselinekeep requiring all three platform jobs to succeed, plus the debug kernel and the CLI jobs. A push that skipped the platform jobs would therefore publish nothing partial or stale, but its commit would have no release.downloadwould then install an ancestor's release, which is older still when that ancestor's release failed.So this PR keeps the conservative behavior: a push runs the platform jobs, and their producers, for every change but documentation, as before. The debug kernel still builds with the guest artifacts, because the release and persistence require it.
Data from the 108 merges to
devbetween October 10 and 21, through #710, that changed more than documentation:download's 20-commit search.If you prefer the alternative, it's a one-line change in
classify_ci_changes, droppingor (event_name == "push" and bool(inputs)), plus the matching test and doc updates.Tests
benchmark_scripts/,microvm_test_scripts/,host_time_probe.rs, andprocess_supervisor.py, the guests, crates,data/,VERSION,LICENSE,.gitattributes, and unions.nvx-rsfile among them, both producer outputs equal the OR of their consumers.nvx-rs(ci: key the guest images and VMM tests on the guest binaries' sources #710's rows and acceptance test, ported): every file of the crate selects the microVM tests and the platform jobs, and only the guest binaries' inputs select the VMM tests and change the guest image keys, for pull requests and pushes.check-required-cirequires and validates each flag, and passes each one to its own suite: flipping any one flag fails the check.result != 'success'guard, only those jobs andRequired status checkread the outputs, and the detector lists exactly the classifier's outputs.nvx.pycommands that they run, which the guard maps fromnvx.py's parser with the AST. It also covers every module that those modules import, every file that they read beside them throughPath(__file__).with_name, and thenvxcrate that the CLI jobs build. The guest-artifact inputs come from the cache keys and, since ci: key the guest images and VMM tests on the guest binaries' sources #710 tooknvx-rsout of the image keys'hashFiles, from the files of the guest binaries' source identity, with which every image key ends. The guard therefore follows key changes such as ci: key the guest images and VMM tests on the guest binaries' sources #710's.Validation
All on the head rebased onto
devat6f0facefd, which includes #710, #717, #714, #661, and #656:validate-nvxunittest set ran 1,100 tests, and everytest_nvx_toolstest passed. The 18 failures were intest_setup_azure's Linux shell-script tests, which fail the same way onorigin/devin this environment.nvx-rstests passed on its own tree.test_adversarial.py,test_hosts.py,compileall, everynvx.py ... --helpinvalidate-nvx, andcheck_markdown_links.pypassed.CiConfigurationTestsclass (67 tests) passed.ruff check,ruff format --check, andpyrightfor Linux and Windows passed, all at the pinned versions.ci.ymlor the three reusable workflows.doctor.py,release.py, orprocess_supervisor.pyfrom the microVM tests, or droppingdata/,VERSION,run-platform, orgate-performancefrom the platform jobs. After the rebase, so does each of 8 more: droppingnvx-rs/or the Rust pin from either suite, dropping the guest binaries' source pattern from the VMM tests, or excludingguest_binaries.pyfrom either suite.ci.yml, an input of every output, so its own CI runs the full matrix.Expected effect
Replaying the new classifier over the same diffs that the old one classified:
108 merges to
devfrom October 10 to 21, through #710, that changed more than documentation, plus 24 documentation-only merges, which run nothing in every case. "Old" isdev's classifier with #710, whose narrower VMM-test inputs already skip the VMM tests for host-sidenvx-rschanges.124 completed, non-draft pull-request runs of this repository's branches from October 15 to 21, across 74 PRs; each head is diffed from its base before merging.
nvxcrate. Since ci: key the guest images and VMM tests on the guest binaries' sources #710, a change to its host side or tests skips the VMM tests, but it still runs the microVM tests, which run its CLI, and the platform jobs, whose packages ship it. A follow-up that packages the release outside the benchmark runners could letrun-benchmarksdrop the package inputs, so that such changes would skip the benchmarks too.Interactions with other #430 PRs
Merged into
devsince this PR opened; the rebase adapted to the first five:run-openvmm-vmm-testskeeps ci: key the guest images and VMM tests on the guest binaries' sources #710's inputs, only the files that the guest binaries' build reads, andrun-guest-artifactsfollows them.run-microvm-testsandrun-benchmarkskeep all ofnvx-rs/. ci: key the guest images and VMM tests on the guest binaries' sources #710's classification rows and its acceptance test now check the six outputs, and the drift guard takes the source-identity files as guest-artifact inputs, because the image keys'hashFilesno longer listnvx-rs.scripts/setup/tool-versions.conf, was already an input of the unit tests.ci.pyis an input of every suite.microvm_test_scripts/selects only the microVM tests on a pull request. Its gitlink move selects everything; this PR doesn't touch the gitlink.nvx-rscode selects the microVM tests and the platform jobs, but not the VMM tests.devpushes now queue instead of cancelling the waiting run, so every non-documentation commit gets its run. With this PR's push rule, that run also runs the platform jobs and publishes the commit's release.Still open; whichever merges second adapts:
run-testsorrun-workloads, which this PR removes.test_ci_jobs_follow_their_change_detector_outputand the policy tests fail until each gated job reads one of the new outputs, so no job can be skipped silently. ci: build the guest-artifact components in parallel and download only what each job uses #711'sdistro-artifactsjob belongs withrun-guest-artifacts.microvm_durations.py) and ci: report nightly full-run failures #709 (nightly_ci.py) add modules that select both suites until the classifier excludes them. That over-selects but never skips.guest_artifact_reuse.py) needs nothing: the drift guard derives theartifactsjob's modules.Post-merge verification
Detect CI workload inputssays so, and thatRequired status checkpasses when jobs are skipped.devpush after merge still publishes the development release and persists the performance results.