Skip to content

fix(ci): declare the production environment so the token reaches the job - #500

Merged
fjmorant merged 1 commit into
masterfrom
fix/publish-environment
Sep 26, 2026
Merged

fjmorant merged 1 commit into
masterfrom
fix/publish-environment

Conversation

@fjmorant

Copy link
Copy Markdown
Owner

NPM_TOKEN was added as a secret of the production environment, not as a repository secret:

$ gh api .../environments/production/secrets   ->  NPM_TOKEN
$ gh api .../actions/secrets                   ->  none
$ grep 'environment:' .github/workflows/publish.yml  ->  (nothing)

An environment's secrets are only visible to a job that declares that environment. The publish job declared none, so secrets.NPM_TOKEN resolved to empty and a real release would have failed at npm publish with a 403 — which reads like a problem with the npm account rather than a secret that never arrived.

The rehearsal could not have caught this. npm only warns about missing authentication under --dry-run, so the manual run went green.

Declaring the environment, rather than moving the secret

Your setup is the better one, so the workflow now adapts to it:

jobs:
  publish:
    environment: production

Environment secrets bring protection rules with them — required reviewers, wait timers, and a restriction on which branches and tags may deploy. Worth using now that the job declares it:

Settings → Environments → production → Deployment branches and tags → v*

That makes it impossible to publish from anything but a release tag, which is a stronger guarantee than the tag check this workflow performs on itself. Currently set to "No restriction", and there are no protection rules, so merging this changes nothing about what is allowed — it only makes those controls available.

Plus a guard for the general case

A missing token now fails before the gate rather than after it, with a message naming the cause:

event token
release set proceeds
release empty fails immediately, ::error::NPM_TOKEN is empty…
rehearsal empty warns, continues — nothing to authenticate against anyway
rehearsal set proceeds

This is the same class of mistake as the tag mismatch, which I guarded and this one I did not. It sits next to that check, so both cheap failures happen in the first ~30 seconds instead of after lint, tests and three build checks.

After merging

Re-run Publish from the Actions tab. With the environment declared, the guard should now print "NPM_TOKEN is reaching this job" instead of the warning — which is the confirmation the earlier rehearsal could not give you. Then gh release create v1.0.0 --title 1.0.0 --generate-notes.

🤖 Generated with Claude Code

NPM_TOKEN was added as a secret of the production environment rather than as a
repository secret. An environment's secrets are only visible to a job that
declares that environment, and the publish job declared none, so
secrets.NPM_TOKEN resolved to empty.

The rehearsal could not catch this. npm only warns about missing
authentication under --dry-run, so the manual run went green while a real
release would have failed at npm publish with a 403 — which reads like a
problem with the npm account rather than a secret that never arrived.

Declaring the environment is the better fix than moving the secret. Environment
secrets bring protection rules with them: required reviewers, wait timers, and
a restriction on which branches and tags may deploy. Limiting the latter to v*
makes it impossible to publish from anything but a release tag, which is
stronger than the tag check this workflow does for itself.

Also adds a guard for the case in general, next to the tag check and before the
gate rather than after it. An empty token fails a release immediately with a
message naming the cause, and warns without failing on a rehearsal, where there
is nothing to authenticate against anyway.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@fjmorant
fjmorant merged commit 1ed59c6 into master Sep 26, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant