diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 96878c5..94bd743 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -4,6 +4,12 @@ on: release: types: [published] workflow_dispatch: + # GitHub does not start new workflow runs for events caused by the default + # GITHUB_TOKEN (e.g. gh release create in another workflow). After + # "Release on merge" creates a release, trigger publish here instead. + workflow_run: + workflows: [Release on merge] + types: [completed] permissions: contents: read @@ -11,12 +17,37 @@ permissions: jobs: publish: + if: >- + github.event_name != 'workflow_run' || + github.event.workflow_run.conclusion == 'success' runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 + with: + ref: ${{ github.event_name == 'workflow_run' && 'main' || github.event_name == 'release' && github.ref || 'main' }} + + - name: Decide whether to publish + id: gate + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + if [[ "${{ github.event_name }}" != "workflow_run" ]]; then + echo "publish=true" >> "${GITHUB_OUTPUT}" + exit 0 + fi + VERSION="$(node -p "require('./package.json').version")" + TAG="v-${VERSION}" + if gh release view "${TAG}" --repo "${{ github.repository }}" >/dev/null 2>&1; then + echo "publish=true" >> "${GITHUB_OUTPUT}" + else + echo "No GitHub release ${TAG} yet (or release job was skipped); skipping publish." + echo "publish=false" >> "${GITHUB_OUTPUT}" + fi # Omit registry-url: setup-node otherwise sets NODE_AUTH_TOKEN to a placeholder and npm publish uses that instead of OIDC. - name: Setup Node + if: steps.gate.outputs.publish == 'true' uses: actions/setup-node@v6 with: node-version: 22 @@ -24,9 +55,11 @@ jobs: cache: npm - name: Upgrade npm for trusted publishing (OIDC) + if: steps.gate.outputs.publish == 'true' run: npm install -g npm@">=11.5.1" - name: Ensure versions match + if: steps.gate.outputs.publish == 'true' shell: bash run: | set -euo pipefail @@ -46,11 +79,14 @@ jobs: fi - name: Install dependencies + if: steps.gate.outputs.publish == 'true' run: npm install --ignore-scripts --no-package-lock - name: Publish to npm + if: steps.gate.outputs.publish == 'true' run: npm publish --access public --provenance - name: Publish to JSR + if: steps.gate.outputs.publish == 'true' run: npx jsr publish diff --git a/.github/workflows/release-on-merge.yml b/.github/workflows/release-on-merge.yml index 6182b30..7c06786 100644 --- a/.github/workflows/release-on-merge.yml +++ b/.github/workflows/release-on-merge.yml @@ -1,7 +1,8 @@ name: Release on merge # When a release/* PR merges into main, create a GitHub release (tag v-). -# The published release triggers publish.yml (npm + JSR). +# Events from GITHUB_TOKEN do not start other workflows; publish.yml is triggered via +# workflow_run when this workflow completes (see publish.yml). on: pull_request: