From 368bd820944bae80b240dfc0b4593eb71cc8c198 Mon Sep 17 00:00:00 2001 From: Rob Gilbreath Date: Wed, 2 Sep 2026 20:18:52 -0800 Subject: [PATCH] ci: skip publish when the version is already on npm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit npm publish over an existing version is a hard E403, so every merge to master that didn't bump package.json (Dependabot's, and CI-only PRs now that verify-version-bump exempts them) ended in a red publish run — run 33714086138 after #19. Look the version up first, as datto-rmm-api-client and timezest already do; the package is access: restricted, so the lookup uses the read-only NPM_TOKEN while the publish itself stays on OIDC trusted publishing. --- .github/workflows/npm-publish.yml | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 45d9384..dc427a8 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -65,8 +65,30 @@ jobs: - name: Install dependencies run: npm ci + # Skip when this exact version is already on npm. `npm publish` over an + # existing version is a hard E403, which turned every unbumped merge — + # Dependabot's, and CI-only PRs now that the bump gate exempts them — + # into a red publish run (run 33714086138, 2026-09-02). The package is + # `access: restricted`, so the lookup needs the read-only NPM_TOKEN; + # the publish itself stays on OIDC trusted publishing. + - name: Check if version already published + id: check + shell: bash + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: | + set -euo pipefail + NAME=$(node -p "require('./package.json').name") + VERSION=$(node -p "require('./package.json').version") + if npm view "${NAME}@${VERSION}" version >/dev/null 2>&1; then + echo "published=true" >> "$GITHUB_OUTPUT" + echo "::notice::${NAME}@${VERSION} already on npm — no version bump on this commit, skipping publish." + else + echo "published=false" >> "$GITHUB_OUTPUT" + echo "${NAME}@${VERSION} not yet published — will publish." + fi + # No build step: this package ships index.js / index.d.ts directly. - # `npm publish` is a no-op failure if the version already exists, so a - # push without a version bump simply doesn't release. - name: Publish to npm + if: steps.check.outputs.published != 'true' run: npm publish