fix: auto-approve bot review when PR base is changed off main (#1971)

* fix: reset bot review when PR base is changed off main

The check-pr-target workflow only ran on 'opened' events targeting main,
so it never re-ran after a submitter edited the base branch to 'staged'.
The REQUEST_CHANGES review was left in place, blocking merge and requiring
a manual maintainer override.

Changes:
- Broaden trigger to also fire on edited, reopened, and synchronize events,
  and add 'staged' to the branches filter so the workflow runs after a
  base-branch edit.
- Before posting REQUEST_CHANGES, check whether the bot already has an
  active CHANGES_REQUESTED review to avoid duplicate reviews.
- After a base-branch edit: if the PR no longer targets main and the bot's
  latest review state is CHANGES_REQUESTED, post an APPROVE review to
  clear the block automatically.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: rerun PR target check for any base branch

Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>
This commit is contained in:
Aaron Powell
2026-06-11 19:21:47 -07:00
committed by GitHub
parent bdc06cee15
commit 3e4cc87e91
+62 -17
View File
@@ -2,8 +2,11 @@ name: Check PR Target Branch
on: on:
pull_request_target: pull_request_target:
branches: [main] types: [opened, edited, reopened, synchronize]
types: [opened]
concurrency:
group: check-pr-target-${{ github.event.pull_request.number }}
cancel-in-progress: true
permissions: permissions:
pull-requests: write pull-requests: write
@@ -16,20 +19,62 @@ jobs:
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
with: with:
script: | script: |
const body = [ const pull = context.payload.pull_request;
'⚠️ **This PR targets `main`, but PRs should target `staged`.**', const owner = context.repo.owner;
'', const repo = context.repo.repo;
'The `main` branch is auto-published from `staged` and should not receive direct PRs.', const pullNumber = context.issue.number;
'Please close this PR and re-open it against the `staged` branch.', const botLogin = 'github-actions[bot]';
'',
'You can change the base branch using the **Edit** button at the top of this PR,',
'or run: `gh pr edit ${{ github.event.pull_request.number }} --base staged`'
].join('\n');
await github.rest.pulls.createReview({ const { data: reviews } = await github.rest.pulls.listReviews({
owner: context.repo.owner, owner,
repo: context.repo.repo, repo,
pull_number: context.issue.number, pull_number: pullNumber,
event: 'REQUEST_CHANGES', per_page: 100
body
}); });
const latestBotReview = reviews
.filter((review) => review.user?.login === botLogin)
.sort((a, b) => new Date(a.submitted_at ?? a.created_at) - new Date(b.submitted_at ?? b.created_at))
.at(-1);
const latestBotState = latestBotReview?.state;
if (pull.base.ref === 'main') {
if (latestBotState !== 'CHANGES_REQUESTED') {
const requestChangesBody = [
'⚠️ **This PR targets `main`, but PRs should target `staged`.**',
'',
'The `main` branch is auto-published from `staged` and should not receive direct PRs.',
'Please close this PR and re-open it against the `staged` branch.',
'',
'You can change the base branch using the **Edit** button at the top of this PR,',
'or run: `gh pr edit ${{ github.event.pull_request.number }} --base staged`'
].join('\n');
await github.rest.pulls.createReview({
owner,
repo,
pull_number: pullNumber,
event: 'REQUEST_CHANGES',
body: requestChangesBody
});
}
return;
}
if (latestBotState === 'CHANGES_REQUESTED') {
const approveBody = [
'✅ Base branch is now set correctly.',
'',
'Removing the prior block because this PR no longer targets `main`.'
].join('\n');
await github.rest.pulls.createReview({
owner,
repo,
pull_number: pullNumber,
event: 'APPROVE',
body: approveBody
});
}