From e05ef2211320311abc8e5b8fa9541936d619fd07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamila=20=C5=9Aroda?= Date: Wed, 22 Jul 2026 13:49:50 +0200 Subject: [PATCH 1/2] ci: sync bot approval with assignee approval Mirror a non-author assignee's approval as a second (bot) approval, and dismiss it if the assignee approval is no longer active. Ported from the acp repo, minus the Slack failure notification. Co-Authored-By: Claude Fable 5 --- .github/workflows/assignee-approval-sync.yml | 46 ++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .github/workflows/assignee-approval-sync.yml diff --git a/.github/workflows/assignee-approval-sync.yml b/.github/workflows/assignee-approval-sync.yml new file mode 100644 index 0000000..2ea2d63 --- /dev/null +++ b/.github/workflows/assignee-approval-sync.yml @@ -0,0 +1,46 @@ +name: Sync bot approval with assignee +on: + pull_request_review: + types: [submitted, dismissed, edited] + pull_request: + types: [assigned, unassigned] + +permissions: + pull-requests: write + +jobs: + sync: + runs-on: ubuntu-latest + if: github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.user.login != 'dependabot[bot]' + steps: + - name: Mirror assignee approval as a second (bot) approval + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BOT: "github-actions[bot]" + PR: ${{ github.event.pull_request.number }} + REPO: ${{ github.repository }} + AUTHOR: ${{ github.event.pull_request.user.login }} + run: | + assignees=$(gh pr view "$PR" -R "$REPO" --json assignees -q '.assignees[].login') + reviews=$(gh api "/repos/$REPO/pulls/$PR/reviews" --paginate --jq '.[]' | jq -s '.') + + # Latest review of any non-author assignee is APPROVED? + # (GitHub ignores the author's own approval for required approvals.) + approved=false + for a in $assignees; do + [ "$a" = "$AUTHOR" ] && continue + state=$(echo "$reviews" | jq -r --arg u "$a" \ + '[.[]|select(.user.login==$u)]|last|.state // empty') + [ "$state" = "APPROVED" ] && approved=true + done + + # Bot's active approval = its latest review, only if still APPROVED + botrev=$(echo "$reviews" | jq -r --arg b "$BOT" \ + '([.[]|select(.user.login==$b)]|last) as $r | if $r.state=="APPROVED" then $r.id else empty end') + + if $approved && [ -z "$botrev" ]; then + gh pr review "$PR" -R "$REPO" --approve --body "Auto-approve: assignee approved." + elif ! $approved && [ -n "$botrev" ]; then + gh api -X PUT "/repos/$REPO/pulls/$PR/reviews/$botrev/dismissals" \ + -f message="Assignee approval no longer active — dismissing bot approval." + fi From 6aba4ee05c003f0162477c23452ad8b3105fd10c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamila=20=C5=9Aroda?= Date: Wed, 22 Jul 2026 15:48:31 +0200 Subject: [PATCH 2/2] copilot review fixes --- .github/workflows/assignee-approval-sync.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/assignee-approval-sync.yml b/.github/workflows/assignee-approval-sync.yml index 2ea2d63..783c68a 100644 --- a/.github/workflows/assignee-approval-sync.yml +++ b/.github/workflows/assignee-approval-sync.yml @@ -15,12 +15,13 @@ jobs: steps: - name: Mirror assignee approval as a second (bot) approval env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} BOT: "github-actions[bot]" PR: ${{ github.event.pull_request.number }} REPO: ${{ github.repository }} AUTHOR: ${{ github.event.pull_request.user.login }} run: | + set -euo pipefail assignees=$(gh pr view "$PR" -R "$REPO" --json assignees -q '.assignees[].login') reviews=$(gh api "/repos/$REPO/pulls/$PR/reviews" --paginate --jq '.[]' | jq -s '.')