From fa852014df85d3b9cc3b4e5e8c36bd772737faa6 Mon Sep 17 00:00:00 2001 From: lefarcen <935902669@qq.com> Date: Tue, 23 Jun 2026 16:41:22 +0800 Subject: [PATCH] feat(ci): auto-approve the release bot's own clean backport to satisfy release/v* review rule (#4682) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit release/v* requires one approving review, so backport-automerge could not merge the bot's own backport PRs (an app can't approve its own PR). Approve as github-actions[bot] — a separate identity — under the SAME gates as the merge (author == release bot, same-repo, non-draft, head == the CI SHA, CI green). The diff was already reviewed + approved on main; the backport is a mechanical, conflict-free cherry-pick, so this auto-approval is scoped strictly to the release bot's verified backports, then merged with the App token. Topology test updated. Co-authored-by: Claude Opus 4.8 --- .github/workflows/backport-automerge.yml | 23 +++++++++++++++++++++++ e2e/tests/packaged-smoke-workflow.test.ts | 9 +++++++++ 2 files changed, 32 insertions(+) diff --git a/.github/workflows/backport-automerge.yml b/.github/workflows/backport-automerge.yml index e6323f3fc..62ba2e43b 100644 --- a/.github/workflows/backport-automerge.yml +++ b/.github/workflows/backport-automerge.yml @@ -17,6 +17,7 @@ on: permissions: contents: read + pull-requests: write # github-actions[bot] approves the bot's own clean backport (Approve step) jobs: followup: @@ -64,6 +65,28 @@ jobs: echo "head_oid=$(printf '%s' "$row" | jq -r '.headRefOid')" } >> "$GITHUB_OUTPUT" + - name: Approve the clean backport (release bot, CI green) + # release/v* requires 1 approving review. The diff was already reviewed + approved on + # main; this is a mechanical, conflict-free cherry-pick by the release bot with green CI. + # Approve as github-actions[bot] — a DIFFERENT identity than the App that authored the PR + # (an author can't approve its own PR) — under the SAME bot-identity + SHA + CI gates as + # the merge below, so only the release bot's own verified backports are auto-approved. + if: >- + ${{ steps.pr.outputs.found == 'true' + && steps.pr.outputs.draft == 'false' + && steps.pr.outputs.author == 'open-design-release-bot[bot]' + && steps.pr.outputs.cross == 'false' + && steps.pr.outputs.head_oid == github.event.workflow_run.head_sha + && github.event.workflow_run.conclusion == 'success' }} + env: + GH_TOKEN: ${{ github.token }} + REPO: ${{ github.repository }} + NUM: ${{ steps.pr.outputs.number }} + run: | + set -euo pipefail + gh pr review "$NUM" --repo "$REPO" --approve \ + --body "Auto-approved: clean cherry-pick by the release bot of code already reviewed on main, CI green. (release/v* requires one approval.)" + - name: Auto-merge clean backport on green CI # Guards (release/v* has no required checks, so this workflow IS the gate): # - author == the release bot and same-repo (not a fork) — so a stranger can't get a diff --git a/e2e/tests/packaged-smoke-workflow.test.ts b/e2e/tests/packaged-smoke-workflow.test.ts index 43147f688..cab234460 100644 --- a/e2e/tests/packaged-smoke-workflow.test.ts +++ b/e2e/tests/packaged-smoke-workflow.test.ts @@ -236,6 +236,15 @@ describe("packaged smoke workflow", () => { expect(workflow).toContain("--squash"); expect(workflow).toContain("--delete-branch"); + // To satisfy release/v*'s one-approval rule, the bot's own clean backport is auto-approved by + // github-actions[bot] (pull-requests: write) — under the same author==bot gate as the merge. + expect(workflow).toContain("pull-requests: write"); + expect(workflow).toContain("gh pr review"); + expect(workflow).toContain("--approve"); + const approveStep = sectionBetween(workflow, "Approve the clean backport", "gh pr review"); + expect(approveStep).toContain("steps.pr.outputs.author == 'open-design-release-bot[bot]'"); + expect(approveStep).toContain("github.token"); + // The Feishu failure path carries the same identity gates, so a fork / non-bot backport-* // PR can't spam the release group. const feishuStep = sectionBetween(workflow, "Notify Feishu on failed backport CI", "FEISHU_WEBHOOK");