Skip to content

fix(ci): gate publishing on the registry, and bump actions off Node 20 - #25

Merged
galangel merged 2 commits into
mainfrom
chore/ci-registry-gate-and-action-bumps
Aug 18, 2026
Merged

fix(ci): gate publishing on the registry, and bump actions off Node 20#25
galangel merged 2 commits into
mainfrom
chore/ci-registry-gate-and-action-bumps

Conversation

@galangel

@galangel galangel commented Aug 18, 2026

Copy link
Copy Markdown
Owner

Two independent CI fixes, one commit each so they can be reverted separately.


1. Gate publishing on the registry, not a git diff

check-version compared package.json at HEAD against HEAD~1. That made a version bump a one-shot trigger: when the publish that followed it failed, the bump was already consumed and no later push would ever retry it.

That single flaw stranded three versions, each behind a different publish failure:

version bumped in publish failed on
1.1.1 #16 expired npm token
1.2.0 #15 expired npm token
1.2.1 #18 npm 12 requiring Node ≥ 22

Each needed a fresh version number or a manual dispatch to escape. Now the gate asks the registry instead:

GET registry.npmjs.org/<name>/<version>
  200 → already published → skip
  404 → not there        → publish
  else → fail the job rather than guess

This is idempotent, so a failed publish simply retries on the next push — no stranding, no burnt version numbers.

Knock-on changes:

  • workflow_dispatch no longer bypasses the gate. Bypassing would now mean attempting to republish an existing version, which npm rejects anyway. Dispatch still works for retrying without pushing.
  • fetch-depth: 2 removed — no history needed.
  • Outputs renamed to say what they mean: version_changedshould_publish, new_versionversion.

Verified against the live registry

I extracted the step's script from the parsed YAML and ran it for real, rather than trusting it by inspection:

GET https://registry.npmjs.org/@galangel%2freact-tip-magic/1.2.1 -> 200
@galangel/react-tip-magic@1.2.1 is already published; nothing to do
  → version=1.2.1  should_publish=false

GET https://registry.npmjs.org/@galangel%2freact-tip-magic/9.9.9 -> 404
@galangel/react-tip-magic@9.9.9 is not on the registry; will publish
  → version=9.9.9  should_publish=true

Both branches behave correctly and the scope is URL-encoded properly as @galangel%2freact-tip-magic.


2. Bump actions off the deprecated Node 20 runtime

Every recent run warned that checkout, setup-node and action-gh-release target Node 20, which GitHub has deprecated and is already force-running on Node 24.

action from to
actions/checkout v4 v7
actions/setup-node v4 v7
actions/upload-artifact v4 v7
actions/configure-pages v4 v6
actions/upload-pages-artifact v3 v5
actions/deploy-pages v4 v5
codecov/codecov-action v4 v7
softprops/action-gh-release v1 v3

18 references across all three workflows. Several cross multiple majors, so I checked the inputs actually in use — token/files/fail_ci_if_error, name/path/retention-days, and tag_name/name/generate_release_notes/draft/prerelease — all stable across these ranges. No input changes were needed.

