-
Notifications
You must be signed in to change notification settings - Fork 0
fix(release): stop a stable cut from silently shipping without native packages #198
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
b64450b
fix(release): stop a stable cut from silently shipping without native…
MichaelTaylor3d 338ce56
docs(release): record the packaging guarantee the stable path now enf…
MichaelTaylor3d 9e08e82
docs(devlog): a successful tag push is not proof the release workflow…
MichaelTaylor3d 83bbde3
fix(release): identify a tag's runs by commit, and always rebuild on …
MichaelTaylor3d File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| # The RELEASE ASSET GUARD (dig_ecosystem#2290). | ||
| # | ||
| # A `vX.Y.Z` release of dig-node is not shippable just because its binaries exist. dig-updater's | ||
| # feedsign resolves dig-node by the NATIVE INSTALL PACKAGE file names — the beacon installs | ||
| # dig-node by handing a package to msiexec/installer/dpkg, it never places a bare binary — and it | ||
| # FAILS CLOSED on the whole signed manifest when even one component cannot be resolved. So a | ||
| # stable release that carries binaries but no `.msi`/`.pkg`/`.deb` does not merely ship an | ||
| # incomplete dig-node: it freezes auto-update for EVERY product on the stable channel. | ||
| # | ||
| # That is not hypothetical. `v0.99.9` shipped binaries only, feedsign failed closed on four | ||
| # consecutive runs, and the stable manifest sat frozen and then EXPIRED for ~15 hours while every | ||
| # individual workflow run in this repo reported success. Nothing was red, because nothing was | ||
| # asking the one question that mattered: does the published release actually carry the assets the | ||
| # feed needs? | ||
| # | ||
| # This workflow asks it, and is the only place that does. | ||
| # | ||
| # * workflow_call — the stable release path (nightly-release.yml) waits on this after cutting a | ||
| # tag, so a package-less stable release reddens the release run itself rather than surfacing | ||
| # hours later as a feed failure in another repo. | ||
| # * workflow_dispatch — point it at ANY tag on demand. This is what makes the guard falsifiable: | ||
| # dispatching it at a release known to lack packages MUST fail, and at a complete release MUST | ||
| # pass. A guard that cannot be shown to go red is not a guard. | ||
| # | ||
| # It polls rather than sampling once, because the binary build and the package build are separate | ||
| # workflows that finish at different times; a single sample would race them and produce a red that | ||
| # only means "not finished yet". | ||
| name: Verify release assets | ||
|
|
||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| tag: | ||
| description: "The release tag to verify (e.g. v0.99.9)." | ||
| type: string | ||
| required: true | ||
| timeout_minutes: | ||
| description: >- | ||
| How long to wait for the assets to appear before failing. The default spans a cold | ||
| cross-OS package build (the .msi and .pkg legs dominate). | ||
| type: number | ||
| required: false | ||
| default: 75 | ||
| workflow_dispatch: | ||
| inputs: | ||
|
MichaelTaylor3d marked this conversation as resolved.
|
||
| tag: | ||
| description: "The release tag to verify (e.g. v0.99.9)." | ||
| type: string | ||
| required: true | ||
| timeout_minutes: | ||
| description: "How long to wait for the assets to appear before failing." | ||
| type: number | ||
| required: false | ||
| default: 5 | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| verify: | ||
| name: Verify ${{ inputs.tag }} carries the native install packages | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Assert the feed-resolvable assets are present | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| REPO: ${{ github.repository }} | ||
| TAG: ${{ inputs.tag }} | ||
| TIMEOUT_MINUTES: ${{ inputs.timeout_minutes }} | ||
| run: | | ||
| set -euo pipefail | ||
|
|
||
| # The version as it appears in asset names: the tag without its leading `v`. | ||
| VERSION="${TAG#v}" | ||
|
|
||
| # EXACTLY the names dig-updater's feedsign looks for. Kept as a literal list rather than | ||
| # derived from a glob: a glob would happily accept a `.deb` for the wrong arch or a | ||
| # stale version and call the release complete, which is the failure this guard exists to | ||
| # catch. | ||
| # | ||
| # THIS IS THE THIRD COPY OF A CROSS-REPO CONTRACT, and a shell step cannot import the | ||
| # Rust constant that owns it. Producer: `package.yml` in this repo. Consumer: | ||
| # `dig-updater/crates/dig-updater-feedsign/src/resolve.rs` (`asset_name_parts`). | ||
| # Verifier: here. Nothing enforces that the three agree, so they are held together by | ||
| # `SYSTEM.md` (dig-updater section, "dig-node release-asset file names") and the | ||
| # `canonical` skill (beacon/update trust anchors). Change one, change all three. | ||
| # | ||
| # Note macOS contributes ONE name, not two: the `.pkg` is universal and carries no arch | ||
| # token, so `macos/arm64` and `macos/x64` both resolve to it — feedsign's five platforms | ||
| # yield four distinct file names. | ||
| # | ||
| # `arm64.deb` is required here DELIBERATELY, and this is stricter than feedsign's own | ||
| # failure condition. feedsign fails closed only when a component resolves ZERO assets, so | ||
| # a release missing just `arm64.deb` would still publish — silently dropping linux/arm64 | ||
| # hosts from auto-update rather than reddening anything. That silent drop is exactly the | ||
| # arm64 platform floor (#1741/#1736/#2126), so the stable channel treats a missing arm64 | ||
| # package as a failed release. Do not relax this to match feedsign. | ||
| EXPECTED=( | ||
| "dig-node_${VERSION}_amd64.deb" | ||
| "dig-node_${VERSION}_arm64.deb" | ||
| "dig-node-${VERSION}-macos.pkg" | ||
| "dig-node-${VERSION}-windows-x64.msi" | ||
|
MichaelTaylor3d marked this conversation as resolved.
|
||
| ) | ||
|
|
||
| deadline=$(( $(date +%s) + TIMEOUT_MINUTES * 60 )) | ||
| attempt=0 | ||
|
|
||
| while :; do | ||
| attempt=$(( attempt + 1 )) | ||
|
|
||
| # A missing release is a legitimate "not yet" while the release workflow is still | ||
| # running, so it is treated the same as a missing asset rather than aborting early. | ||
| assets="$(gh release view "$TAG" --repo "$REPO" --json assets --jq '.assets[].name' 2>/dev/null || true)" | ||
|
|
||
| missing=() | ||
| for name in "${EXPECTED[@]}"; do | ||
| printf '%s\n' "$assets" | grep -qxF "$name" || missing+=("$name") | ||
| done | ||
|
|
||
| if [ ${#missing[@]} -eq 0 ]; then | ||
| echo "$TAG carries all ${#EXPECTED[@]} native install packages — feedsign can resolve dig-node." | ||
| { | ||
| echo "### Release assets verified — \`$TAG\`" | ||
| echo | ||
| for name in "${EXPECTED[@]}"; do echo "- \`$name\`"; done | ||
| } >> "$GITHUB_STEP_SUMMARY" | ||
| exit 0 | ||
| fi | ||
|
|
||
| if [ "$(date +%s)" -ge "$deadline" ]; then | ||
| { | ||
| echo "### Release assets MISSING — \`$TAG\`" | ||
| echo | ||
| echo "dig-updater's feedsign cannot resolve dig-node from this release, so the" | ||
| echo "STABLE signed feed will fail closed for every component until it is fixed." | ||
| echo | ||
| echo "Missing:" | ||
| for name in "${missing[@]}"; do echo "- \`$name\`"; done | ||
| } >> "$GITHUB_STEP_SUMMARY" | ||
| echo "::error::release $TAG is missing ${#missing[@]} native install package(s): ${missing[*]}. dig-updater feedsign resolves dig-node by these names and fails closed on the ENTIRE stable manifest when they are absent. Attach them (dispatch package.yml against the $TAG ref) before this release is allowed to stand as latest." | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "attempt $attempt: still missing ${#missing[@]} of ${#EXPECTED[@]} (${missing[*]}); retrying…" | ||
| sleep 30 | ||
| done | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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
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
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.