Repository navigation
release: check the nvx package and declare the breaking release (SL8.1) - #1561
Pedro Henrique Penna (ppenna) merged 3 commits into
Conversation
This pull request changes existing testsIt modifies or removes 6 existing test asset(s), listed below. Review each with care: a change to a test can hide a regression that the test caught. See doc/contribute.md#changes-to-existing-tests. Test code
Relocated unchanged: 0; added: 11. Compared the merge base |
There was a problem hiding this comment.
🟡 Changes recommended
The API gate counts calls in comments and string literals, allowing a binary with commented-out delegation to pass despite never calling a library entry point.
1 open issue
What changed in this PR
This PR prepares NVX’s breaking prerelease using the existing release pipeline; it does not publish a release itself. The proposed version, 0.2.0-alpha.1, remains provisional.
Changes:
- Checks that hidden public API items correspond to binary entry points and their containing modules.
- Requires packaged API snapshots and installs and runs
nvx-ingressfrom the unpacked crate outside the checkout. - Declares the release version, adds its breaking-change changelog, and updates documentation and tests.
| File | Description |
|---|---|
scripts/test_public_api.py |
Tests entry-point discovery and hidden API validation. |
scripts/test_crate_release.py |
Tests package contents, guest-tool checks, and changelog version alignment. |
scripts/publish_nvx_crate.py |
Updates help and documentation for the install check. |
scripts/public_api.py |
Adds binary entry-point and hidden API checks. |
scripts/nvx_tools/crate_release.py |
Requires API snapshots and validates a standalone guest-tool install. |
nvx-rs/Cargo.toml |
Declares the provisional release version. |
nvx-rs/Cargo.lock |
Aligns the crate’s locked version. |
doc/distribution.md |
Documents the new prerelease series. |
doc/contribute.md |
Explains the hidden entry-point requirement. |
doc/ci.md |
Documents package and API validation. |
doc/acceptance-case-matrix.md |
Records the expanded checks in existing CI cases. |
CHANGELOG.md |
Lists breaking changes and links the migration guide. |
Review effort: Balanced
89b53a6 to
00453f8
Compare
There was a problem hiding this comment.
🟡 Changes recommended
The API checker can miss a Windows-exposed entry point when Linux hides it and can mistake text inside raw C strings for a real delegation call, allowing invalid API snapshots to pass.
2 open issues
1 resolved since last review
Review effort: Balanced
The breaking release's public API must hold exactly the planned surface and one hidden main per binary (#1132): NVX's programs live in nvx, private to it, and each binary calls a #[doc(hidden)] main, the only public item that a program adds (#1076). public_api.py checked that the API matches its snapshots, hidden items marked, but not which items may be hidden, so a program's other items, or a binary whose entry point is public, could reach the API unnoticed. The script now also finds each binary's entry point, the function main of nvx that the binary's code calls, such as nvx::host::cli::main for nvx-rs, from the targets that cargo metadata lists. It reads the code outside the source's comments, which nest, and its string, byte string, C string, raw string, and character literals, so that a call that a comment or a literal holds counts for none. It fails, with or without --update, unless the API's hidden items, over both platforms' listings, are those functions and the modules that hold them: when a binary calls no such function or several, when two binaries call one, when no listing hides a binary's main, when a listing shows one without hiding it, or when the API hides anything else. A guest program's main is hidden on Linux alone, since its binary is a stub elsewhere, but no platform may list an entry point unhidden. The current snapshots pass: their hidden items are the 12 binaries' mains and the modules that hold them. The nvx-rs job runs the check in every pull request and in the full run of dev that publishes the crate, whose Required status check requires that job, so the release's snapshots are checked too. doc/ci.md and doc/contribute.md describe the rule, and the case matrix's row of the public API check names it. Tests: test_public_api.py's EntryPointTests find the main that each binary calls, skipping a guest stub's, refuse a binary that calls none or two, or whose delegation a comment holds, find no call in line, doc, nested block comments, or string, raw string, byte string, C string and raw C string literals, and keep the code after a comment or a literal that holds a quote, and a lifetime. They accept hidden mains and their modules, also when a module holds public items, and report another hidden item, a public main, a main that one platform hides and another lists unhidden, and a main that two binaries share. Part of #1132 (SL8.1). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The breaking release must let users install and run the guest tools from the package alone (#1132): outside any checkout, cargo install nvx --no-default-features --features guest --profile guest --bin nvx-ingress, then nvx-ingress. Package nvx crate packed the crate, checked the package against the commit, and built it with every feature, but never with the guest feature alone or the guest profile, and never from outside the repository, so a package that only the checkout's build could complete, such as one that lost a file of the guest's code path or the guest profile, could still be published. The package job now also installs nvx-ingress from the package's files, the directory that its build unpacked, with cargo install --locked --path, --no-default-features --features guest and --profile guest, into the job's work directory, from which it runs Cargo, $RUNNER_TEMP/nvx-crate in CI, outside the checkout. Then it runs the installed program's test mode on a snapshot of the socket tables that holds no socket, which must print one scan at time 0 that announces no listener, the NVXL conformance vector NONE. A failure fails the job, which then outputs no version, so Publish nvx crate publishes nothing. The job already held no right to publish, so the build scripts and procedural macros of this build cannot publish either. The package must now also hold the public API's snapshots, with which its users check the API that it promises; the nvx-rs job, which Required status check requires, checks them in the same run. The publish job's check of the package requires them too. doc/ci.md's crates.io releases and the case matrix's rows of the two crate jobs describe the new checks, and the scripts' docstrings the package job's steps. Tests: test_crate_release.py's fake Cargo also takes cargo install, and runs the installed tool, whose output a test sets. test_the_package_job_installs_and_runs_the_guest_tool_of_the_package checks the install's command, its directory, outside the checkout, the snapshot and the run; a tool that fails or prints another announcement publishes nothing; and a package without either snapshot fails its check. The demo crate of the tests holds snapshots, and test_the_first_version_is_the_declared_one expects the install and the run after the build. Part of #1132 (SL8.1). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The breaking release of #1076 must declare its version and record what it breaks (#1132). crates.io holds 0.1.0-alpha.1 to 0.1.0-alpha.16, and dev's nightly runs take the next number of the 0.1.0-alpha series whenever the crate changes there, until this work reaches dev. The crate now declares 0.2.0-alpha.1, as #1132 decided, the first version of a series that nothing has published, which doc/distribution.md describes for a new series: the full run of dev that first packs this commit publishes exactly that version, whatever numbers the nightlies took meanwhile, and a requirement such as nvx = "0.1.0-alpha.7", which Cargo also resolves to later 0.1.0 pre-releases, never resolves to it. The release also corrects the crate's description, which crates.io displays with each version: it named the OpenVMM control protocol, policy lowering, and the supervision of NVX microVMs, which #1076 made private or removed. It now names the library's mechanisms and value types, as nvx-rs/README.md describes them. No check reads it. The new root CHANGELOG.md records the release in one entry, which lists its breaking changes and links doc/migrate-from-alpha.7.md for the details. The documents that name the crate's versions follow the new series: doc/distribution.md's description of the crate and the version that its install of the guest tools names, doc/ci.md's description of the nightly versions, and the version requirements of nvx-rs/README.md, which name 0.2.0-alpha.1 and the nightly 0.2.0-alpha.2 in place of 0.1.0-alpha.4. Tests: ChangelogTests keeps the changelog's newest entry equal to the version that nvx-rs/Cargo.toml declares, so a pull request that starts another series adds its entry. Part of #1132 (SL8.1). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
00453f8 to
bc6f299
Compare
05cb371
into
feature/nvx-refactor

