openvmm: add product version and build identity - #4162
openvmm: add product version and build identity#4162Ben Hillis (benhillis) wants to merge 4 commits into
Conversation
`openvmm --version` did not exist, and there was nothing to report if it had: the workspace set no `version`, so every crate in it was `0.0.0`. OpenVMM ships as a source archive that packagers build themselves, which rules out the usual approach of having CI inject a version at build time -- the packager builds long after our pipeline has exited, from a tree with no git history to recover a version from. The version therefore has to be committed to the tree. QEMU, systemd, the kernel, cloud-hypervisor and rustc all do this, and each falls back gracefully when `.git` is absent rather than deriving the release version from a tag. So: set `version` in `[workspace.package]`, inherit it in `openvmm` and `openvmm_entry`, and wire up clap's `version`. `OPENVMM_PKGVERSION` lets a packager append their own build identity, as QEMU's `-Dpkgversion` and cloud-hypervisor's `CH_EXTRA_VERSION` do; an empty value is ignored, since build systems routinely pass an undefined variable through as "". Two things fall out of that: - The Windows VERSIONINFO resource is a second version surface, stamped from `OPENVMM_MAJOR`/`MINOR`/`PATCH`/`REVISION` and defaulting to `0.0.0.0`. No in-repo caller sets those, so leaving it alone would have left one binary reporting `0.1.0-dev` from `--version` and `0.0.0.0` from its file properties. It now defaults to the crate version, with the env vars still overriding per-component so a pipeline can stamp a build number in. - `cargo xtask fmt` deliberately strips `version` from `[package]`, partly because doing so also makes a crate unpublishable. The three crates on its exception list now set `publish = false` explicitly, restoring the property the lint was relying on. Verified by building `openvmm` from an extracted archive with no `.git` anywhere above it, which is the case that actually matters.
The workspace version advances only in the reviewed pull request that selects the next release. Development-build identity is added separately from the committed product version. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0ba1c0df-faf0-4a0e-b39d-c3eb0e363fce
Add a dedicated build-info crate so Git checkouts report VERSION+gCOMMIT while Git-free source trees retain the plain product version. Wire concise and detailed CLI output and document the behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4fe65aa5-d620-4856-a525-e32bf98c16b1
There was a problem hiding this comment.
Pull request overview
Adds a first slice of OpenVMM build identity by centralizing the canonical product version in the workspace and exposing a consistent -V/--version output via a new openvmm_build_info crate.
Changes:
- Introduces
openvmm_build_infoto compute a compile-time build identity (product version + optional Git revision) and provide short/long version strings. - Wires
openvmm_entry’s clap metadata so-V/--versionreport OpenVMM identity instead of the parser crate version, and adds unit coverage for this behavior. - Makes version-carrying crates explicitly
publish = false, updates the xtask house rule docs, and documents the new CLI version behavior in the Guide.
Reviewed changes
Copilot reviewed 11 out of 12 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
xtask/src/tasks/fmt/lints/package_info.rs |
Updates the “version exceptions” list and documents why some crates are allowed to carry versions. |
vm/vmgs/vmgstool/Cargo.toml |
Explicitly sets publish = false for a versioned binary crate. |
openvmm/openvmm/Cargo.toml |
Adopts workspace version and marks openvmm as non-publishable. |
openvmm/openvmm_entry/src/cli_args.rs |
Uses openvmm_build_info for clap version/long_version and adds a unit test for -V/--version. |
openvmm/openvmm_entry/Cargo.toml |
Adds the new openvmm_build_info dependency. |
openvmm/openvmm_build_info/version.rs |
Implements VERSION vs VERSION+g<short> resolution and unit tests. |
openvmm/openvmm_build_info/src/lib.rs |
Exposes get().version() / get().long_version() backed by build-script outputs. |
openvmm/openvmm_build_info/Cargo.toml |
Adds the new crate with workspace versioning and publish = false. |
openvmm/openvmm_build_info/build.rs |
Resolves Git identity at build time and emits the long-version payload. |
Guide/src/reference/openvmm/management/cli.md |
Documents the semantics of -V/--version output. |
Cargo.toml |
Adds canonical OpenVMM version under [workspace.package] and registers openvmm_build_info as a workspace dependency. |
Cargo.lock |
Reflects the new workspace version for openvmm and adds openvmm_build_info. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 12 changed files in this pull request and generated no new comments.
Suppressed comments (1)
xtask/src/tasks/fmt/lints/package_info.rs:39
- The docs here state that version-carrying crates must also set
publish = false, but the lint logic below only allows versions forVERSION_EXCEPTIONSand does not enforcepublish = false. That makes it easy to accidentally regress the publishing-protection policy in future edits (e.g., adding a new exception without addingpublish = false). Consider either enforcingpublish = falseforVERSION_EXCEPTIONSin the lint, or softening this comment to avoid implying an invariant the tool doesn’t check.
/// List of packages that are allowed to have a version.
///
/// Each of these must also set `publish = false`, since carrying a version
/// forfeits the implicit publishing protection described at the module level.
///
Append .dirty for tracked checkout changes and derive Windows VERSIONINFO directly from the canonical Cargo product version. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4fe65aa5-d620-4856-a525-e32bf98c16b1
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 16 changed files in this pull request and generated no new comments.
Suppressed comments (1)
openvmm/openvmm_build_info/build.rs:113
watch_git_identityemits acargo:rerun-if-changeddirective for every tracked file (git ls-files -z). In a repo this size that can mean thousands of watched paths, which makes Cargo stat a large set of files on every build and can noticeably slow incremental builds.
Consider reducing the watcher set (e.g., a coarser-grained scheme that still toggles the .dirty suffix correctly) so build identity stays fresh without paying an O(tracked_files) cost each build.
if let Some(paths) = git(repo, &["ls-files", "-z"]) {
for path in paths.split_terminator('\0') {
watch_tracked_path(repo, Path::new(path));
}
}
Adds the reusable release-publication primitives needed by the standalone OpenVMM source release described in #4150. - makes release notes and existing-release handling explicit - allows callers to require validation/attestation side effects before publication - distinguishes a missing release from `gh` authentication or server failures - adds a reusable `actions/attest@v4` Flowey node - preserves the existing VmgsTool draft, `TODO` notes, and skip-existing behavior This is independent of the build identity work in #4162 and does not yet add the OpenVMM publication workflow. --------- Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com> Copilot-Session: 4fe65aa5-d620-4856-a525-e32bf98c16b1
| let mut next_component = || { | ||
| version | ||
| .next() | ||
| .and_then(|component| component.parse::<u16>().ok()) | ||
| .expect("OpenVMM's Cargo version must be MAJOR.MINOR.PATCH with u16 components") | ||
| }; | ||
| let major = next_component(); | ||
| let minor = next_component(); | ||
| let patch = next_component(); | ||
| assert!( | ||
| version.next().is_none(), | ||
| "OpenVMM's Cargo version must contain exactly three components" | ||
| ); |
There was a problem hiding this comment.
How much of this structure is guaranteed by Cargo already?
| #![expect(missing_docs)] | ||
|
|
||
| #[cfg(test)] | ||
| #[path = "../version.rs"] |
There was a problem hiding this comment.
Why is this file not in src?
|
|
||
| let product_version = env!("CARGO_PKG_VERSION"); | ||
| let repo_root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../.."); | ||
| let git = collect_git_source(&repo_root); |
There was a problem hiding this comment.
We already use vergen in places to look at git info, would that be cleaner?
| //! The exceptions in [`VERSION_EXCEPTIONS`] are the crates where the version is | ||
| //! *not* meaningless, because something outside the crate reads it. Those | ||
| //! crates lose the publishing protection described above, so each one sets | ||
| //! `publish = false` explicitly instead. |
There was a problem hiding this comment.
We should be checking that they do have publish=false set.
Purpose
Implement the product-version and build-identity portion of #4150 as an independently reviewable first slice.
Behavior
[workspace.package] versionVERSION+g<9-character commit>for every clean Git checkout, including an exact release-tag checkout.dirtywhen a checkout has staged or unstaged tracked changesVERSIONfor a Git-free source tree-Vand detailed identity through--versionMAJOR.MINOR.PATCH.0from the Cargo product version for WindowsVERSIONINFOThe detailed form includes the build kind, canonical product version, full Git revision when available, and build target.
Implementation
openvmm_build_infoto resolve identity at compile timeCARGO_PKG_VERSIONOut of scope
This PR intentionally contains no source-archive assembly, distribution-build gate, release workflow, provenance, packaging guide, telemetry, saved-state metadata, or additional binary metadata surfaces. Those will be separate follow-up PRs after this behavior is accepted.
Validation
cargo check,cargo clippy --all-targets,cargo doc --no-deps, and unit tests for the affected OpenVMM and Flowey packagescargo xtask fmt --fixopenvmm_build_inforemains fresh