Skip to content

fix(npm): repair broken publish pipeline and installer fallback - #67

Merged
tawanorg merged 1 commit into
mainfrom
fix/npm-publish-pipeline
Jul 26, 2026
Merged

tawanorg merged 1 commit into
mainfrom
fix/npm-publish-pipeline

Conversation

@tawanorg

Copy link
Copy Markdown
Owner

Summary

npm publishing has been failing silently since 2026-04-07. The registry is at 1.8.1 while git tags are at v1.17.0 — nine minor releases that never reached the primary install channel, including the /resume history fix and the sync_paths fix.

Channel Version
git tags / GitHub Releases v1.17.0
npm @tawandotorg/claude-sync 1.8.1 (2026-04-06)
@tawandotorg/claude-sync-* platform packages never published

Three faults, each of which hid the next:

  • continue-on-error: true on the publish step meant a failed publish still reported the release green. That is why this went unnoticed for 16 weeks. Removed.
  • publish-npm.sh runs under set -e, so the first platform-package E404 aborted the script before the root package was published — the direct cause of the root being stuck at 1.8.1. Platform failures are now collected and re-raised at the end, so one bad platform blocks neither the others nor the root package, and CI still goes red.
  • install.js pinned its redirect allowlist to objects.githubusercontent.com. GitHub now serves release assets from release-assets.githubusercontent.com, so every download failed and checksum verification was silently skipped along the way. Now matches the githubusercontent.com parent domain and requires https. Added 2026-07-09, three months after the last successful publish, so it never reached a user.

Also restores postinstall: node install.js as a fallback alongside the platform packages, per the chosen design: install.js returns early when the matching optionalDependency already supplied the binary, and otherwise downloads from GitHub Releases. A platform package that fails to publish now degrades to a download instead of leaving no binary at all.

Verification

  • Both install paths exercised for real, not reasoned about:
    • platform package present → skips download, exits 0, no network
    • platform package absent → downloads v1.17.0, checksum verified, ./bin/claude-sync --version → claude-sync version 1.17.0
  • 9 host-allowlist cases under node --test, including evilgithubusercontent.com, githubusercontent.com.evil.com, github.com.evil.com, and http downgrade — all correctly rejected. Wired into CI, since the installer is the primary distribution path and had no test coverage.
  • bash -n, node --check, YAML and JSON parse clean; make check passes.

Action required that this PR cannot do

The underlying E404 is a credentials problem. NPM_TOKEN can write the existing @tawandotorg/claude-sync but cannot create new packages in the @tawandotorg scope — npm returns 404 rather than 403 to avoid leaking package existence.

Rotate it to a granular token with read/write on the whole @tawandotorg scope, not just selected packages. Until then, releases will now fail loudly instead of silently — which is the intended behaviour, but expect red release runs until the token is replaced.

Reviewer note

Removing continue-on-error means the later "Publish to GitHub Packages" step (if: success()) is now skipped when the npm publish fails. I left that as-is deliberately: a half-published release shouldn't propagate to a secondary registry. Easy to make the two channels independent if you'd rather.

npm publishing has been failing silently since 2026-04-07. The registry
sits at 1.8.1 while git tags are at v1.17.0 — nine minor releases that
never shipped to the primary install channel.

Three separate faults, each of which hid the next:

1. `continue-on-error: true` on the publish step meant a failed publish
   still reported the release as successful. Removed, so a publish
   failure now fails the release.

2. publish-npm.sh runs under `set -e`, so the first platform package
   E404 aborted the script before the root package was published —
   which is why the root stayed at 1.8.1. Platform failures are now
   collected and re-raised at the end, so one bad platform no longer
   blocks the others or the root package, and CI still goes red.

3. install.js pinned its redirect allowlist to
   objects.githubusercontent.com. GitHub now serves release assets from
   release-assets.githubusercontent.com, so every download failed and
   checksum verification was silently skipped. The allowlist now matches
   the githubusercontent.com parent domain and requires https, and is
   covered by tests. This was added 2026-07-09, three months after the
   last successful publish, so it never reached a user.

Restores `postinstall: node install.js` as a fallback alongside the
platform packages: install.js returns early when the matching
optionalDependency already provided the binary, and otherwise downloads
from GitHub Releases. A platform package that fails to publish now
degrades to a download instead of leaving no binary at all.

Note: the underlying E404 is a credential problem this commit cannot
fix. NPM_TOKEN can write the existing @tawandotorg/claude-sync but
cannot create new packages in the @tawandotorg scope; it needs
read/write on the whole scope. Until it is rotated, releases will now
fail loudly rather than silently.
@tawanorg
tawanorg merged commit 0911b2a into main Jul 26, 2026
2 checks passed
github-actions Bot pushed a commit that referenced this pull request Jul 26, 2026
## [1.17.1](v1.17.0...v1.17.1) (2026-07-26)

### Bug Fixes

* **npm:** repair broken publish pipeline and installer fallback ([#67](#67)) ([0911b2a](0911b2a))
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 1.17.1 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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