From a3218bf95b2c1860b08275ef951770912d79b0ed Mon Sep 17 00:00:00 2001 From: Ralf Anton Beier Date: Sun, 3 May 2026 16:14:14 +0200 Subject: [PATCH] ci(release-npm): switch to workflow_run trigger so npm publish auto-fires after Release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Release workflow creates the GitHub Release page using the default GITHUB_TOKEN, and GitHub deliberately suppresses downstream workflow triggers from runs that authenticated with GITHUB_TOKEN (loop-prevention guarantee). As a result, release-npm.yml's `release: published` trigger never fires for v0.7.0 or v0.8.0 — both stuck without npm publication despite the binary archives being on the GitHub Release page. Switch to workflow_run on the upstream Release workflow. This is the documented escape hatch for chaining workflows when the upstream uses GITHUB_TOKEN. Side effects: * head_branch on a tag-push source workflow is the tag name itself (e.g. v0.8.0), so version resolution stays straightforward. * Guard added against non-release tags so a manual Release run on a branch ref doesn't accidentally trigger an npm publish. * Both jobs gated on workflow_run.conclusion == 'success' so failed upstream releases don't fire downstream publishes; workflow_dispatch bypasses the gate for manual backfills. Backfilling v0.7.0 and v0.8.0 npm publication will be done via workflow_dispatch once this lands on main. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/release-npm.yml | 43 ++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release-npm.yml b/.github/workflows/release-npm.yml index 8813fd9..060aecf 100644 --- a/.github/workflows/release-npm.yml +++ b/.github/workflows/release-npm.yml @@ -8,10 +8,26 @@ name: Release NPM # # Platform packages MUST be published before the root package so npm can # resolve optionalDependencies on the first install after tag. +# +# Trigger: workflow_run on the Release workflow, NOT release: published. +# Reason: Release creates the GitHub Release page using the default +# GITHUB_TOKEN, and GitHub deliberately suppresses downstream workflow +# triggers from runs that authenticated with GITHUB_TOKEN (loop-prevention +# guarantee). workflow_run is the documented escape hatch for chaining +# workflows in this case. Note: workflow_run only fires when this file is +# present on the default branch. + +# Release variant: serialize per-release, never cancel. A cancelled npm +# publish run can leave platform packages published but root package +# missing — first-install resolution would fail until manual cleanup. +concurrency: + group: release-npm-${{ github.event.workflow_run.head_branch || github.event.inputs.version || github.ref }} + cancel-in-progress: false on: - release: - types: [published] + workflow_run: + workflows: ["Release"] + types: [completed] workflow_dispatch: inputs: version: @@ -24,6 +40,9 @@ permissions: jobs: publish-platform-packages: name: Publish platform package (${{ matrix.platform }}) + # Skip on failed/cancelled upstream Release runs. Always run for + # manual workflow_dispatch (used for backfills). + if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' runs-on: ubuntu-latest strategy: fail-fast: false @@ -60,14 +79,25 @@ jobs: - name: Resolve version id: version env: - EVENT_TAG: ${{ github.event.release.tag_name }} + # workflow_run: head_branch is the tag name (e.g. v0.8.0) when + # the upstream Release workflow ran on a tag push. + # workflow_dispatch: the user-supplied tag input (used for + # backfills of releases whose initial workflow_run never fired). + RUN_BRANCH: ${{ github.event.workflow_run.head_branch }} INPUT_TAG: ${{ github.event.inputs.version }} run: | - TAG="${EVENT_TAG:-$INPUT_TAG}" + TAG="${INPUT_TAG:-$RUN_BRANCH}" if [ -z "$TAG" ]; then echo "No tag provided" >&2 exit 1 fi + # Guard: only publish for release tags. Release.yml is currently + # only triggered by tag push, but this guard makes the workflow + # safe against accidental manual runs of Release on a branch ref. + if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+ ]]; then + echo "Tag '$TAG' is not a release tag (expected vX.Y.Z); skipping" >&2 + exit 1 + fi VERSION="${TAG#v}" echo "tag=$TAG" >> "$GITHUB_OUTPUT" echo "version=$VERSION" >> "$GITHUB_OUTPUT" @@ -113,6 +143,7 @@ jobs: publish-root-package: name: Publish root package (@pulseengine/rivet) needs: publish-platform-packages + if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -125,10 +156,10 @@ jobs: - name: Resolve version id: version env: - EVENT_TAG: ${{ github.event.release.tag_name }} + RUN_BRANCH: ${{ github.event.workflow_run.head_branch }} INPUT_TAG: ${{ github.event.inputs.version }} run: | - TAG="${EVENT_TAG:-$INPUT_TAG}" + TAG="${INPUT_TAG:-$RUN_BRANCH}" VERSION="${TAG#v}" echo "tag=$TAG" >> "$GITHUB_OUTPUT" echo "version=$VERSION" >> "$GITHUB_OUTPUT"