已关闭
feat(build): 新增 npm 分发渠道,支持 npx 一行安装 gitcode cli #496
aflyingto创建于  8月4日关闭于  8月4日
aflyingto成员
8月4日 创建

Background

GitCode CLI 当前分发渠道:PyPI wheel(内置全平台二进制)、DEB/RPM、Homebrew、独立二进制、Docker。无 npm 渠道(仓库无 package.json,release workflow 不涉及 npm)。

近期集成的官方 lark-cli 提供 npx @larksuite/cli@latest install 一行安装体验(npm 包 + install 子命令引导:装二进制 + 装补全 + 装配套)。用户反馈:希望 GitCode CLI 也有同款一行安装,覆盖 Node-first 用户与只有 node 的 CI 镜像。

Proposal

新增薄 npm 包作为分发渠道,发布方式对标 lark-cli 与现有 PyPI wheel:

设计

  • 新建 npm 包(@gitcode/cli 或 gitcode-cli,命名/所有权待定),bin 指向一个 Node wrapper 脚本
  • wrapper 复用 gc_cli/wrapper.py 的平台选择逻辑(linux/darwin/windows × amd64/arm64),按 process.platform/process.arch 选内置二进制并 exec
  • 提供 install 子命令:把二进制写入 PATH 可达位置(或包内 bin)、装 shell 补全(bash/zsh/fish),对标 lark-cli 的 install 引导
  • 凭证:npm 包不含任何 GitCode/飞书令牌;只分发二进制
  • 安装一行:npx @gitcode/cli@latest install(或 npm i -g @gitcode/cli && gc)

发布流程

  • release workflow(.github/workflows/release.yml)新增 npm job:构建 Node wrapper + 打包各平台二进制 + 发布到 npm
  • npm 不支持 OIDC Trusted Publishing(与 PyPI 不同),需配置 npm automation token 为 GitHub Secret(或 npm provenance/SLSA)
  • 发布后验证扩展到 npm:npm view @gitcode/cli version == 目标版本;npx @gitcode/cli@latest install 装出的 gc version 输出正确
  • spec/delivery/release-process.md 与 build-and-package.md 增补 npm 渠道章节

Acceptance Criteria

Alternatives

  • 保持现状不加 npm:Node 用户走 Homebrew/wheel/二进制。但 node-only CI 镜像无 python/brew 时门槛高。
  • npm 包只做下载器(不内置二进制):首运行从 GitCode/GitHub Release 下载二进制。包更小但需联网首运行;与 lark-cli(内置)体验不一致。
  • 复用 PyPI wheel 的二进制,npm 只做触发:技术可行但 npm 生态用户期望 npm 包自包含。

不在本 Issue 范围

  • npm 包名/所有权的最终决定(需先在 npm 注册并确认)
  • 是否引入 npm provenance/SLSA 签名(后续增强)
likedislike
Aaflyingto成员
8月4日 添加了label:agent-friendlyfeaturepriority:mediumscope/build
Aaflyingto成员
8月4日 添加了label:status/triage
aflyingto成员
8月4日 评论:

验证记录

  • 当前验证版本/分支:origin/main(无 npm 基础设施)
  • 需求确认:用户反馈希望支持 npx <pkg> install 一行安装,覆盖 Node-first 用户与纯 node CI 镜像
  • 核查命令:
    • git ls-tree -r origin/main --name-only | grep -iE 'package\.json|node_modules|\.npmrc' → 空(无 npm 基础设施)
    • npm view gitcode-cli version → 1.1.15(非 scoped 名已被他人占用)
    • npm view @gitcode/cli → 404 Not Found(scoped 名 @gitcode/cli 可用)
  • 结论:需求真实,无重复实现,方案(薄 npm 包 + Node wrapper 复用 wheel 平台选择逻辑 + install 子命令)可行。包名定为 @gitcode/cli(scoped)。

人工前置(不阻塞代码实现,但阻塞首次 npm publish)

  • npm 上需存在 gitcode 组织(org)并由发布者拥有写权限;若不存在需先创建
  • GitHub 仓库需配置 NPM_TOKEN(automation token)Secret 给 release workflow 的 npm job
  • npm 不支持 OIDC Trusted Publishing(与 PyPI 不同)

代码、wrapper、workflow、spec/docs 可先行实现;首次 npm publish 待上述人工配置完成后随下次发版执行。

likedislike
Aaflyingto成员
8月4日 添加了label:status/in-progress, status/verified
Aaflyingto成员
8月4日 关联了pull request:feat(build): npm 分发渠道 @gitcode-cli/cli (#496)
Aaflyingto成员
8月4日 关闭了 issue
Aaflyingto成员
8月4日 关联了pull request:fix(npm): 确定性化 wrapper/install 单测 (#496)
Aaflyingto成员
8月4日 关联了pull request:feat(build): npm publish 改用 OIDC Trusted Publishing (#496)
Aaflyingto成员
8月4日 关联了pull request:fix(npm): bin/gc.js 加 shebang 修复 npm bin shim (#496)
aflyingto成员
8月5日 评论:

交付确认 ✅

npm 分发渠道已完整落地并验证:

最终机制

  • npm 包 @gitcode-cli/cli(scoped,gitcode-cli org)
  • Node wrapper npm/bin/gc.js(shebang + 平台二进制选择 + install 引导装二进制/补全/PATH)
  • release workflow npm job:交叉编译 5 平台二进制 + 同步版本 + npm publish,经 OIDC Trusted Publishing(id-token: write,无 NPM_TOKEN,自动 provenance)
  • npm/package.json repository.url = https://github.com/gitcode-cli/cli.git(OIDC 校验)

落地历程

  • PR 431:npm 包 + workflow npm job(token 方式,首发失败)
  • PR 433:确定性化单测
  • PR 435:改 OIDC Trusted Publishing(Classic token 2025-11 已移除,granular 无法创建首个包)
  • PR 436:补 bin/gc.js shebang(修 0.10.2 bin shim bug)
  • PR 437:v0.10.3 release notes + 版本同步

发版结果

  • v0.10.1 / v0.10.2:npm job 失败(granular 404 / shebang bug),PyPI/Homebrew/GitHub 已发
  • v0.10.3:全渠道成功——npm 经 OIDC 自动发布,npx @gitcode-cli/cli@0.10.3 install 端到端验证通过(gc version → 0.10.3 / commit 1ebe4a6)
  • 0.10.2 已 deprecate(bin shim 坏)

用户安装

npx @gitcode-cli/cli@latest install
# 或
npm install -g @gitcode-cli/cli

Issue 交付完成。

likedislike
Aaflyingto成员
8月5日 关联了pull request:fix(npm): 去掉误导性 'official' 措辞 (#496)
Aaflyingto成员
8月6日 关联了pull request:chore(npm): 扩充 keywords 提升可发现性 (#496)