diff --git a/docs/proposals/binary-distribution.md b/docs/proposals/binary-distribution.md deleted file mode 100644 index 90861ed..0000000 --- a/docs/proposals/binary-distribution.md +++ /dev/null @@ -1,171 +0,0 @@ -# 技术方案:GitHub Release 发布 + 外部 FC 同步 OSS 安装 - -> 状态:**已定架构**(本仓库不直传 OSS;安装脚本外置;**不含 Homebrew**)。 -> 范围:仅 `bailian-cli`(`bl`);不含 `kscli` 二进制。 -> 操作清单:[docs/agents/binary-distribution.md](../agents/binary-distribution.md) -> 发版编排:[docs/agents/publish.md](../agents/publish.md) - ---- - -## 1. 目标架构 - -```text -Publish workflow(本仓库) - ├─ npm - └─ GitHub Release(source of truth) - ↓ - 调用外部 FC:拉取最新 Release → 同步 OSS - ↓ - 别处维护的 install.sh / install.ps1 → 只拉 OSS -``` - -| 环节 | 谁负责 | 本仓库是否实现 | -| ------------------------- | ------------ | ------------------------------- | -| npm publish | 本仓库 CI | ✅ | -| Bun 编译 + GitHub Release | 本仓库 CI | ✅ | -| Release → OSS 同步 | **外部 FC** | ❌(仅可选 webhook 触发) | -| 生产安装脚本 | **别处维护** | ❌(`packaging/` 仅作契约参考) | -| 用户 curl / irm | OSS 上的脚本 | ❌ | - -本仓库**不存放、不上传 OSS AccessKey**;开源侧只用 `GITHUB_TOKEN`。 - ---- - -## 2. 本仓库发版(Publish) - -入口:`.github/workflows/publish.yml` → `publish-stable.mjs` / `publish-channel.mjs`。 - -```text -stable: - check → npm latest → git tag v → gh release(正式) - assets: bl-*, SHA256SUMS, latest.json - (不再把 install.sh/ps1 挂到 Release;生产脚本外置) - -channel: - bump beta → npm @channel → gh prerelease v - + 滚动 prerelease tag channel-(仅 .json) -``` - -可选:发版成功后 `POST` `BAILIAN_OSS_SYNC_WEBHOOK`,通知 FC 开始同步(Secret 配置,无则跳过)。 - -`--skip-binary`:只发 npm。 - -### 构建矩阵 - -| Bun target | 产物 | -| ------------------ | ----------------- | -| `bun-darwin-arm64` | `darwin-arm64` | -| `bun-darwin-x64` | `darwin-x64` | -| `bun-linux-x64` | `linux-x64` | -| `bun-windows-x64` | `windows-x64.exe` | - -不构建 `linux-arm64` / `windows-arm64`。 - ---- - -## 3. GitHub Release 约定(source of truth) - -基址:`https://github.com/modelstudioai/cli/releases` - -| 模式 | Tag | 资产 | -| -------------- | ---------------------------------------------- | --------------------------------------- | -| stable | `v`(先 push tag,再 `--verify-tag`) | 矩阵二进制、`SHA256SUMS`、`latest.json` | -| channel 版本化 | `v0.0.0-beta--`(prerelease) | 二进制、`SHA256SUMS` | -| channel 滚动 | `channel-`(prerelease,clobber) | `.json` | - -Manifest 内 `url` 指向 GitHub download(给 FC / 镜像方解析用)。FC 同步到 OSS 时应**改写**为 OSS URL,或安装脚本忽略 `url`、按固定 OSS 路径拼接。 - ---- - -## 4. 外部 FC(本仓库不实现) - -建议契约: - -1. 触发:Publish webhook,或监听 `release` 事件 / 定时拉取 Latest -2. 读取 GitHub Latest(stable)或约定 channel tag -3. 下载资产 → 上传 OSS,建议布局: - -```text -https://bailian-cli.oss-cn-hangzhou.aliyuncs.com/bailian-cli/ - channels/latest.json # 改写 url 后的正式版 manifest - channels/.json # 可选测试渠道 - releases// - bl---[.exe] - SHA256SUMS - install.sh # 由脚本维护方上传,非本仓库 CI - install.ps1 -``` - -4. **完整校验后再对外**:SHA256 对齐、矩阵文件齐全,避免「Release 已发、OSS 半同步」窗口误导用户 -5. 失败告警(钉钉/飞书/SLS),因用户安装不经过本仓库 CI - ---- - -## 5. 安装脚本(别处维护) - -生产入口(示例,以实际 OSS 域名为准): - -```bash -curl -fsSL https://bailian-cli.oss-cn-hangzhou.aliyuncs.com/bailian-cli/install.sh | bash -# Windows: -irm https://bailian-cli.oss-cn-hangzhou.aliyuncs.com/bailian-cli/install.ps1 | iex -``` - -脚本只依赖 OSS;不要求用户访问 GitHub。 - -本仓 `packaging/install.sh` / `install.ps1`:**契约参考**(路径、校验、`install-method=binary`),不作为生产分发物挂 Release。 - -### 与本仓的契约(脚本方必须遵守) - -- 资产名:`bl---[.exe]` -- 校验:`SHA256SUMS` -- 渠道:默认 `latest`;可选 `BAILIAN_CHANNEL` -- 写入:`~/.bailian/install-method` = `binary` -- 不支持:linux-arm64 / windows-arm64 → 提示 `npm i -g bailian-cli` - ---- - -## 6. 运行时(本仓库) - -- `BAILIAN_COMPILED=1`、install-method、`bl update` 分流仍在本仓 -- 二进制更新默认读 **OSS** manifest(`BAILIAN_CLI_CDN` 可覆盖);与用户安装源一致 -- GitHub Release 仍是发版真相源;更新链路走 OSS 镜像 - ---- - -## 7. 职责边界(验收标准) - -| 验收项 | 通过条件 | -| ----------------- | ----------------------------------------------------- | -| 本仓库 Publish 绿 | npm 可装 + GitHub Release 资产齐全 | -| 国内可一键安装 | FC 已同步 + 外置脚本可 curl(**不在本仓 CI 门禁内**) | -| 无 AK 进 git | OSS 密钥只在 FC / 脚本发布流水线 | - ---- - -## 8. 风险 - -- Release 成功 ≠ 用户能装(依赖 FC)→ 必须有同步监控 -- 脚本外置 → 命名/矩阵变更要同步通知脚本方 -- `latest.json` 双份(GH / OSS)→ FC 负责改写与一致性 -- channel 是否进 OSS:由 FC 与脚本方另定;本仓照常发 prerelease - ---- - -## 9. 本仓库代码落点 - -| 路径 | 职责 | -| --------------------------------------------- | ------------------------------------- | -| `publish-stable.mjs` / `publish-channel.mjs` | npm + Release + 可选 webhook | -| `lib/binary-build.mjs` / `binary-compile.mjs` | 编译与 manifest | -| `lib/binary-release.mjs` | `gh release`(不含生产 install 脚本) | -| `packaging/*` | 安装契约参考 | -| `.github/workflows/publish.yml` | CI | - -调试: - -```sh -node tools/release/lib/binary-build.mjs --mode stable --host -node tools/release/lib/binary-release.mjs --mode stable --skip-build --dry-run -node tools/release/publish-stable.mjs --dry-run -``` diff --git a/packaging/install.ps1 b/packaging/install.ps1 deleted file mode 100644 index 07bea41..0000000 --- a/packaging/install.ps1 +++ /dev/null @@ -1,78 +0,0 @@ -# REFERENCE install script for the OSS layout (production scripts are maintained elsewhere). -# Expected production entry: -# irm https://bailian-cli.oss-cn-hangzhou.aliyuncs.com/bailian-cli/install.ps1 | iex -param() - -$ErrorActionPreference = "Stop" - -$CdnBase = if ($env:BAILIAN_CLI_CDN) { $env:BAILIAN_CLI_CDN.TrimEnd("/") } else { "https://bailian-cli.oss-cn-hangzhou.aliyuncs.com/bailian-cli" } -$Channel = if ($env:BAILIAN_CHANNEL) { $env:BAILIAN_CHANNEL } else { "latest" } -$Version = $env:BAILIAN_VERSION -$InstallRoot = if ($env:BAILIAN_SHARE_DIR) { $env:BAILIAN_SHARE_DIR } else { Join-Path $env:LOCALAPPDATA "bailian-cli" } -$ConfigDir = if ($env:BAILIAN_CONFIG_DIR) { $env:BAILIAN_CONFIG_DIR } else { Join-Path $env:USERPROFILE ".bailian" } - -function Write-Log([string]$Message) { - [Console]::Error.WriteLine($Message) -} - -if ([string]::IsNullOrWhiteSpace($Version)) { - $manifestUrl = "$CdnBase/channels/$Channel.json" - Write-Log "Fetching $manifestUrl" - $manifest = Invoke-RestMethod -Uri $manifestUrl - $Version = $manifest.version - if ([string]::IsNullOrWhiteSpace($Version)) { - throw "Could not parse version from $Channel channel manifest" - } -} - -$Arch = if ($env:PROCESSOR_ARCHITECTURE -eq "ARM64") { "arm64" } else { "x64" } -if ($Arch -eq "arm64") { - throw "windows arm64 is not supported for binary install; use: npm install -g bailian-cli" -} - -$Asset = "bl-$Version-windows-$Arch.exe" -$Url = "$CdnBase/releases/$Version/$Asset" -$SumsUrl = "$CdnBase/releases/$Version/SHA256SUMS" - -$TempDir = Join-Path ([System.IO.Path]::GetTempPath()) ("bailian-cli-install-" + [guid]::NewGuid().ToString("N")) -New-Item -ItemType Directory -Path $TempDir | Out-Null -try { - $AssetPath = Join-Path $TempDir $Asset - $SumsPath = Join-Path $TempDir "SHA256SUMS" - Write-Log "Downloading $Asset…" - Invoke-WebRequest -Uri $Url -OutFile $AssetPath - Invoke-WebRequest -Uri $SumsUrl -OutFile $SumsPath - - $Expected = $null - Get-Content $SumsPath | ForEach-Object { - if ($_ -match "^([a-fA-F0-9]+)\s+$([regex]::Escape($Asset))\s*$") { - $Expected = $Matches[1].ToLowerInvariant() - } - } - if (-not $Expected) { throw "Checksum for $Asset not found in SHA256SUMS" } - $Actual = (Get-FileHash -Algorithm SHA256 -Path $AssetPath).Hash.ToLowerInvariant() - if ($Expected -ne $Actual) { throw "Checksum mismatch for $Asset" } - - $VersionDir = Join-Path $InstallRoot "versions\$Version" - New-Item -ItemType Directory -Force -Path $VersionDir | Out-Null - New-Item -ItemType Directory -Force -Path $ConfigDir | Out-Null - $Target = Join-Path $VersionDir "bl.exe" - Copy-Item -Force $AssetPath $Target - $ShimDir = Join-Path $InstallRoot "bin" - New-Item -ItemType Directory -Force -Path $ShimDir | Out-Null - Copy-Item -Force $Target (Join-Path $ShimDir "bl.exe") - Copy-Item -Force $Target (Join-Path $ShimDir "bailian.exe") - Set-Content -Path (Join-Path $ConfigDir "install-method") -Value "binary" -NoNewline - - $UserPath = [Environment]::GetEnvironmentVariable("Path", "User") - if (-not ($UserPath -split ";" | Where-Object { $_ -eq $ShimDir })) { - [Environment]::SetEnvironmentVariable("Path", "$ShimDir;$UserPath", "User") - Write-Log "Added $ShimDir to your user PATH. Open a new terminal to use bl." - } - - Write-Log "Installed: $Target (bailian-cli $Version)" - Write-Log "Done. Run: bl --help" -} -finally { - Remove-Item -Recurse -Force $TempDir -ErrorAction SilentlyContinue -} diff --git a/packaging/install.sh b/packaging/install.sh deleted file mode 100644 index f3952b9..0000000 --- a/packaging/install.sh +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env bash -# REFERENCE install script for the OSS layout (production scripts are maintained elsewhere). -# Production users should curl the copy hosted on OSS after FC sync, not this file from git. -# -# Expected production entry: -# curl -fsSL https://bailian-cli.oss-cn-hangzhou.aliyuncs.com/bailian-cli/install.sh | bash -# BAILIAN_VERSION=1.10.1 bash install.sh -# BAILIAN_CHANNEL=latest bash install.sh -set -euo pipefail - -CDN_BASE="${BAILIAN_CLI_CDN:-https://bailian-cli.oss-cn-hangzhou.aliyuncs.com/bailian-cli}" -CDN_BASE="${CDN_BASE%/}" -CHANNEL="${BAILIAN_CHANNEL:-latest}" -VERSION="${BAILIAN_VERSION:-}" -BIN_DIR="${BAILIAN_BIN_DIR:-${HOME}/.local/bin}" -SHARE_DIR="${BAILIAN_SHARE_DIR:-${HOME}/.local/share/bailian-cli}" -CONFIG_DIR="${BAILIAN_CONFIG_DIR:-${HOME}/.bailian}" - -log() { printf '%s\n' "$*" >&2; } -die() { log "error: $*"; exit 1; } - -need_cmd() { - command -v "$1" >/dev/null 2>&1 || die "required command not found: $1" -} - -detect_os_arch() { - local uname_s uname_m - uname_s="$(uname -s)" - uname_m="$(uname -m)" - - case "${uname_s}" in - Darwin) OS="darwin" ;; - Linux) OS="linux" ;; - *) die "unsupported OS: ${uname_s}" ;; - esac - - case "${uname_m}" in - arm64|aarch64) ARCH="arm64" ;; - x86_64|amd64) ARCH="x64" ;; - *) die "unsupported architecture: ${uname_m}" ;; - esac - - if [[ "${OS}" == "darwin" ]] && [[ "$(sysctl -n sysctl.proc_translated 2>/dev/null || true)" == "1" ]]; then - ARCH="arm64" - fi - - if [[ "${OS}" == "linux" && "${ARCH}" == "arm64" ]]; then - die "linux arm64 is not supported for binary install; use: npm install -g bailian-cli" - fi -} - -resolve_version() { - if [[ -n "${VERSION}" ]]; then - return - fi - need_cmd curl - local manifest - manifest="$(mktemp)" - curl -fsSL "${CDN_BASE}/channels/${CHANNEL}.json" -o "${manifest}" \ - || die "failed to download channel manifest: ${CDN_BASE}/channels/${CHANNEL}.json" - VERSION="$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "${manifest}" | head -n1)" - rm -f "${manifest}" - [[ -n "${VERSION}" ]] || die "could not parse version from ${CHANNEL} channel manifest" -} - -download_and_verify() { - local asset="bl-${VERSION}-${OS}-${ARCH}" - local url="${CDN_BASE}/releases/${VERSION}/${asset}" - local sums_url="${CDN_BASE}/releases/${VERSION}/SHA256SUMS" - local tmp_dir version_dir - tmp_dir="$(mktemp -d)" - # shellcheck disable=SC2064 - trap "rm -rf '${tmp_dir}'" EXIT - - log "Downloading ${asset}…" - curl -fsSL "${url}" -o "${tmp_dir}/${asset}" || die "download failed: ${url}" - curl -fsSL "${sums_url}" -o "${tmp_dir}/SHA256SUMS" || die "download failed: ${sums_url}" - - need_cmd shasum - local expected actual - expected="$(awk -v file="${asset}" '$2 == file { print $1; exit }' "${tmp_dir}/SHA256SUMS")" - [[ -n "${expected}" ]] || die "checksum for ${asset} not found in SHA256SUMS" - actual="$(shasum -a 256 "${tmp_dir}/${asset}" | awk '{ print $1 }')" - [[ "${expected}" == "${actual}" ]] || die "checksum mismatch for ${asset}" - - version_dir="${SHARE_DIR}/versions/${VERSION}" - mkdir -p "${version_dir}" "${BIN_DIR}" "${CONFIG_DIR}" - install -m 755 "${tmp_dir}/${asset}" "${version_dir}/bl" - ln -sfn "${version_dir}/bl" "${BIN_DIR}/bl" - ln -sfn "${version_dir}/bl" "${BIN_DIR}/bailian" - printf 'binary\n' > "${CONFIG_DIR}/install-method" - chmod 600 "${CONFIG_DIR}/install-method" 2>/dev/null || true -} - -warn_path() { - case ":${PATH}:" in - *":${BIN_DIR}:"*) ;; - *) - log "" - log "Add ${BIN_DIR} to your PATH, then open a new terminal:" - log " export PATH=\"${BIN_DIR}:\$PATH\"" - ;; - esac -} - -warn_npm_conflict() { - if command -v npm >/dev/null 2>&1; then - local npm_bl - npm_bl="$(npm root -g 2>/dev/null)/bailian-cli" || true - if [[ -d "${npm_bl}" ]]; then - log "warning: npm global bailian-cli is also installed; PATH may prefer one over the other." - log " Consider: npm uninstall -g bailian-cli" - fi - fi -} - -main() { - need_cmd curl - need_cmd uname - detect_os_arch - resolve_version - log "Installing bailian-cli ${VERSION} (${OS}-${ARCH}) from ${CDN_BASE}" - download_and_verify - warn_npm_conflict - warn_path - log "" - log "Installed: ${BIN_DIR}/bl → bailian-cli ${VERSION}" - if command -v "${BIN_DIR}/bl" >/dev/null 2>&1 || [[ -x "${BIN_DIR}/bl" ]]; then - "${BIN_DIR}/bl" --version >&2 || true - fi - log "Done. Run: bl --help" -} - -main "$@"