Part of #1132 (SL8.1: The breaking release is published).
The release's version is
0.2.0-alpha.1, as decided on #1132 (#1132 (comment)).What and why
The breaking release of #1076 needs its changelog and version, CI checks that its package and public API are the planned ones, and a standalone install of the guest tools from the package. This PR prepares that release; it publishes nothing. The full run of
devthat first packs a commit containing it publishesnvxat the declared version, with the existing publishing jobs, after Pedro Henrique Penna (@ppenna) mergesfeature/nvx-refactorintodev.public_api.pycompared the API with its snapshots, hidden items marked, but not which items may be hidden. It now reads each[[bin]]target's code, fromcargo metadata, outside its comments, which nest, and its string, byte string, C string, raw string and character literals, for the singlenvx::…::main()that the binary calls. It fails, with or without--update, unless the hidden items of both platforms' listings are exactly those functions and the modules that hold them: a binary that calls none or several, or whose delegation a comment holds, two binaries that share one, a main that no listing hides, a main that a listing shows without hiding it, and any other hidden item fail. The current snapshots pass: their hidden items are the 12 binaries' mains and their modules. Thenvx-rsjob runs it in every pull request and in the full run ofdev, whoseRequired status checkgates the crate jobs.Package nvx crate(publish_nvx_crate.py package) checked and built the package with every feature only. It now also requires the public API's snapshots in the package, so its users can check the surface that it promises, and, after the all-features build, runscargo install --locked --path <unpacked package> --no-default-features --features guest --profile guest --bin nvx-ingress --root …from its work directory,$RUNNER_TEMP/nvx-crate, outside the checkout, then runs the installednvx-ingress teston a snapshot without sockets, which must print0 4e56584c01000000(NVXL'sNONEvector). A failure fails the job, soPublish nvx cratepublishes nothing. The job already holds no right to publish.CHANGELOG.mdwith one entry lists the breaking changes, each checked against the code and the public API snapshots, and linksdoc/migrate-from-alpha.7.md. The release also corrects the crate'sdescriptioninnvx-rs/Cargo.toml, because crates.io displays it with each version: it named the OpenVMM control protocol, policy lowering, and the supervision of NVX microVMs, which nvx-rs slimming workstream: makenvxa library of mechanisms and value types #1076 made private or removed, and now names the library's mechanisms and value types, asnvx-rs/README.mddescribes them. No test or check reads the description; the package checks read only the name and the version. Every document that names the crate's versions follows the new series:doc/distribution.md's description of the crate and the version that its install of the guest tools names,doc/ci.md's description of the nightly versions, and the version requirements ofnvx-rs/README.md;doc/migrate-from-alpha.7.mdalready pins0.2.0-alpha.1.CI's publishing jobs need no change: with
0.2.0-alpha.1declared,plan_releaseseesnvx-rs/changed since the newest version's commit ondev, andnext_versiontakes the declared number of the new series, which sorts above every0.1.0-alpha.N, so the first full run publishes exactly0.2.0-alpha.1, and later nightlies0.2.0-alpha.2and on. Onlynvxis published, as before.Measured: 147 core lines, in 4 counted files (
scripts/public_api.py88,scripts/nvx_tools/crate_release.py55,scripts/publish_nvx_crate.py2,nvx-rs/Cargo.toml2); the estimate is 80, the stop 160.BOOT_CONTRACT_VERSIONandCONTROL_CONTRACT_REVISIONare unchanged. The public API is unchanged; its snapshots need no update.Old tests of the area: every test of
scripts/test_crate_release.pyandscripts/test_public_api.pyis kept; the workflow tests ofscripts/test_nvx_tools.pyare kept unchanged, since the workflow does not change. The case matrix's rows ofCheck the public API,crate-packageandcrate-releasedescribe the new checks, as kept.Validation
At
bc6f29938b2, onecd6e02d85f:scripts/test_adversarial.pyand thenvx.py … --helpchecks: OK.python3 scripts/public_api.py: passes.cargo package --list --locked(nvx-mshv-test): 516 files, the 514 that Git tracks innvx-rs/, with.cargo_vcs_info.jsonandCargo.toml.orig; among thempublic-api/linux.txtandpublic-api/windows.txt.cargo publish --dry-run --locked(nvx-mshv-test): packaged 516 files, 7.8 MiB (1.8 MiB compressed), verified, "aborting upload due to dry run". Nothing was published, and no tag was pushed.python3 scripts/publish_nvx_crate.py package --work-dir /mnt/data/ppenna/nvx-sl8-1-cratewithRUSTUP_TOOLCHAIN=1.95.0, asPackage nvx crateruns it (nvx-mshv-test, which queries crates.io read-only and never publishes): "nvx-rs/ changed since f7720fb, from which nvx 0.1.0-alpha.16 was packed: packing nvx 0.2.0-alpha.1", checked the 516 files, built with every feature, installednvx-ingresswith theguestprofile from the unpacked package and ran it, exit 0 in 40 s; package SHA-2567455c26fa1a8267beb8d5f577cc3e8a5c11d050d30cfa6475cae929f48852e0d.nvx-0.2.0-alpha.1.crate, unpacked outside any repository on nvx-mshv-test:cargo install --path nvx-0.2.0-alpha.1 --no-default-features --features guest --profile guest --bin nvx-ingress(no--locked, fresh resolution) gave a glibc executable, and--locked --target x86_64-unknown-linux-musla static-pie one; each printed0 4e56584c01000000for an empty snapshot,0 4e56584c0100000106011f90for one TCP listener on port 8080, and exited 2 without arguments.scripts/test_adversarial.py, thenvx-host-connecttests and thenvx.py … --helpchecks: OK.python scripts/public_api.py: passes.check_markdown_links.py: passes,CHANGELOG.md's link to the migration guide included. Ruff check and format: clean; Pyright strict for Linux and Windows: clean.check_test_layout.py: passes. The case matrix check (check_matrix.py … 99d2022085f): passes.Test changes (
check_test_changes.py --base origin/feature/nvx-refactor: 6 changes to existing tests, 11 added; labeltests-modified):CRATE_FILES: the demo crate holds the two API snapshots, which a package must now hold._Cargo.__init__,_Cargo.__call__,_Cargo.reset: the fake Cargo also takescargo install, and records each command's directory;_Cargo.capture, new, runs the installed tool with a result that a test sets, and Git for real.ReleaseTests.package: patchesrun_capturewith that fake too.ReleaseTests.test_the_first_version_is_the_declared_one: expects the install and the tool's run after the build.test_the_package_job_installs_and_runs_the_guest_tool_of_the_package,test_a_guest_tool_that_does_not_run_as_it_should_publishes_nothing,test_a_package_must_hold_the_snapshots_of_its_public_api,ChangelogTests.test_the_newest_entry_is_the_series_that_the_crate_declares, andEntryPointTestsinscripts/test_public_api.py, withtest_finds_no_call_in_a_comment_or_a_literalandtest_hides_an_entry_point_on_every_platform_that_lists_it.