Repository navigation
nvx-rs: check the public API that adapters build on - #630
Closed
Enrique Saurez (esaurez) wants to merge 4 commits into
Closed
Enrique Saurez (esaurez) wants to merge 4 commits into
Enrique Saurez (esaurez) wants to merge 4 commits into
Conversation
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The snapshot format test rejects valid CRLF checkouts and breaks Windows validation when automatic line-ending conversion is enabled.
1 open issue
What changed in this PR
Adds public-API snapshot checks for the nvx-rs configurations used by adapters, supporting the shared-runtime contract work in #620 and #535.
Changes:
- Adds pinned API-listing tools, snapshots, tests, and CI integration.
- Introduces an adapter-contract question and contributor guidance.
- Includes the independent runtime adapter and CI hooks from stacked PR #626.
| File | Description |
|---|---|
tests/runtime-adapter/tests/independent_build.rs |
Checks independent builds, feature isolation, and static linkage. |
tests/runtime-adapter/src/lib.rs |
Reports runtime contract versions. |
tests/runtime-adapter/src/bin/runtime-adapter-host.rs |
Adds the host skeleton. |
tests/runtime-adapter/src/bin/runtime-adapter-guest.rs |
Adds the guest skeleton. |
tests/runtime-adapter/README.md |
Documents adapter configurations and checks. |
tests/runtime-adapter/Cargo.toml |
Defines independent adapter features and dependencies. |
tests/runtime-adapter/Cargo.lock |
Locks adapter dependencies. |
tests/public-api/README.md |
Documents snapshot checks and updates. |
tests/public-api/protocol.txt |
Records the protocol API baseline. |
tests/public-api/guest.txt |
Records the guest API baseline. |
scripts/test_public_api.py |
Tests API checking and snapshot handling. |
scripts/test_nvx_tools.py |
Tests CI integration and change classification. |
scripts/nvx_tools/ci.py |
Classifies adapter changes as microVM test inputs. |
scripts/check_public_api.py |
Generates and compares API listings. |
doc/project-structure.md |
Describes new tools and test directories. |
doc/contribute.md |
Adds adapter-contract contribution guidance. |
doc/ci.md |
Documents adapter and public-API checks. |
.gitignore |
Excludes adapter build output. |
.github/workflows/run-nvx-microvm-tests.yml |
Adds adapter scenario hooks. |
.github/pull_request_template.md |
Asks about adapter-contract changes. |
.github/copilot-instructions.md |
Adds adapter and snapshot validation guidance. |
.github/actions/validate-nvx/action.yml |
Runs public-API unit tests. |
.github/actions/check-nvx-rs/action.yml |
Checks adapter configurations and API snapshots. |
Review effort: Balanced
Enrique Saurez (esaurez)
force-pushed
the
esaurez/a1-api-gate-20261019
branch
from
October 20, 2026 07:21
e8a050c to
09f0167
Compare
Enrique Saurez (esaurez)
marked this pull request as ready for review
October 20, 2026 07:29
Enrique Saurez (esaurez)
force-pushed
the
esaurez/a1-api-gate-20261019
branch
from
October 20, 2026 15:39
09f0167 to
b0884b2
Compare
Enrique Saurez (esaurez)
requested a review
from Pedro Henrique Penna (ppenna)
October 20, 2026 15:59
This was referenced Oct 20, 2026
Enrique Saurez (esaurez)
force-pushed
the
esaurez/a1-api-gate-20261019
branch
from
October 20, 2026 23:33
b0884b2 to
367b6da
Compare
Adapters build on the nvx crate in three configurations: protocol-only, host-only, and guest-only. The nvx-rs job now lists the public API of each configuration on each of its targets with a pinned cargo-public-api release and nightly toolchain, and compares the listings with snapshots committed in tests/public-api, so that every change to the API, additions included, shows in review. Items that only some targets list get a snapshot of their own, so that a host-specific API remains possible. The check runs on Linux, and dev pushes cache the build of cargo-public-api. A pull request template asks whether a change touches the adapter contract and, if it does, for a migration note and conformance cases. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b901ceb9-fff0-4a76-9f55-a4b07d9c0633
cargo-public-api leaves out the defaults of generic parameters: it lists `pub type nvx::Result<T, E>` for `Result<T, E = Error>`, so a change to a default passed the check. The check now reads the rustdoc JSON that each listing builds, resolves the public path of each item from the crate root through its modules and re-exports, and appends a line for each default, with the default type as its rustdoc JSON without item IDs. It fails with a tooling error when that JSON reaches other modules than the listing, which would mean that it is stale. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b901ceb9-fff0-4a76-9f55-a4b07d9c0633
A default records its type's rustdoc JSON, whose item IDs change between builds. Dropping them lost which item an imported name such as `Error` resolves to, so a change of the import alone passed the check. Each ID is now replaced by the item's qualified path: the first public path of an item of the crate, or the path that rustdoc records for any other. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b901ceb9-fff0-4a76-9f55-a4b07d9c0633
Enrique Saurez (esaurez)
force-pushed
the
esaurez/a1-api-gate-20261019
branch
from
October 21, 2026 00:04
f2973d6 to
d942e15
Compare
cargo-public-api renders a required and a provided trait item alike, so giving a trait method a default body, or removing one, which breaks the implementations that leave the method out, passed the check. For each item of a public trait, the check now records from the rustdoc JSON whether the trait provides it: a method with a body, or an associated constant or type with a default, together with that default. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b901ceb9-fff0-4a76-9f55-a4b07d9c0633
Comment on lines
+219
to
+223
| items = {target: listings[target].splitlines() for target in configuration.targets} | ||
| first, *others = configuration.targets | ||
| shared = Counter(items[first]) | ||
| for target in others: | ||
| shared &= Counter(items[target]) |
| f"the rustdoc JSON for {target} does not match the {configuration.name} " | ||
| f"listing: its modules differ by {sorted(listed ^ reached)}" | ||
| ) | ||
| return items + lines(generic_defaults(document) + trait_item_defaults(document)) |
Contributor
Author
|
Closing: the public-API gate is being dropped from the plan. |
This was referenced Oct 21, 2026
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.