Also confirmed every referenced major tag resolves upstream (so nothing points at a tag that doesn't exist) and all three workflows still parse.


⚠️ What this PR's CI does and does not prove

Worth being explicit, because the coverage is uneven:

Workflow Trigger Verified here?
ci.yml pull_request yes — checkout, setup-node, upload-artifact all exercised
deploy-storybook.yml push to main only no
publish.yml push to main / dispatch no

So configure-pages, upload-pages-artifact, deploy-pages, action-gh-release and the new gate are not exercised until this lands on main. The codecov step is additionally gated on github.event_name == 'push', so codecov-action@v7 is untested here too.

The gate's logic is covered by the local run above. The storybook deploy and the release step are the two things to watch on the first push after merge.

Expected behaviour right after merge

The push will run Publish to npm, the gate will find 1.2.1 already published, and the publish job will skip — same visible outcome as before, but now for the correct reason. The next version bump publishes automatically without a dispatch.

galangel and others added 2 commits August 18, 2026 15:22
The old check compared package.json at HEAD against HEAD~1. That made a
version bump a one-shot trigger: if the publish that followed it failed,
the bump was already consumed and no later push would ever retry it. Three
versions were stranded that way, each by a different publish failure:

  1.1.1  bumped in #16, publish failed on an expired npm token
  1.2.0  bumped in #15, publish failed on an expired npm token
  1.2.1  bumped in #18, publish failed on npm 12 requiring Node >= 22

Ask the registry instead: GET registry.npmjs.org/<name>/<version> and read
the status. 200 means published, so skip; 404 means it is not there, so
publish; anything else fails the job rather than guessing. This is
idempotent, so a failed publish just retries on the next push.

Consequences:

- workflow_dispatch no longer needs to bypass the gate. Bypassing would now
  mean attempting to republish an existing version, which npm rejects
  anyway. Dispatch is still useful for retrying without pushing.
- fetch-depth: 2 is gone; no history is needed.
- Outputs renamed to say what they mean: version_changed -> should_publish,
  new_version -> version.

Verified by running the step's script locally against the live registry:
1.2.1 returns 200 and yields should_publish=false, a synthetic 9.9.9
returns 404 and yields should_publish=true, and the scope is URL-encoded
correctly as @galangel%2freact-tip-magic.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every recent run warned that actions/checkout, actions/setup-node and
softprops/action-gh-release target Node 20, which GitHub has deprecated and
is already force-running on Node 24.

Bumped across all three workflows, to the current major of each:

  actions/checkout              v4 -> v7
  actions/setup-node            v4 -> v7
  actions/upload-artifact       v4 -> v7
  actions/configure-pages       v4 -> v6
  actions/upload-pages-artifact v3 -> v5
  actions/deploy-pages          v4 -> v5
  codecov/codecov-action        v4 -> v7
  softprops/action-gh-release   v1 -> v3

Every input in use is stable across these majors: token/files/
fail_ci_if_error for codecov, name/path/retention-days for upload-artifact,
and tag_name/name/generate_release_notes/draft/prerelease for the release
step. No input changes were needed.

Confirmed each referenced major tag resolves in its upstream repository and
that all three workflows still parse.

Note on coverage: ci.yml runs on pull_request, so checkout, setup-node and
upload-artifact are exercised by this PR. deploy-storybook.yml and
publish.yml only run on pushes to main, and the codecov step is gated on
github.event_name == 'push', so those three are not verified until this
lands on main.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@galangel
galangel merged commit 5aeb2cb into main Aug 18, 2026
6 checks passed
@galangel
galangel deleted the chore/ci-registry-gate-and-action-bumps branch August 18, 2026 12:38
galangel added a commit that referenced this pull request Aug 18, 2026
#25)

* fix(ci): gate publishing on the registry instead of a git diff

The old check compared package.json at HEAD against HEAD~1. That made a
version bump a one-shot trigger: if the publish that followed it failed,
the bump was already consumed and no later push would ever retry it. Three
versions were stranded that way, each by a different publish failure:

  1.1.1  bumped in #16, publish failed on an expired npm token
  1.2.0  bumped in #15, publish failed on an expired npm token
  1.2.1  bumped in #18, publish failed on npm 12 requiring Node >= 22

Ask the registry instead: GET registry.npmjs.org/<name>/<version> and read
the status. 200 means published, so skip; 404 means it is not there, so
publish; anything else fails the job rather than guessing. This is
idempotent, so a failed publish just retries on the next push.

Consequences:

- workflow_dispatch no longer needs to bypass the gate. Bypassing would now
  mean attempting to republish an existing version, which npm rejects
  anyway. Dispatch is still useful for retrying without pushing.
- fetch-depth: 2 is gone; no history is needed.
- Outputs renamed to say what they mean: version_changed -> should_publish,
  new_version -> version.

Verified by running the step's script locally against the live registry:
1.2.1 returns 200 and yields should_publish=false, a synthetic 9.9.9
returns 404 and yields should_publish=true, and the scope is URL-encoded
correctly as @galangel%2freact-tip-magic.


* chore(ci): bump actions off the deprecated Node 20 runtime

Every recent run warned that actions/checkout, actions/setup-node and
softprops/action-gh-release target Node 20, which GitHub has deprecated and
is already force-running on Node 24.

Bumped across all three workflows, to the current major of each:

  actions/checkout              v4 -> v7
  actions/setup-node            v4 -> v7
  actions/upload-artifact       v4 -> v7
  actions/configure-pages       v4 -> v6
  actions/upload-pages-artifact v3 -> v5
  actions/deploy-pages          v4 -> v5
  codecov/codecov-action        v4 -> v7
  softprops/action-gh-release   v1 -> v3

Every input in use is stable across these majors: token/files/
fail_ci_if_error for codecov, name/path/retention-days for upload-artifact,
and tag_name/name/generate_release_notes/draft/prerelease for the release
step. No input changes were needed.

Confirmed each referenced major tag resolves in its upstream repository and
that all three workflows still parse.

Note on coverage: ci.yml runs on pull_request, so checkout, setup-node and
upload-artifact are exercised by this PR. deploy-storybook.yml and
publish.yml only run on pushes to main, and the codecov step is gated on
github.event_name == 'push', so those three are not verified until this
lands on main.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant