ci: publish standalone OpenVMM source releases - #4220
ci: publish standalone OpenVMM source releases#4220Ben Hillis (benhillis) wants to merge 7 commits into
Conversation
Assembly and the distribution gate landed without anything that publishes the result, so the archive CI validated was discarded. Add the publication half. A manually dispatched pipeline assembles the archive once, transfers it to the distribution-build gate as an artifact, and then attaches those same bytes to a draft GitHub release along with provenance attestations for both published files. Validating a reassembled copy would be reproducible but would no longer prove that what was tested is what ships. Publication stops at a draft on purpose. A maintainer reviews it and clicks Publish, and GitHub creates openvmm-v<VERSION> at the commit the workflow pinned, so no tag exists for a release nobody approved and the irreversible step stays a human one. Document the maintainer procedure, and update the packaging guide now that the archive and SHA256SUMS have somewhere to be published.
map and depending_on take the receiver by reference.
The page described the gate as validation without saying where that validation stops, which invites more confidence than it earns. Name the one question the gate answers, list the checks it deliberately omits, and say that a release publishes source rather than binaries or a servicing commitment.
Permit a release PR to explicitly select the already-committed version when that value has never been released, avoiding a meaningless Cargo.toml edit for the initial 0.1.0 release. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2f283c1b-ae06-4449-9ac9-897cd279f65e
Pin the attestation action and reject pre-existing release tags so GitHub cannot silently attach a release to a different commit than the assembled source identity. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2f283c1b-ae06-4449-9ac9-897cd279f65e
|
One or more custom setup steps configured for this repository failed during this Copilot code review run: Setup steps run before each review. If the review above is missing context, or no review was posted at all, the failing step above may be the cause. See the workflow run for failure details, fix your setup steps configuration, and re-request a review. Note You can configure setup steps for Copilot code review separately from Copilot cloud agent with a |
There was a problem hiding this comment.
Pull request overview
This PR adds the “publication” half of the OpenVMM standalone source-release flow: a manually dispatched pipeline that assembles the deterministic source archive, validates it via the distro-build gate, generates build-provenance attestations, and drafts a GitHub release. It also adds maintainer documentation for cutting source releases and updates the packaging guide to reflect the new published release artifacts.
Changes:
- Add a new Flowey pipeline + autogenerated GitHub Actions workflow for drafting OpenVMM source releases (archive + SHA256SUMS), gated by the distro-build validation.
- Add build-provenance attestation support for the release artifacts (and pin
actions/attestby commit SHA). - Add/extend Guide documentation for maintainers (source release process) and packagers (verification expectations).
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| Guide/src/SUMMARY.md | Adds the new maintainer guide page to the Guide navigation. |
| Guide/src/dev_guide/contrib/openvmm_source_release.md | New maintainer procedure for selecting a version, dispatching the workflow, and publishing. |
| Guide/src/dev_guide/contrib/openvmm_packaging.md | Updates packager guidance to reference GitHub releases + provenance attestation verification. |
| flowey/flowey_lib_hvlite/src/_jobs/publish_openvmm_gh_release.rs | New job that attests and drafts the GitHub release from the assembled source archive. |
| flowey/flowey_lib_hvlite/src/_jobs/mod.rs | Exposes the new publish job module. |
| flowey/flowey_lib_common/src/attest_build_provenance.rs | Pins actions/attest to a full commit SHA for provenance generation. |
| flowey/flowey_hvlite/src/pipelines/openvmm_source_release.rs | New pipeline wiring: assemble → validate distro build → attest + draft release. |
| flowey/flowey_hvlite/src/pipelines/mod.rs | Registers the new pipeline under the ci command set. |
| .github/workflows/openvmm-source-release.yaml | Autogenerated workflow definition for the new pipeline (manual workflow_dispatch). |
| .flowey.toml | Registers the new Flowey pipeline for GitHub workflow generation. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
`gh release create` binds a draft to an existing tag as-is, and ignores `--target` when that tag already exists. The previous "tag is unused" check therefore only held at draft time: a tag created during the human review window would silently rebind the release to another commit at publish time. Create `refs/tags/openvmm-v<VERSION>` at the archived revision before the draft. Ref creation is atomic, so a rerun either creates the tag or finds it already present, in which case it must still name the exact archived commit. Draft creation then passes `--verify-tag` so it can only ever attach to that tag. Also drop the local backend from the pipeline. It creates a tag and a release in the upstream repository, so there is nothing meaningful for a local run to do. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2f283c1b-ae06-4449-9ac9-897cd279f65e
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.
Suppressed comments (2)
Guide/src/dev_guide/contrib/openvmm_source_release.md:40
<COMMIT>here reads like a full SHA, but OpenVMM’s version formatting uses a short revision prefix (currently 9 chars) and may also append.dirty. Tightening the wording will help maintainers match what they see in practice.
The version stays at the released value after publication. Commits made
afterwards report `<VERSION>+g<COMMIT>` and are identifiable as
development builds, so there is no second commit to "reopen" the version.
flowey/flowey_lib_hvlite/src/_jobs/publish_openvmm_gh_release.rs:126
- The existing-tag verification only accepts lightweight tags (
object.type == "commit"). Ifopenvmm-v<VERSION>ever exists as an annotated tag that ultimately points at the pinned commit (e.g., created out-of-band), this logic will fail even though the tag still names the correct revision. Consider resolvingobject.type == "tag"throughgit/tags/<sha>and comparing the underlying commit SHA.
let tag_type = existing["object"]["type"].as_str();
let tag_target = existing["object"]["sha"].as_str();
if tag_type != Some("commit") || tag_target != Some(target.as_str()) {
anyhow::bail!(
"release tag {tag} already exists at {} ({}) instead of commit {target}",
The tag is a side effect the job cannot take back, and it was created before anything checked whether a release already existed for that version. `publish_gh_release` reads its prerequisites first, so the existing-release check ran only after the tag had been pinned and the artifacts attested. That inverted the intended failure order. If a release existed but its tag did not -- a hand-created draft, or a tag deleted while its release was kept -- a rerun dispatched at a different commit would recreate the tag at that commit, silently rebinding the pre-existing release, and only then fail. That is the rebinding this pipeline exists to prevent. Check for the release first and feed the result into the pin step, so a refused run leaves no tag behind. The shared publisher keeps its own check as a backstop. Also report an existing annotated tag as an annotated tag. `object.sha` names the annotation rather than a commit, so comparing it against the archived revision claimed the tag pointed at the wrong commit when the real problem was the tag kind. Finally, stop implying publication cannot rebind a draft. A draft tracks a tag name and GitHub enforces immutability only after publication, so a tag moved during review is still adopted at publish time. Creating the tag up front rules out publication inventing one elsewhere; it does not freeze the tag. Document confirming the target commit before publishing instead. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2f283c1b-ae06-4449-9ac9-897cd279f65e
Purpose
Add the publication half of the standalone OpenVMM source-release flow now that #4200 has landed. CI already proves that a deterministic source archive can build with distribution-provided dependencies; this adds the manually dispatched workflow that turns those same validated bytes into a reviewable GitHub release.
This PR also selects 0.1.0 as the initial OpenVMM source release. The root
[workspace.package] versionalready carries0.1.0, and noopenvmm-v0.1.0tag or release exists, so there is no no-opCargo.tomledit. Merging this PR is the reviewed decision to use that existing value for the initial release.Release workflow
Add an OpenVMM Source Release workflow with no automatic triggers. When dispatched against a commit, it:
openvmm-<VERSION>.tar.gzandSHA256SUMSonce;openvmm-v<VERSION>at the archived revision;A maintainer reviews the draft, writes release notes, and publishes it.
Why the tag is created before the draft
gh release createbinds a draft to an existing tag as-is and ignores--targetwhen that tag already exists. Checking only that the tag was unused at draft time left a window: a tag created during human review would silently rebind the release to a different commit at publish time, decoupling the published tag from the validated archive.Creating the ref up front closes that window. Ref creation is atomic, so a rerun either creates the tag or finds it already present, in which case it must still name the exact archived commit or the job fails. Draft creation passes
--verify-tagso it can only ever attach to that tag.The tradeoff is that the tag is publicly visible while the release is still a draft. This is documented in the maintainer guide.
Safety properties
SHA256SUMSare published; internal identity metadata stays private to the workflow artifact;actions/atteststep is pinned to a full commit SHA;Documentation
Add a maintainer guide covering version selection, workflow dispatch, draft review and publication, correction policy, and current limitations. The packager guide now distinguishes the release workflow's guarantees from downstream checks it does not perform.
Validation
cargo check -p flowey_lib_common -p flowey_lib_hvlite -p flowey_hvlitecargo clippy --all-targets -p flowey_lib_common -p flowey_lib_hvlite -p flowey_hvlitecargo doc --no-deps -p flowey_lib_common -p flowey_lib_hvlite -p flowey_hvlitecargo test -p flowey_lib_common -p flowey_lib_hvlite -p flowey_hvlitecargo xtask fmt --fix, including Flowey workflow regenerationOut of scope
Prebuilt binaries, OpenPGP signing, generated release notes, and a commitment to service published versions remain separate decisions.