From 40940c0ecb63accf1254782e87e97c6e933956ca Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 23 Sep 2026 03:12:54 +0000 Subject: [PATCH] Add release-tag workflow for tagging from CI Environments that cannot push tags directly can dispatch this workflow to tag a master commit (after checking the CMake version and that the tag is new) and start package.yml on the tag ref. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GWrEYUASNh3BnMktJQ7F9J --- .github/workflows/release-tag.yml | 79 +++++++++++++++++++++++++++++++ CLAUDE.md | 2 + 2 files changed, 81 insertions(+) create mode 100644 .github/workflows/release-tag.yml diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml new file mode 100644 index 000000000..35bf4d80c --- /dev/null +++ b/.github/workflows/release-tag.yml @@ -0,0 +1,79 @@ +name: release-tag + +# Creates the v tag on a master commit and starts package.yml for it. +# A tag pushed with the workflow token does not trigger push workflows, so the +# package run is dispatched explicitly on the tag ref; package.yml keys its +# release path off github.ref, so the result matches a manually pushed tag. +on: + workflow_dispatch: + inputs: + version: + description: Release version without the leading v; must match CMakeLists.txt + required: true + type: string + sha: + description: Master commit to tag (defaults to the current master head) + required: false + type: string + +permissions: + contents: write + actions: write + +concurrency: + group: release-tag + cancel-in-progress: false + +jobs: + tag: + name: tag and package + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout master + uses: actions/checkout@v4 + with: + ref: master + fetch-depth: 0 + + - name: Create and push the release tag + env: + VERSION: ${{ inputs.version }} + TARGET_SHA: ${{ inputs.sha }} + shell: bash + run: | + set -euo pipefail + if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then + echo "::error::Invalid version '$VERSION'" + exit 1 + fi + tag="v$VERSION" + if ! target="$(git rev-parse --verify --quiet "${TARGET_SHA:-HEAD}^{commit}")"; then + echo "::error::Unknown commit '${TARGET_SHA}'" + exit 1 + fi + if ! git merge-base --is-ancestor "$target" HEAD; then + echo "::error::$target is not on master" + exit 1 + fi + declared_version="$(git show "$target:CMakeLists.txt" | awk '$1 == "project(acecode" && $2 == "VERSION" { print $3; exit }')" + if [ "$declared_version" != "$VERSION" ]; then + echo "::error::CMakeLists.txt at $target declares '$declared_version', not $VERSION" + exit 1 + fi + if git ls-remote --exit-code --tags origin "refs/tags/$tag" >/dev/null; then + echo "::error::Tag $tag already exists" + exit 1 + fi + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git tag -a "$tag" "$target" -m "ACECode $tag" + git push origin "refs/tags/$tag" + echo "Tagged $target as $tag" + + - name: Start package workflow for the tag + env: + GH_TOKEN: ${{ github.token }} + VERSION: ${{ inputs.version }} + shell: bash + run: gh workflow run package.yml --repo "$GITHUB_REPOSITORY" --ref "v$VERSION" diff --git a/CLAUDE.md b/CLAUDE.md index 1c4c55fc3..a5b5ca738 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -794,6 +794,8 @@ Crow 的 `ResponseCorsMiddleware` 在响应完成时复用 `add_loopback_cors_he `.github/workflows/package.yml` builds Linux x64/arm64, Windows x64/arm64, macOS x64/arm64. Releases auto-cut on `v*` tags. +`.github/workflows/release-tag.yml`(手动触发,输入 `version` + 可选 `sha`)用于无法直接推 tag 的环境:校验目标提交在 master 上且 `CMakeLists.txt` 版本一致、tag 不存在,再用 workflow token 打注解 tag,并显式 `gh workflow run package.yml --ref v` —— workflow token 推的 tag 不会触发 push 事件,而 package.yml 只看 `github.ref`,效果与手推 tag 相同。发布门槛不变:仍要等该提交在 master 上的 `test.yml` push 检查通过。 + **npm 发布已暂停**:`publish-npm` job 使用固定 `if: ${{ false }}`,`v*` tag 和手动 workflow 均不会发布 npm;保留的 `npm_version` 输入目前不生效。全平台包、GitHub Release、macOS PKG 和更新包发布不受影响。 **npm 保留实现**(当前不会运行):CLI 主包为 `@aceagent/acecode`,桌面主包为 `@aceagent/desktop`,另有 6 个平台二进制包 `@aceagent/-`(esbuild 模式:主包只有 JS 垫片,`optionalDependencies` 按 os/cpu 字段精确钉同版本平台包)。平台包同时装 `acecode` / `acecode-desktop`(macOS 为 `ACECode.app`)——Desktop 按自身真实路径所在目录定位 daemon(`locate_daemon_exe`),不能拆包,垫片必须直接 spawn 包内原始文件不能拷走。组装脚本 [scripts/npm/prepare-npm-packages.mjs](scripts/npm/prepare-npm-packages.mjs),主包模板在 [npm/cli/](npm/cli) 与 [npm/desktop/](npm/desktop);改名/换 scope 需同步脚本、模板与两个 bin 垫片。job 恢复运行后的行为:`NPM_TOKEN` secret 缺失 → 失败;已发布版本 → 幂等跳过(重跑安全);预发布版本(名含 `-`)→ dist-tag `next`,否则 `latest`。手动 `npm_version` 必须与 `CMakeLists.txt` 项目版本一致,且不会重复创建 GitHub Release。linux-old(glibc ≤ 2.28)产物刻意不上 npm(npm 无法按 glibc 选包),老发行版用户走 GitHub Releases。裸名 `acecode` 已被 registry 以与活跃包 `ace-code` 过于相似为由拒绝,不能改回裸名。