3960d746f4
When a tagged release lands on master, both the master-push and tag-push
events trigger the publish job. The skip-on-exists check (`npm view`)
runs concurrently on both, both see the version as not-yet-published,
and both proceed to `npm publish`. The first wins; the second gets
E403 ("cannot publish over previously published versions") and reds
out the run.
Fixes the race by adding a publish-${{ github.sha }} concurrency group
so the second run queues until the first finishes — by then npm view
sees the published version and the skip path takes over cleanly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
62 lines
1.4 KiB
YAML
62 lines
1.4 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: [master]
|
|
tags: ['v*']
|
|
pull_request:
|
|
branches: [master]
|
|
|
|
jobs:
|
|
test:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "22"
|
|
cache: "npm"
|
|
|
|
- run: npm ci
|
|
|
|
- run: npm run typecheck
|
|
name: Type check
|
|
|
|
- run: npm test
|
|
name: Test
|
|
|
|
publish:
|
|
needs: test
|
|
runs-on: ubuntu-latest
|
|
if: (github.ref == 'refs/heads/master' && github.event_name == 'push') || startsWith(github.ref, 'refs/tags/')
|
|
concurrency:
|
|
group: publish-${{ github.sha }}
|
|
cancel-in-progress: false
|
|
permissions:
|
|
id-token: write
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "22"
|
|
registry-url: "https://registry.npmjs.org"
|
|
cache: "npm"
|
|
|
|
- run: npm ci
|
|
|
|
- run: npm run build
|
|
|
|
- name: Publish (skip if version already exists)
|
|
run: |
|
|
PKG_NAME=$(node -p "require('./package.json').name")
|
|
PKG_VERSION=$(node -p "require('./package.json').version")
|
|
if npm view "${PKG_NAME}@${PKG_VERSION}" version 2>/dev/null; then
|
|
echo "Version ${PKG_VERSION} already published — skipping."
|
|
else
|
|
npm publish --provenance --access public
|
|
fi
|
|
env:
|
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|