Skip to content

ci: publish stable from release PRs and prereleases from a configurable branch - #580

Open
wangl-cc wants to merge 7 commits into
mainfrom
codex/stable-release-automation
Open

wangl-cc wants to merge 7 commits into
mainfrom
codex/stable-release-automation

Conversation

@wangl-cc

@wangl-cc wangl-cc commented Sep 13, 2026 •

Copy link
Copy Markdown
Member

Requested by Loong · project thread

Stable 发布现在由带 release 标签的同仓库 PR 合入 main 明确触发。版本和 changelog 在 PR 中一起审核,普通版本 bump 不再触发发布;已单独更新版本时,可以创建只更新 changelog 的 release PR。Beta/Nightly 改为从 PRERELEASE_BRANCH 指定的分支发布(默认 main),这样 main 只发 stable,大改动(如 0.8)在 dev 分支上出 beta。

Stable

  • 新增 Prepare Stable Release,支持 auto、patch、minor、major 和指定版本,使用 git-cliff 2.13.1 推导版本和生成 changelog。重新运行时会关闭其他未合并的 release-prep/* PR 并删除其分支。
  • 新增独立的 Release Readiness workflow,在 pull_request 和 merge_group 上运行:带标签的 PR 只能改 CHANGELOG.md、Cargo.lock、crates/maa-cli/Cargo.toml,且 changelog 必须是最新的;release-prep/* 分支没有 release 标签时直接失败(合并后不会发布);merge queue 中按实际合并结果再检查一次,避免队列里前面的 PR 让 changelog 过期。
  • release.yml 只监听 pull_request: closed,未合并或无标签的关闭事件使用独立 concurrency 组,不再占用 release-state 队列。
  • 1.0 之前 feat 只 bump patch(features_always_bump_minor = false),新 minor 需要显式选择或 breaking change。
  • 放宽 git-cliff 规则:去掉 require_conventional / fail_on_unmatched_commit,非约定式提交不会再卡住所有发布通道;GitHub Revert 按钮生成的 Revert "..." 映射为 revert:;Security 分组放在 skip 规则之后,dependabot 不再进入 Security。

Beta / Alpha (Nightly)

  • 构建时通过 MAA_VERSION 注入版本,不修改源码分支的 Cargo.toml、Cargo.lock 或 changelog。编号由已发布索引维护;Beta tag 或 Nightly 发布超前于索引时,先恢复索引再分配序号。
  • 新增仓库变量 PRERELEASE_BRANCH:定时 Nightly 和手动 Beta/Alpha 都从该分支取源码(scheduled run 只在默认分支触发,所以由 workflow 主动 checkout 该分支);从其他分支手动运行会直接失败。
  • Nightly 只要上一个 tag 之后有新提交就构建,基础版本为下一个 patch。
  • 预发布说明按 上一个 stable tag..HEAD 区间生成,避免 dev 分支合并 main 后把已发布提交算进来。
  • 删除 nightly 后轮询确认 tag 已消失再重建,避免 release 变成 draft。

发布产物与下游

  • 将发布计划、说明和打包产物保存为 artifacts,失败重试复用原内容(构建产物保留 7 天,超过需要 Re-run all jobs)。打包直接输出 bundle,保持输入索引只读。独立更新 version 分支,拒绝 tag 冲突及旧发布覆盖较新索引。
  • 下游发布等待索引更新成功,且每次重试都重新检查当前 stable 身份,防止旧任务在新版发布后回退包版本。手动 WinGet 发布核对实际请求的 tag;手动 AUR 非 dry-run 时必须填 pkgver。
  • Homebrew maa-cli-beta 只在 stable 比当前 beta 新时才跟进,不会被回退。
  • 移除独立的 changelog 发布工作流,新增发布工具回归测试工作流;CI 和 docs lint 也在 dev-* 分支上运行。DEVELOPMENT.md 补充了流程、恢复方法和分支模型(dev 分支定期合并 main,最终以 merge commit 合回 main)。

验证

  • cargo +nightly fmt、cargo clippy -p xtask --all-targets --locked -- -D warnings 和 cargo test -p xtask --locked 通过,xtask 共 22 项测试。
  • 使用 git-cliff 2.13.1 的 test-release-files.sh、test-release-recovery.sh 及 ShellCheck 通过,覆盖 changelog-only PR、过期说明刷新、Readiness 的 PR / merge queue 场景、非约定式与 Revert 提交、pre-1.0 feat、dev 分支预发布说明、Nightly 索引滞后与恢复、tag 删除等待、Homebrew beta 不回退、旧下游任务重试和手动 WinGet tag 错配。
  • 在 main 真实历史副本上验证 auto 选出 0.7.6,Prepare/check 在普通 merge 和 squash 两种合入方式下都通过。
  • actionlint 1.7.12 在忽略尚未支持的 concurrency.queue 字段诊断后通过。

尚未运行真实 GitHub Actions 发布。

合并前后需要的仓库设置

  • Settings → Actions → General:开启 Allow GitHub Actions to create and approve pull requests。
  • 将 Release Readiness 加入 main 的 required checks(merge queue 才会在队列里运行它)。
  • 需要从 dev 分支出 beta/nightly 时,设置仓库变量 PRERELEASE_BRANCH(例如 dev-0.8)。
  • 首次真实发布时确认:merge queue 合入后 pull_request.closed 的 merge_commit_sha 指向 main 上的最终提交;brew info 返回的 beta 版本格式符合预期。

🤖 Generated with Claude Code

https://claude.ai/code/session_012ULwm4FYPWei21gc5bhw1x

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

你好——我发现了 1 个问题

面向 AI Agent 的提示
请处理此次代码审查中的评论:

## 单独评论

### 评论 1
<location path=".github/workflows/release.yml" line_range="45-47" />
<code_context>
+    if: >-
+      github.event_name == 'pull_request' &&
+      github.event.action != 'closed' &&
+      (contains(github.event.pull_request.labels.*.name, 'release') ||
+       startsWith(github.event.pull_request.head.ref, 'release-prep/')) &&
+      github.event.pull_request.head.repo.full_name == github.repository
     runs-on: ubuntu-latest
-    outputs:
</code_context>
<issue_to_address>
**小问题:** Release Readiness 作业会对任何头部分支以 `release-prep/` 开头的同仓库 PR 运行,即使该 PR 没有 `release` 标签。这与所述的显式标签触发条件相矛盾,并导致未添加标签的发布准备分支也会接收特定于发布的验证和状态检查。

**触发场景:** 同仓库 PR 使用以 `release-prep/` 开头的头部分支,但尚未添加 `release` 标签时。

**建议修复:** 在作业条件中要求存在 `release` 标签,或移除 `startsWith(github.event.pull_request.head.ref, 'release-prep/')` 这一备选条件。
</issue_to_address>

Sourcery 对开源项目免费——如果你喜欢我们的审查,请考虑分享它们 ✨
Original comment in English

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path=".github/workflows/release.yml" line_range="45-47" />
<code_context>
+    if: >-
+      github.event_name == 'pull_request' &&
+      github.event.action != 'closed' &&
+      (contains(github.event.pull_request.labels.*.name, 'release') ||
+       startsWith(github.event.pull_request.head.ref, 'release-prep/')) &&
+      github.event.pull_request.head.repo.full_name == github.repository
     runs-on: ubuntu-latest
-    outputs:
</code_context>
<issue_to_address>
**nitpick:** The Release Readiness job runs for any same-repository PR whose head branch starts with `release-prep/`, even when the PR has no `release` label. This contradicts the stated explicit-label trigger and causes unlabelled release-preparation branches to receive release-specific validation and status checks.

**Triggers:** When a same-repository PR uses a `release-prep/` head branch before the `release` label is added.

**Suggested fix:** Require the `release` label in the job condition, or remove the `startsWith(github.event.pull_request.head.ref, 'release-prep/')` alternative.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread .github/workflows/release.yml Outdated
@codecov

codecov Bot commented Sep 13, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 72.93%. Comparing base (df0a6b7) to head (09d9aa2).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #580   +/-   ##
=======================================
  Coverage   72.93%   72.93%           
=======================================
  Files          72       72           
  Lines        6798     6798           
  Branches     6798     6798           
=======================================
  Hits         4958     4958           
  Misses       1546     1546           
  Partials      294      294           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

wangl-cc and others added 6 commits September 13, 2026 15:35
…rge queue

- Drop require_conventional and fail_on_unmatched_commit so a single
  unconventional commit (e.g. GitHub's Revert button) no longer blocks
  nightly, beta and stable releases; map `Revert "..."` to `revert:`.
- Move Release Readiness into its own workflow that also runs on
  merge_group, checking the queue entry that lands the release commit.
- Fail readiness for release-prep PRs without the release label.
- Release only listens for closed PRs; unlabeled closes use a throwaway
  concurrency group instead of queueing behind release builds.
- Wait for the deleted nightly tag to disappear before recreating it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ULwm4FYPWei21gc5bhw1x
- Nightly builds new commits without a bumping change against the next
  patch version instead of skipping; beta still skips.
- Group security-tagged commits after the skip rules so dependency bumps
  stay out of the changelog.
- Prepare closes other open release-prep PRs when the version changes.
- Require pkgver for non-dry-run AUR publication.
- Document the 7-day build artifact limit for failed-job reruns.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ULwm4FYPWei21gc5bhw1x
Set features_always_bump_minor = false so `auto` derives 0.7.x from
features on main; starting 0.8 requires an explicit `minor` selection
or a breaking change.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ULwm4FYPWei21gc5bhw1x
- PRERELEASE_BRANCH (default main) selects where beta and nightly come
  from; scheduled nightly builds that branch's head and manual
  prereleases from other branches fail fast. Stable stays on main.
- Prerelease notes use the latest reachable stable tag as an explicit
  range, so a dev branch that merges main does not repeat published fixes.
- Stable releases no longer move the Homebrew maa-cli-beta formula back.
- Run CI and markdown lint on dev-* branches.
- Document the dev branch model and how it merges back into main.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ULwm4FYPWei21gc5bhw1x
@wangl-cc wangl-cc changed the title ci: publish releases from explicit release PRs ci: publish stable from release PRs and prereleases from a configurable branch Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants