Skip to content

npm release pipeline + bin rename (ccr collides with upstream CCR) - #1

Merged
acrot0 merged 2 commits into
mainfrom
feat/npm-release
Sep 24, 2026
Merged

acrot0 merged 2 commits into
mainfrom
feat/npm-release

Conversation

@acrot0

@acrot0 acrot0 commented Sep 24, 2026

Copy link
Copy Markdown
Owner

What

  1. .github/workflows/release.yml — push a v* tag and it runs the full test suite, asserts the tag agrees with package.json, prints the packed tarball for review, then publishes with --provenance. workflow_dispatch with dry_run: true rehearses everything short of publishing.

  2. bin rename: ccr → ccr-toolkit — the upstream CCR CLI already owns the command ccr (@musistudio/claude-code-router v3.1.1, verified on the registry). A global install of both packages collides with EEXIST, leaving whichever installed second broken. Unpublished, so the rename is free now and expensive after. The four hard-coded ccr strings in cli.mjs output and the README sample are updated to match.

  3. npm metadata — repository/bugs/homepage added. npm publish --provenance requires a repository field pointing at the publishing repo; without it the publish step fails.

  4. README: npm install path documented; the <you> placeholder left in the clone URL fixed; tests badge 185 → 195.

Verification

  • npm test: 195/195 passing
  • npm pack --dry-run: 12 files, 40.7 kB — contents correct
  • node src/cli.mjs --list: all ccr-toolkit references aligned

Before the first npm release (one-time)

  1. Merge this, then add the NPM_TOKEN repository secret (Settings → Secrets → Actions).
  2. npm login locally, or create the token at npmjs.com.
  3. Note: tag v0.2.0 already exists (GitHub release) and npm has no 0.2.0 — either publish as 0.2.1 (recommended: tag v0.2.1, bump version first) or delete and re-push the v0.2.0 tag to trigger the workflow.
  4. Rehearse once with workflow_dispatch → dry_run: true before the first real tag.

Tag-driven npm publish with provenance: push a v* tag and the full test
suite, a tag/version agreement check, and a tarball content review run
before anything ships. workflow_dispatch with dry_run: true rehearses
the whole pipeline without publishing.

Renames the main bin from ccr to ccr-toolkit — the upstream CCR CLI
already owns ccr, so a global install of both packages collides with
EEXIST, leaving whichever installed second broken. Adds the
repository/bugs/homepage metadata that npm publish --provenance
requires, documents the npm install path, and fixes the <you>
placeholder left in the clone URL.
npm 正在淘汰长期发布 token:绕过 2FA 的 granular access token 已于
2026 年 8 月失去敏感账号/包管理操作权限,约 2027 年 1 月将失去直接
发布能力——发布面收缩为「读私有包 + 暂存发布,需人工 2FA 批准」。
原 workflow 用的正是这种 NPM_TOKEN,届时会失效。

改为 OIDC 优先:包存在后,npm 自动识别 GitHub Actions 的 OIDC 环境,
用短时、绑定 workflow 的 token 认证,无长期密钥可泄露或轮换。

但 OIDC 无法冷启动。读 npm 源码确认其实现是向
  POST /-/npm/v1/oidc/token/exchange/package/<包名>
换取 token——交换以「包已存在且已配可信发布者」为前提,注册表没有
「用 OIDC 发布全新包」的端点。故首次发布仍走 token,之后自动切 OIDC。

token 传递方式:以 NPM_TOKEN 交给 shell(npm 不读此名),仅在非空时
export 成 NODE_AUTH_TOKEN。这样缺失 secret 时 npm 看到的是「未定义」
而非「已定义为空」,直接走 OIDC 分支,不依赖 npm 对空 token 的处理。

新增 11 项测试锁住这些在打 tag 时才暴露、且失败得很晚的契约
(id-token 权限、provenance、token 传法、dry_run 守卫、测试先于发布、
tag 与版本一致、显式指定公共 registry、repository 字段、冷启动说明)。

顺带修正 README 中过期的测试数(103 → 206,badge 同步),并把 harness
遥测目录加进 .gitignore。

测试 206 项全绿;npm pack 12 文件正常。
@acrot0
acrot0 merged commit b2f1d8a into main Sep 24, 2026
7 checks passed
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