Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ jobs:
# Bucket / prefix / allowlists live in the FC function.
FC_TRIGGER_URL: ${{ vars.FC_TRIGGER_URL }}
FC_RELEASE_AUDIENCE: ${{ vars.FC_RELEASE_AUDIENCE }}
# Script order: git tag, then binary GitHub Release + OSS, then npm.
# OSS upload can fail on a network blip; npm must not succeed first.
run: node tools/release/publish-stable.mjs ${{ inputs.package == 'knowledge-studio-cli' && '--knowledge' || '' }}

publish-channel:
Expand Down Expand Up @@ -162,6 +164,8 @@ jobs:
# credentials in this repo (see publish-stable env notes).
FC_TRIGGER_URL: ${{ vars.FC_TRIGGER_URL }}
FC_RELEASE_AUDIENCE: ${{ vars.FC_RELEASE_AUDIENCE }}
# Script order: binary GitHub Release + OSS, then npm.
# OSS upload can fail on a network blip; npm must not succeed first.
run: node tools/release/publish-channel.mjs ${{ inputs.package == 'knowledge-studio-cli' && '--knowledge' || '' }} --channel "${{ inputs.channel }}"

# bailian-kb-dsh is the dsh plugin (downstream host adapter): independent version,
Expand Down
16 changes: 9 additions & 7 deletions docs/agents/publish.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@

```text
publish-stable.mjs / publish-channel.mjs ← 唯一发版入口
├─ npm(pnpm publish)
└─ binary(lib/binary-release
→ binary-build
→ gh-release
→ oss-direct-upload → FC release 通道)
├─ binary 先走(lib/binary-release
│ → binary-build → gh-release
│ → oss-direct-upload → FC release 通道)
└─ OSS 成功后再 npm(pnpm publish)
```

bailian-cli 的二进制(GitHub Release + OSS)在 npm 之前。OSS 上传受网络波动可能失败;若 npm 先成功,会出现 latest 已发出但 CDN 没有对应二进制。stable 仍要先推 `v<version>` tag,因为 GitHub Release 首次创建带 `--verify-tag`。`knowledge-studio-cli` / `--skip-binary` 没有二进制,仍只发 npm。

`tools/release/lib/binary-release.mjs` 等是实现,一般不要单独当发版入口(调试可用)。

