fix(ci): make the Homebrew/Winget bump workflows actually fire

All four bump workflows triggered on `release: types: [released]`, which never
fires here: create-release.yml publishes the release with GITHUB_TOKEN, and
GitHub suppresses workflow-triggering events for GITHUB_TOKEN actions. They had
zero runs across every release up to v1.13.1.

Switch them to `workflow_run` on "Create Release Assets" completion, filtered to
a successful tag push. That also removes a latent race: `released` fired while
the matrix legs were still uploading assets, whereas workflow_run fires after
all of them finish.

The workflow_run payload carries no draft/prerelease flags, so add a
resolve-release composite action that reads them back from the API and feeds
assert-stable-release, keeping the defense-in-depth guard intact instead of
inferring stability from the tag string alone.

Also gate the cask/winget bumps on the package existing upstream. Neither
`amethyst-nostr` nor `VitorPamplona.Amethyst` has been bootstrapped, and
bump-cask-pr/winget-releaser can only update an existing package — without the
gate, fixing the trigger would file a spurious [release-ops] issue on every
release.

Docs: correct the claims this uncovered — Homebrew/Winget are not shipping,
macOS is arm64-only (no Intel DMG), the release carries 31 assets (13 Android,
not 12), Maven Central publishes from a step inside deploy-android and lags
repo1 by tens of minutes, RELEASE_NOTES_ID is minor-releases-only, and note the
git-credential-manager hang that blocks the release push.
This commit is contained in:
Vitor Pamplona
2026-07-29 09:37:24 -04:00
parent 7d26c06fe9
commit 054dffd55d
7 changed files with 358 additions and 102 deletions
@@ -0,0 +1,73 @@
name: Resolve Release
description: >-
Resolve a bump workflow's target tag and that release's real published state.
Companion to assert-stable-release: this one FETCHES the facts, that one
ENFORCES them. Split so the enforcement stays a pure function of its inputs.
Handles both entry points of the bump workflows:
- workflow_run -> tag comes from the triggering run's head_branch
- workflow_dispatch (manual recovery) -> tag comes from the input
In both cases draft/prerelease are read back from the GitHub API rather than
inferred, so a draft or prerelease can never slip through to a third-party
package repo just because the trigger payload lacked the flags.
inputs:
tag:
description: "Release tag to resolve (e.g. vX.Y.Z)"
required: true
github_token:
description: "Token used to read the release via the GH API"
required: true
outputs:
tag:
description: "The resolved tag, verbatim (e.g. v1.13.1)"
value: ${{ steps.resolve.outputs.tag }}
ver:
description: "The tag with the leading 'v' stripped (e.g. 1.13.1)"
value: ${{ steps.resolve.outputs.ver }}
is_prerelease:
description: "'true' if the GH Release is flagged prerelease"
value: ${{ steps.resolve.outputs.is_prerelease }}
is_draft:
description: "'true' if the GH Release is still a draft"
value: ${{ steps.resolve.outputs.is_draft }}
runs:
using: composite
steps:
- name: Resolve tag and release state
id: resolve
shell: bash
env:
TAG: ${{ inputs.tag }}
GH_TOKEN: ${{ inputs.github_token }}
REPO: ${{ github.repository }}
run: |
set -euo pipefail
if [[ -z "$TAG" ]]; then
echo "::error::No tag to resolve (neither workflow_run.head_branch nor the dispatch input was set)"
exit 1
fi
# A missing release here is a real fault, not something to paper over:
# every caller is about to publish this version to an external package
# manager. Fail loudly and let the caller's Report-failure step file it.
if ! META=$(gh release view "$TAG" --repo "$REPO" --json isDraft,isPrerelease 2>&1); then
echo "::error::No GH Release found for tag $TAG in $REPO -- refusing to bump"
echo "$META"
exit 1
fi
IS_DRAFT=$(echo "$META" | jq -r '.isDraft')
IS_PRERELEASE=$(echo "$META" | jq -r '.isPrerelease')
{
echo "tag=$TAG"
echo "ver=${TAG#v}"
echo "is_draft=$IS_DRAFT"
echo "is_prerelease=$IS_PRERELEASE"
} >> "$GITHUB_OUTPUT"
echo "resolved tag=$TAG ver=${TAG#v} draft=$IS_DRAFT prerelease=$IS_PRERELEASE"