diff --git a/.github/workflows/build-dist.yml b/.github/workflows/build-dist.yml index 841f7e55..3a21458b 100644 --- a/.github/workflows/build-dist.yml +++ b/.github/workflows/build-dist.yml @@ -9,6 +9,11 @@ on: push: tags: ['v*'] workflow_dispatch: + inputs: + tag: + description: 'Release tag to build + attach (e.g. v5.6.0);由 release.yml 推 tag 后触发' + required: true + type: string permissions: contents: write @@ -22,7 +27,7 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Checkout xiaobei - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Read pinned openclaw version id: pin @@ -32,10 +37,14 @@ jobs: echo "version=$OPENCLAW_VERSION" >> "$GITHUB_OUTPUT" - name: Setup Node + pnpm (build env) - uses: actions/setup-node@v4 + # v6:package-manager-cache 限 npm-only,避免 pnpm 装好前自动开缓存报 + # "Unable to locate executable file: pnpm"(setup-node#1351) + uses: actions/setup-node@v6 with: node-version: '24.15.0' - - uses: pnpm/action-setup@v4 + - uses: pnpm/action-setup@v6 + with: + version: 10.30.2 - name: Clone openclaw at pinned commit run: | @@ -121,13 +130,18 @@ jobs: echo "stage_dir=$STAGE" >> "$GITHUB_OUTPUT" - name: Build 4 platform tarballs (engine + portable Node) + id: buildtars run: | set -euo pipefail STAGE="${{ steps.stage.outputs.stage_dir }}" XIAOBEI_VER="$(tr -d '[:space:]' < "$GITHUB_WORKSPACE/version")" - # asset 名优先用 git tag(release source of truth),非 tag 触发回退 version 文件 + # asset tag 优先级:workflow_dispatch inputs.tag > git tag(push 触发)> version 文件 + INPUT_TAG="${{ inputs.tag }}" REF_NAME="${GITHUB_REF##*/}" - if [[ "$REF_NAME" == v* ]]; then ASSET_TAG="$REF_NAME"; else ASSET_TAG="$XIAOBEI_VER"; fi + if [[ -n "$INPUT_TAG" ]]; then ASSET_TAG="$INPUT_TAG" + elif [[ "$REF_NAME" == v* ]]; then ASSET_TAG="$REF_NAME" + else ASSET_TAG="$XIAOBEI_VER"; fi + echo "ASSET_TAG=$ASSET_TAG" mkdir -p "$RUNNER_TEMP/out" # 平台 → (node_url, subdir) @@ -188,8 +202,36 @@ jobs: # 给后续步骤用 echo "out_dir=$RUNNER_TEMP/out" >> "$GITHUB_OUTPUT" + echo "asset_tag=$ASSET_TAG" >> "$GITHUB_OUTPUT" ls -lh "$RUNNER_TEMP/out/" + - name: Smoke test linux tarball (extract + install --skip-browser + openclaw --version) + run: | + set -euo pipefail + ASSET_TAG="${{ steps.buildtars.outputs.asset_tag }}" + if [[ "$ASSET_TAG" != v* ]]; then + echo "无 release tag(asset_tag=$ASSET_TAG),跳过冒烟自检" + exit 0 + fi + TB="$RUNNER_TEMP/out/xiaobei-$ASSET_TAG-linux-x64.tar.zst" + [[ -f "$TB" ]] || { echo "❌ tarball 不存在:$TB"; exit 1; } + SMOKE="$RUNNER_TEMP/smoke" + rm -rf "$SMOKE" + mkdir -p "$SMOKE/extract" "$SMOKE/program" "$SMOKE/runtime" + # 解压一份拿到 scripts/install.sh(install.sh 会再按 XIAOBEI_TARBALL 解压到 program) + tar --zstd -xf "$TB" -C "$SMOKE/extract" + [[ -f "$SMOKE/extract/scripts/install.sh" ]] || { echo "❌ tarball 缺 scripts/install.sh"; exit 1; } + export XIAOBEI_HOME="$SMOKE/program" + export OPENCLAW_HOME="$SMOKE/runtime" + export XIAOBEI_TARBALL="$TB" + export XIAOBEI_TAG="$ASSET_TAG" + export XIAOBEI_SOURCE=github + export AWK_API_KEY="smoke-test-key" + bash "$SMOKE/extract/scripts/install.sh" \ + --no-prompt --skip-bind --skip-browser --root "$XIAOBEI_HOME" + "$XIAOBEI_HOME/bin/openclaw" --version + echo "✅ 冒烟自检通过:tarball 可解压 + 依赖可装 + 引擎可起" + - name: Upload artifacts uses: actions/upload-artifact@v4 with: @@ -200,16 +242,15 @@ jobs: retention-days: 14 - name: Attach to release (on real tag, skip disttest) - if: startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, 'disttest') - continue-on-error: true + if: ${{ startsWith(steps.buildtars.outputs.asset_tag, 'v') && !contains(steps.buildtars.outputs.asset_tag, 'disttest') }} env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - TAG="${GITHUB_REF##*/}" + TAG="${{ steps.buildtars.outputs.asset_tag }}" if ! gh release view "$TAG" >/dev/null 2>&1; then gh release create "$TAG" --title "$TAG" --generate-notes fi for f in "$RUNNER_TEMP"/out/*.tar.zst "$RUNNER_TEMP"/out/*.tar.gz; do [ -e "$f" ] || continue - gh release upload "$TAG" "$f" --clobber || true + gh release upload "$TAG" "$f" --clobber done diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 707da782..2d4e7a51 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,15 +20,21 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup Node.js - uses: actions/setup-node@v4 + # v6:把 package-manager-cache 限制为 npm-only,避免检测到 packageManager: pnpm@ + # 时在 pnpm 装好前自动开 pnpm 缓存而抛 "Unable to locate executable file: pnpm" + #(setup-node#1351)。v5 会自动开 pnpm 缓存,必须配 pnpm/action-setup 才不报错。 + uses: actions/setup-node@v6 with: node-version: '24' - name: Install pnpm - uses: pnpm/action-setup@v4 + # 显式 version 规避 action-setup#227(v6 早期不读 packageManager 版本) + uses: pnpm/action-setup@v6 + with: + version: 10.30.2 - name: Read pinned openclaw version id: pin diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index abfe30e3..f0ed53fb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,6 +18,7 @@ on: permissions: contents: write + actions: write # 防止多个 PR 同时 merge 时并发触发重复 release concurrency: @@ -26,15 +27,15 @@ concurrency: jobs: release: - # wiseflow 走 git clone 路线(见 scripts/install.sh),无 release artifact 通道。 - # 本 job 仅做版本 bump + tag push,让用户 update.sh 可拉特定 tag 而非总跟 master。 - # 后续若重启 tarball 通道,在此 job 内追加 build / upload asset 步骤即可。 + # PR merge → bump version + push v* tag → 触发 build-dist.yml 出 4 平台 tarball + attach release。 + # tag push 用 GITHUB_TOKEN 不会触发下游 on:push workflow(递归保护),故这里主动 + # gh workflow run build-dist.yml(workflow_dispatch 是递归保护例外,GITHUB_TOKEN 可触发)。 if: github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 token: ${{ secrets.RELEASE_TOKEN || secrets.GITHUB_TOKEN }} @@ -98,3 +99,11 @@ jobs: git commit -m "chore: bump version to ${{ steps.version.outputs.new }} [skip ci]" git tag "${{ steps.version.outputs.new }}" git push origin master --tags + + - name: Trigger build-dist tarball workflow + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + TAG="${{ steps.version.outputs.new }}" + echo "Triggering build-dist.yml with tag=$TAG" + gh workflow run build-dist.yml -f tag="$TAG" diff --git a/scripts/README.md b/scripts/README.md index 325cc41c..77e99e84 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -37,6 +37,7 @@ irm https://atomgit.com/wiseflow/xiaobei/raw/branch/master/scripts/install.ps1 | | `--mirror ` / `-Mirror ` | 自定义镜像站根(覆盖默认 atomgit) | | `--force` / `-Force` | 强覆盖已有运行数据(`~/.openclaw`);默认已装机器重跑只更新 program,不碰运行数据 | | `--skip-bind` / `-SkipBind` | 跳过末尾微信扫码绑定(CI / 自动化) | +| `--skip-browser` / `-SkipBrowser` | 跳过 camoufox-cli 浏览器二进制安装(冒烟 / CI,省 ~557MB Firefox 下载) | | `--no-prompt` / `-NoPrompt` | 关闭交互提示(CI / 自动化,隐含 `--skip-bind`) | | `--root ` / `-Root ` | 程序目录覆盖(默认 `~/xiaobei`) | diff --git a/scripts/install.ps1 b/scripts/install.ps1 index 48f51cb3..d8c60a89 100644 --- a/scripts/install.ps1 +++ b/scripts/install.ps1 @@ -29,6 +29,7 @@ param( [switch]$GitHub, # 切回 GitHub release(不走默认 atomgit) [switch]$Force, # 强覆盖已有运行数据(~\.openclaw) [switch]$SkipBind, # 跳过末尾微信扫码绑定 + [switch]$SkipBrowser, # 跳过 camoufox-cli 浏览器二进制(冒烟/CI) [switch]$NoPrompt ) @@ -204,6 +205,10 @@ function Run-SetupCrew { # ─── 8. camoufox-cli ─────────────────────────────────────────── function Install-CamoufoxCli { + if ($SkipBrowser) { + Write-Host " [i] 跳过 camoufox-cli 浏览器二进制(-SkipBrowser);后续手动:camoufox-cli install" -ForegroundColor Yellow + return + } Write-Stage "Installing camoufox-cli browser" $fork = Join-Path $Root "camoufox-cli" if (-not (Test-Path $fork)) { Write-Warn "camoufox-cli fork 不在 tarball 内:$fork;跳过"; return } diff --git a/scripts/install.sh b/scripts/install.sh index fac43e1c..3d39a890 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -1007,6 +1007,10 @@ checkout_openclaw_at_pin() { # camoufox-cli(Firefox 反指纹浏览器) # ═══════════════════════════════════════════════════════════════════ install_camoufox_cli() { + if [[ "$SKIP_BROWSER" == "true" ]]; then + ui_info "跳过 camoufox-cli 浏览器二进制(--skip-browser);后续手动:camoufox-cli install" + return 0 + fi local node="$WISEFLOW_ROOT/$PORTABLE_NODE" local npm_bin; npm_bin="$(dirname "$node")/npm" local fork_dir="$WISEFLOW_ROOT/camoufox-cli" @@ -1111,6 +1115,7 @@ NO_PROMPT=0 USE_LOCAL=false FORCE_RUNTIME=false SKIP_WEIXIN_BIND=false +SKIP_BROWSER=false TAGLINE="$DEFAULT_TAGLINE" parse_args() { @@ -1155,6 +1160,11 @@ parse_args() { SKIP_WEIXIN_BIND=true shift ;; + --skip-browser) + # 跳过 camoufox-cli 装浏览器二进制(冒烟/CI,省 ~557MB Firefox 下载) + SKIP_BROWSER=true + shift + ;; --root) if [[ $# -lt 2 || "${2:-}" == --* ]]; then ui_error "Missing value for $1" @@ -1177,6 +1187,7 @@ Options: --mirror Custom mirror root (overrides default atomgit) --force Overwrite existing runtime data (~/.openclaw); default preserves it on re-install --skip-bind Skip the WeChat QR binding at the end (CI/automation) + --skip-browser Skip camoufox-cli browser binary install (smoke/CI, saves ~557MB Firefox) --verbose Print debug output --no-prompt Disable prompts (CI/automation) --help, -h Show this help