@jtianling/jt-release

把项目更新到 main 上最新的代码(合并), 然后 push 到 release 分支, 触发版本发布.

J@jtianling·latest·↓ 2·updated 2026-07-21·MIT
release

jt-release

自动将 main 分支合并到 release 分支并发布.

声明: "正在使用 jt-release skill 执行发布流程."

流程

1. 前置检查

依次检查, 任一失败则报告并退出:

# 1.1 当前分支
current_branch=$(git branch --show-current)
if [ "$current_branch" != "main" ]; then
  echo "ERROR: 当前不在 main 分支, 请先切换到 main"
  exit 1
fi

# 1.2 工作区干净
if [ -n "$(git status --porcelain --ignore-submodules)" ]; then
  echo "ERROR: 工作区有未提交变更, 请先处理"
  exit 1
fi

# 1.3 release 分支存在
git fetch origin
if ! git rev-parse --verify release >/dev/null 2>&1 && ! git rev-parse --verify origin/release >/dev/null 2>&1; then
  echo "ERROR: release 分支不存在, 请先创建"
  exit 1
fi

# 1.4 远端 main 不领先于本地
local_main=$(git rev-parse main)
remote_main=$(git rev-parse origin/main)
if [ "$(git merge-base "$local_main" "$remote_main")" != "$remote_main" ]; then
  echo "ERROR: 远端 main 有新提交, 请先 pull/rebase"
  exit 1
fi

如果本地没有 release 分支但远端有, 先 checkout:

if ! git rev-parse --verify release >/dev/null 2>&1; then
  git checkout -b release origin/release
  git checkout main
fi

1.5 本地全仓 lint 门禁 (push 前提前抓 CI Lint gate 的错):

CI 的 Lint gate 跑全仓, 但 main push 不触发它 —— 多个 commit 累积的 lint 错会一直憋到 release 发布时 CI 才爆. 发布前先在本地跑一次全仓 lint, 几秒就能提前抓到, 避免推上去白等一轮 CI.

# 仅 Node/pnpm 项目 (package.json 含 check 脚本) 适用; 其它技术栈按需替换 lint 命令
if [ -f package.json ] && grep -q '"check"' package.json; then
  # 坑: 仓库内嵌套 worktree (.worktrees/ 或 worktrees/ 下) 各自的 biome.jsonc
  # 会让全仓 lint 因 nested root config 整体 bail —— 这是配置冲突, 不是真 lint 错,
  # 不能误判成 lint 失败而阻断发布. 只精确识别"嵌套在仓库内的 worktree".
  repo_root=$(git rev-parse --show-toplevel)
  nested_wt=$(git worktree list --porcelain | awk '/^worktree /{print $2}' \
    | grep -F "$repo_root/" || true)

  if [ -n "$nested_wt" ]; then
    echo "WARN: 检测到仓库内嵌套 worktree, 本地全仓 lint 可能因 nested root config 整体 bail (非真 lint 错):"
    echo "$nested_wt"
    echo "已降级为 warn, 不硬阻断. 建议清理 worktree 后重跑, 或人工确认 lint 状态后再发布."
  else
    echo "运行本地全仓 lint (pnpm check)..."
    if ! pnpm check; then
      echo "ERROR: 本地全仓 lint 失败, 请修复上述错误后再发布 (避免推上去等 CI 才发现)"
      exit 1
    fi
  fi
fi

2. 版本号检测与 bump

按优先级在项目根目录检测版本文件, 找到第一个即停止:

优先级文件读取方式
1package.jsonJSON "version" 字段
2Cargo.tomlversion = "X.Y.Z"
3pyproject.tomlversion = "X.Y.Z"

未找到版本文件: 报告 "未找到版本文件, 跳过版本号 bump", 继续合并流程.

对比版本号:

用 git show release:<version-file> 读取 release 分支上的版本号. 如果 release 分支没有该文件 (首次发布), 跳过 bump.

  • 版本号相同 → patch +1 (如 1.2.3 → 1.2.4), 修改版本文件, commit:
    git add <version-file>
    git commit -m "chore: bump version to <new-version>"
    
  • 版本号不同 → 跳过 bump, 报告当前版本号

版本号修改方式:

  • package.json: 用 Read 工具读取, 用 Edit 工具修改 "version" 字段
  • Cargo.toml: 用 Edit 工具修改 version = "X.Y.Z" 行
  • pyproject.toml: 用 Edit 工具修改 version = "X.Y.Z" 行

3. 合并 main → release

git checkout release
git merge --ff-only main

如果 ff-only 失败:

echo "ERROR: 无法 fast-forward 合并, release 分支有独立提交, 请手动处理"
git checkout main
exit 1

4. Push 并切回 main

git push origin release
git checkout main

如果步骤 2 执行了版本号 bump, 也 push main:

git push origin main

5. CI 监控

记录 push 时间, 然后轮询 CI 状态:

gh run list --branch release --limit 10 --json databaseId,name,status,conclusion,createdAt,url

监控逻辑:

  1. 过滤出 push 之后创建的 workflow run
  2. 每 30 秒轮询一次
  3. 所有 run 都 completed + success → 发布成功
  4. 任一 run completed + failure → 立即报告失败
  5. 基础超时 5 分钟, 如果上次轮询到本次轮询之间有状态变化 (如 step 完成), 重置超时计时器
  6. 超时无进展 → 报告超时

6. 最终报告

成功:

## 发布成功

- 版本: <version>
- 分支: main → release
- CI:
  - <workflow-name>: success (<url>)
  - <workflow-name>: success (<url>)

失败:

## 发布失败

- 失败步骤: <step>
- 错误: <message>
- 建议: <action>

红线

永远不要:

  • 在工作区不干净时继续
  • 在远端 main 领先时继续
  • 在无嵌套 worktree 干扰且本地全仓 lint 失败时继续推送
  • ff-only 失败时强制合并
  • 跳过 CI 监控直接报告成功

Featured in 0 collections

See how others combine this skill with their stack

Not yet featured in any collection.

No reviews yet

Use it and be the first to leave a review

Version history

v0.0.0-202607210934latest
2026-07-21