Skip to content

Conversation

@kylecarbs
Copy link
Member

@kylecarbs kylecarbs commented Oct 21, 2025

Problem

The npm publish workflow on main has been failing with:

npm error 404  '@coder/cmux@0.3.0' is not in this registry.

This error is misleading. The actual issue is:

  • The workflow runs on every push to main
  • It tries to publish version 0.3.0 every time
  • npm doesn't allow republishing the same version
  • The 404 error is npm's confusing way of saying "this version already exists"

Solution

Use git describe to generate unique pre-release versions for each commit to main. This allows every push to be publishable without version conflicts.

Version Format

On main branch (pre-releases):

0.3.0-next.14.g6c0e10d
└─┬─┘ └─┬─┘ └┬┘ └──┬──┘
  │     │    │     └─ short git hash
  │     │    └─────── commits since last tag
  │     └──────────── pre-release identifier
  └────────────────── base version from package.json

Published to npm with next tag: npm install @coder/cmux@next

On version tags (stable releases):

0.3.0

Published to npm with latest tag: npm install @coder/cmux

How It Works

  1. Generate unique version: Calculate commits since last tag + git hash
  2. Update package.json: Modify version before building
  3. Build: Run make build with the updated version
  4. Check if version exists: See if this exact version is already on npm
  5. Publish or promote:
    • New version → Publish normally
    • Existing version + tag push → Update dist-tag to latest (promotion)
    • Existing version + main push → Skip (already published)

Handling Version Promotion

If a tagged release (e.g., v0.3.0) is pushed but 0.3.0 already exists on npm (maybe published as a pre-release or from a previous run), the workflow will update the dist-tag to latest instead of failing. This allows promoting versions without re-uploading the tarball.

Every commit to main now gets a unique, installable pre-release version! 🎉

Generated with cmux

The workflow was failing because it tried to publish the same version
(0.3.0) on every push to main. npm doesn't allow republishing the same
version, which caused 404 errors with confusing messages.

Changes:
- Add version check before publishing
- Skip publish if version already exists on npm
- Add helpful message explaining how to publish new versions
- Add NODE_AUTH_TOKEN env var for npm publish

This allows the workflow to run successfully on main without failing
when the version hasn't been bumped.
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 64 to 68
fi
- name: Publish to NPM
if: steps.check-version.outputs.exists == 'false'
run: npm publish --tag ${{ steps.npm-tag.outputs.tag }}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Allow tag builds to retag existing versions

The new check-version gate prevents both the tag computation and publish steps whenever the package version already exists on npm. That works for repeated main pushes, but it also skips the workflow when a release tag (refs/tags/v*) is pushed after the same version has already been published with the next tag from main. In that situation the job exits without updating the latest dist-tag, leaving the previous release as latest. Consider handling the tagged release separately (e.g. using npm dist-tag add when the version exists) so that official releases can promote the version to latest even if the tarball was already uploaded.

Useful? React with 👍 / 👎.

Instead of checking if a version exists, generate unique versions
for each commit using git describe. This allows every push to main
to be publishable to npm.

Version format:
- Tags: Use package.json version as-is (e.g., 0.3.0) -> 'latest' tag
- Main: Generate pre-release (e.g., 0.3.0-next.14.g6c0e10d) -> 'next' tag

The pre-release format includes:
- Base version from package.json
- 'next' identifier for pre-releases
- Number of commits since last tag
- Short git commit hash

This ensures every commit gets a unique publishable version.
When a tagged release is pushed but the version already exists on npm
(e.g., from a pre-release or previous publish), update the dist-tag
instead of failing.

Behavior:
- New version -> Publish normally
- Existing version + tag push -> Update dist-tag to 'latest'
- Existing version + main push -> Skip (already published)

This allows promoting a version to 'latest' even if the tarball was
already uploaded under 'next'.
@kylecarbs kylecarbs merged commit a4422a7 into main Oct 21, 2025
8 of 9 checks passed
@kylecarbs kylecarbs deleted the fix-npm-publish-workflow branch October 21, 2025 02:19
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