Adapters build on the
nvxcrate in three configurations: protocol-only, without features; host-only, withhost; and guest-only, withguest, forx86_64-unknown-linux-musl. This pull request makes CI flag every change to the public API that they build on, and adds a pull request template that asks about the adapter contract.scripts/check_public_api.pylists the public API of each configuration on each of its targets with a pinned cargo-public-api release, 0.52.0, from the rustdoc JSON of the oldest nightly toolchain that the release's tests run with, nightly-2026-02-16. It compares the listings with the snapshots intests/public-api, which record the current API as the baseline:protocol.txt, 867 lines;host.txt, 2985; andguest.txt, 1037. They record the API of this pull request's base, including the NVXS session of nvx-rs: add an application-neutral NVXS session #627, the process references of nvx-rs: add verified process references with event-driven exit waits #625, the store of nvx-rs: add the sandbox store, launch journal, and runtime identity #628, and the guest spawn API of nvx-rs: add a neutral guest spawn API and launch managed workloads through it #629. It lists the protocol-only and host-only configurations for bothx86_64-unknown-linux-gnuandx86_64-pc-windows-msvc, which list the same API today. Items that only some targets list go to a snapshot of their own,NAME.TARGET.txt, so a host-specific API, such as the descriptor and handle allowlists that nvx-rs: share the VMM supervisor and the sandbox store #620 plans, stays possible and shows in review. Blanket implementations are left out; auto-trait and derived implementations stay, because adapters rely on them. cargo-public-api drops the defaults of generic parameters, as inpub type nvx::Result<T, E>forResult<T, E = Error>, so the check appends a line for each default of a public item, read from the rustdoc JSON that the listing builds, with each item ID replaced by the item's qualified path so that a default that names another type through the same spelling changes the snapshot, and, because it also renders a required and a provided trait item alike, a line for each item of a public trait that says whether the trait provides it. The check fails with exit status 2 if that JSON reaches other modules than the listing.nvx-rsjob runs the check on Linux throughcheck-nvx-rs. cargo-public-api publishes no binaries, so the job builds it, anddevpushes cache the build under the hash of the script, as the other caches do. The check exits with 1 and annotates the snapshots when the API changed, and with 2 when it cannot list the API. The job summary reports the size of each listing..github/pull_request_template.mdasks: "Does this change the adapter contract (public API, behavior, persisted formats or wire)? If so, add a migration note and conformance cases."tests/public-api/README.mddescribes the snapshots, how to update them, and how to move the pins.doc/ci.md,doc/contribute.md,doc/project-structure.md, and the Copilot instructions describe the check and the template.Why a committed cargo-public-api snapshot rather than
cargo-semver-checksagainst a Git baseline:cargo-semver-checksreports only the breaking changes that it has lints for, so an addition to the adapter-facing API would pass without review.cargo-semver-checksaccepts a deliberate breaking change only with a version bump, whichnvxmakes when it releases rather than in each change. Here, the reviewed snapshot update in the same pull request accepts it.Its paths select neither the microVM nor the OpenVMM test suites (
run-tests=false).Part of #620. Refs #535.
Validation
Rebased onto
devat b47a9f8, after the package was renamed tonvx(#650): the crate is now namednvxin the script's output and the documentation, while thenvx-rs/directory, thenvx-rsjob, andcheck-nvx-rskeep their names. The snapshots were regenerated there; compared with the previous base they addnvx::host::storefrom #628 andnvx::guest::spawnfrom #629, and record the new field ofSessionError::SequenceOverflowfrom #639. I ran the checks below again on the rebased commit.Windows 11; nothing here boots a VM:
python scripts/check_public_api.pypasses against the snapshots. Controls: a new public function fails the check with exit status 1 in all three configurations; a Windows-only public function fails it until--updatewritesprotocol.x86_64-pc-windows-msvc.txtandhost.x86_64-pc-windows-msvc.txt, leaving the shared snapshots unchanged; once the function is gone, the check reports both target snapshots as obsolete and--updateremoves them; a stray snapshot fails the check.pub struct Control<T = u8>, updating the snapshots, and then changing only the default tou16fails it in all three configurations, with a diff only on the default lines. GivingOutputSink::writea default body fails it with a diff only on that method's line.scripts/check_markdown_links.py.python -m unittest scripts/test_public_api.py scripts/test_nvx_tools.py scripts/test_markdown_links.py scripts/test_tool_versions.py: 623 tests pass.python scripts/nvx.py classify-ci-changeson this commit's paths:run-tests=false,run-workloads=true, both OpenVMM suites false, for pull requests and pushes.WSL Ubuntu, Python 3.10.12, no hypervisor:
python3 scripts/check_public_api.py --install-tools --root DIRfrom scratch: the minimal nightly profile, the three targets, and the cargo-public-api build, in 86 s.x86_64-pc-windows-msvclisting, in under 40 s from a cold target directory and 14 s warm, and writes the job summary underGITHUB_ACTIONSandGITHUB_STEP_SUMMARY.python3 -m unittest scripts/test_public_api.py: 31 tests pass.Left to CI: the check on a GitHub-hosted Linux runner, which builds cargo-public-api because only
devpushes save its cache, and the rest of the matrix.Adapter contract
Does this change the adapter contract (public API, behavior, persisted formats or wire)? If so, add a migration note and conformance cases.
No. This pull request records the current public API and adds the check; it changes no API, behavior, persisted format, or wire.