### OSS 通道:FC 预签名上传(仓库不持有任何 OSS 凭据)
Expand Down Expand Up @@ -73,15 +74,15 @@ workflow 的 `channel` 输入**只决定 npm dist-tag**(如 `mcp` / `plugin` /
1. 在 GitHub 触发 Publish workflow,mode 选 `channel`,channel 填 npm dist-tag 名:
- **`bailian-cli`**:npm 发到该 tag;二进制同时刷新 CDN `sync-release.json`(与 tag 名无关)。本机验证:`BAILIAN_CHANNEL=sync-release`。**先发二进制(zip+tar.gz 上齐)再发静态仓 `install.sh`**,避免新脚本去拉还不存在的 `.tar.gz`。
- **`knowledge-studio-cli`**:仅 npm(自动跳过 binary,不碰 `sync-release.json`)
2. CI 自动:生成 `0.0.0-beta-<sha7>-<YYYYMMDDHHMM>`(UTC 到分钟;同 commit 同分钟重跑会覆盖同号)→ 临时 bump → 自检 → **npm 发到 dist-tag** →(bailian-cli)**Bun 编二进制 + GH prerelease + 覆盖 `sync-release.json`** → 还原 package.json
2. CI 自动:生成 `0.0.0-beta-<sha7>-<YYYYMMDDHHMM>`(UTC 到分钟;同 commit 同分钟重跑会覆盖同号)→ 临时 bump → 自检 →(bailian-cli)**Bun 编二进制 + GH prerelease + 覆盖 `sync-release.json`** → **npm 发到 dist-tag** → 还原 package.json
3. 对应脚本:`tools/release/publish-channel.mjs`

### stable 发布

1. 确保当前 release tooling 覆盖的包(`tools/release/lib/packages.mjs`)已升到目标版本且一致;当前基础集合为 `packages/core` / `packages/runtime` / `packages/commands` / `packages/cli`,`knowledge-studio-cli` 发布会额外包含 `packages/kscli`
2. 在 GitHub 触发 Publish workflow,package 选目标包集合,mode 选 `stable`
3. 需要 production environment 审批人批准
4. CI 自动:自检 → **npm 发到 latest** → **推送 git tag `v<ver>`** → **Bun 编二进制并创建/更新 GitHub Release**(每平台 `.zip`,darwin/linux 额外 `.tar.gz`)→(bailian-cli)维护 CDN **`manifest.json`**(unix 资产含 `tar` / `tarSha256`,`file` 仍为 zip)→ 完成
4. CI 自动:自检 → **推送 git tag `v<ver>`** → **Bun 编二进制并创建/更新 GitHub Release**(每平台 `.zip`,darwin/linux 额外 `.tar.gz`)→(bailian-cli)维护 CDN **`manifest.json`**(unix 资产含 `tar` / `tarSha256`,`file` 仍为 zip)→ **npm 发到 latest** → 完成
5. 如果所选发布集合的当前版本已全部存在于 npm,stable 发布会失败并提示先升级版本号;如果只有部分包已发布,CI 会继续补发缺失包
6. 对应脚本:`tools/release/publish-stable.mjs`

Expand Down Expand Up @@ -162,4 +163,5 @@ node tools/release/publish-channel.mjs --channel test --knowledge --dry-run
| stable 发布前没有升级版本号 | 所选发布集合的版本已全部存在于 npm,CI 明确报错并要求先升级版本号 |
| channel job 缺少 `contents: write` | `gh release create` 失败 |
| darwin 二进制编完后没有 ad-hoc 重签 | Apple Silicon / macOS 27 对失效的 linker 签名直接 SIGKILL(`Killed: 9`) |
| npm 先于二进制 / OSS 成功 | latest 已发出,CDN 上没有对应 zip/tar.gz;OSS 网络失败时无法回滚 npm |
| stable 未先推 tag 就建 Release | `--verify-tag` 失败 |
26 changes: 13 additions & 13 deletions tools/release/publish-channel.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -80,19 +80,8 @@ try {
published.set(pkg.key, exists);
log(`${pkg.name}@${betaVersion}: ${exists ? "already published" : "to publish"}`);
}
if (packages.every((pkg) => published.get(pkg.key))) {
log("\nall packages already published; nothing to do for npm.");
} else {
// 1) npm (dependency order: core → runtime → commands → cli [→ kscli])
for (const pkg of packages) {
if (published.get(pkg.key)) continue;
step(`publish ${pkg.name}@${betaVersion} (tag=${channel}, provenance)`);
pnpmPublish(pkg, { tag: channel, provenance: true, dryRun });
}
}

// 2) binary GitHub Release — must run before finally restores package.json versions.
// Channel binary always refreshes OSS sync-release.json (npm tag is independent).
// 1) binary GitHub Release before npm, and before finally restores package.json.
// OSS sync-release.json can fail on a network blip; npm must not land first.
if (skipBinary) {
const reason = knowledge
? "[knowledge] skipping binary (npm-only; does not touch sync-release.json)"
Expand All @@ -105,6 +94,17 @@ try {
await releaseBinaryArtifacts({ mode: "channel", channel, dryRun });
}

// 2) npm (dependency order: core → runtime → commands → cli [→ kscli])
if (packages.every((pkg) => published.get(pkg.key))) {
log("\nall packages already published; nothing to do for npm.");
} else {
for (const pkg of packages) {
if (published.get(pkg.key)) continue;
step(`publish ${pkg.name}@${betaVersion} (tag=${channel}, provenance)`);
pnpmPublish(pkg, { tag: channel, provenance: true, dryRun });
}
}

const parts = ["npm"];
if (!skipBinary) parts.push("binary/sync-release");
log(`\nchannel release complete: ${channel}@${betaVersion} (${parts.join(" + ")})`);
Expand Down
19 changes: 10 additions & 9 deletions tools/release/publish-stable.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,7 @@ try {
);
}

// 1) npm (dependency order: core → runtime → commands → cli [→ kscli])
for (const pkg of packages) {
if (published.get(pkg.key)) continue;
step(`publish ${pkg.name}@${version} (tag=latest, provenance)`);
pnpmPublish(pkg, { tag: "latest", provenance: true, dryRun });
}

// 2) git tag — must be on origin before the GitHub Release step (--verify-tag)
// 1) git tag — must be on origin before the GitHub Release step (--verify-tag)
const tag = `v${version}`;
if (dryRun) {
log("\n[dry-run] skipping git tag");
Expand All @@ -81,14 +74,22 @@ try {
pushTag(tag);
}

// 3) binary GitHub Release (same version; orchestrated here, not a separate release entry)
// 2) binary GitHub Release + OSS before npm. The OSS upload can fail on a
// network blip; publishing npm first would leave latest without binaries.
if (skipBinary) {
log("\n[skip-binary] skipping binary GitHub Release");
} else {
step(`publish binary GitHub Release (mode=stable, version=${version})`);
await releaseBinaryArtifacts({ mode: "stable", dryRun });
}

// 3) npm (dependency order: core → runtime → commands → cli [→ kscli])
for (const pkg of packages) {
if (published.get(pkg.key)) continue;
step(`publish ${pkg.name}@${version} (tag=latest, provenance)`);
pnpmPublish(pkg, { tag: "latest", provenance: true, dryRun });
}

const parts = ["npm"];
if (!skipBinary) parts.push("binary");
log(`\nstable release complete (${parts.join(" + ")}).`);
Expand Down
Loading