From c6f8d96220c600516a8388479f27cd8ef8209ab4 Mon Sep 17 00:00:00 2001 From: Justin Carper Date: Wed, 26 Aug 2026 11:06:08 -0500 Subject: [PATCH 1/2] ci(release): add workflow_dispatch fallback for tag-push event gaps Push/tag events have intermittently failed to enqueue runs (merges to main after 2026-08-26T14:55Z created no CI runs), blocking tag-triggered publishes. Adds a manual trigger with a required tag input; the job resolves RELEASE_REF_NAME once, checks out the tag's exact commit, and all tag-derived steps use it instead of GITHUB_REF_NAME (mirrors ci.yml's dispatch-scoped model-data-drift pattern). --- .github/workflows/release.yml | 38 ++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d79ec3d..9b16512 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,13 +5,25 @@ on: tags: - "v[0-9]+.[0-9]+.[0-9]+" - "v[0-9]+.[0-9]+.[0-9]+-*" + # Fallback for when a tag push doesn't enqueue a run (GitHub event-delivery + # gaps). Triggers are workflow-wide in Actions, so the tag input is + # re-derived as RELEASE_REF_NAME (see the `ref` step) and every step below + # uses that instead of GITHUB_REF_NAME; the tag is fetched and checked out + # at its exact commit. + workflow_dispatch: + inputs: + tag: + description: "Release tag, e.g. v0.9.0-next.0 (must exist)" + required: true + type: string # Default to no permissions; elevate per-job (least privilege). permissions: {} -# Never run two publishes for the same ref concurrently. +# Never run two publishes for the same release concurrently (dispatch runs +# carry the branch ref, so key the group on the resolved release ref). concurrency: - group: release-${{ github.ref }} + group: release-${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }} cancel-in-progress: false jobs: @@ -22,7 +34,21 @@ jobs: contents: write # create the GitHub Release id-token: write # npm provenance attestation steps: + - name: Resolve release ref + id: ref + run: | + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + echo "RELEASE_REF_NAME=${{ inputs.tag }}" >> "$GITHUB_OUTPUT" + else + echo "RELEASE_REF_NAME=$GITHUB_REF_NAME" >> "$GITHUB_OUTPUT" + fi + - uses: actions/checkout@v7 + with: + # Manual runs dispatch from a branch (usually main); check out the + # tag's exact commit so tag and package.json agree. + ref: ${{ steps.ref.outputs.RELEASE_REF_NAME }} + fetch-depth: 0 - name: Set up Node uses: actions/setup-node@v7 @@ -37,9 +63,10 @@ jobs: - name: Verify tag matches package.json version run: | PKG_VERSION="$(node -p "require('./package.json').version")" - TAG_VERSION="${GITHUB_REF_NAME#v}" + TAG_NAME="${{ steps.ref.outputs.RELEASE_REF_NAME }}" + TAG_VERSION="${TAG_NAME#v}" if [[ "$PKG_VERSION" != "$TAG_VERSION" ]]; then - echo "::error::git tag $GITHUB_REF_NAME (=$TAG_VERSION) does not match package.json version $PKG_VERSION" + echo "::error::tag $TAG_NAME (=$TAG_VERSION) does not match package.json version $PKG_VERSION" exit 1 fi @@ -73,7 +100,8 @@ jobs: - name: Classify release from tag id: version run: | - VERSION="${GITHUB_REF_NAME#v}" + TAG_NAME="${{ steps.ref.outputs.RELEASE_REF_NAME }}" + VERSION="${TAG_NAME#v}" echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT" if [[ "$VERSION" == *-* ]]; then echo "NPM_TAG=next" >> "$GITHUB_OUTPUT" From a0909198a45306d66ff97b5051a2b49873b5ee29 Mon Sep 17 00:00:00 2001 From: Justin Carper Date: Wed, 26 Aug 2026 11:08:42 -0500 Subject: [PATCH 2/2] ci(release): pass explicit tag_name to softprops for dispatch runs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first workflow_dispatch release run published to npm but failed at 'Create GitHub Release' — with GITHUB_REF_NAME=main, softprops had no tag to attach the release to. --- .github/workflows/release.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9b16512..b33a1b2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -128,6 +128,9 @@ jobs: - name: Create GitHub Release uses: softprops/action-gh-release@v3 with: + # Dispatch runs carry the branch ref; GITHUB_REF_NAME isn't the tag + # there, so pass the resolved tag explicitly. + tag_name: ${{ steps.ref.outputs.RELEASE_REF_NAME }} name: "v${{ steps.version.outputs.VERSION }}" generate_release_notes: true prerelease: ${{ steps.version.outputs.PRERELEASE }}