Skip to content

Commit 3f9c5e1

Browse files
authored
Merge pull request #4449 from github/copilot/prt-migration-20260811-copilot-cli
Migrate pull request automation away from pull_request_target
2 parents da6329c + 132979e commit 3f9c5e1

2 files changed

Lines changed: 126 additions & 20 deletions

File tree

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
name: Close invalid PR writer
2+
3+
on:
4+
workflow_run:
5+
workflows: [Close issue/PR on adding invalid label]
6+
types: [completed]
7+
# pull_request does not run for conflicted PRs, so reconcile from the trusted default branch.
8+
schedule:
9+
- cron: '*/5 * * * *'
10+
workflow_dispatch:
11+
12+
permissions: {}
13+
14+
jobs:
15+
close-invalid-pr-from-workflow-run:
16+
if: >
17+
github.repository == 'github/copilot-cli' &&
18+
github.event_name == 'workflow_run' &&
19+
github.event.workflow_run.event == 'pull_request' &&
20+
github.event.workflow_run.repository.full_name == github.repository
21+
runs-on: ubuntu-latest
22+
permissions:
23+
actions: read
24+
pull-requests: write
25+
concurrency:
26+
group: close-invalid-pr-${{ github.event.workflow_run.pull_requests[0].number || github.run_id }}
27+
cancel-in-progress: false
28+
steps:
29+
- name: Close invalid PR
30+
env:
31+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
32+
GH_REPO: ${{ github.repository }}
33+
WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }}
34+
run: |
35+
set -euo pipefail
36+
37+
trusted_workflow_id="$(gh api "repos/$GH_REPO/actions/workflows/close-invalid.yml" --jq .id)"
38+
workflow_run="$(gh api "repos/$GH_REPO/actions/runs/$WORKFLOW_RUN_ID")"
39+
40+
if [ "$(jq -r .workflow_id <<<"$workflow_run")" != "$trusted_workflow_id" ] ||
41+
[ "$(jq -r .event <<<"$workflow_run")" != "pull_request" ] ||
42+
[ "$(jq -r .repository.full_name <<<"$workflow_run")" != "$GH_REPO" ]; then
43+
echo "Workflow run is not a trusted pull_request run from $GH_REPO; skipping."
44+
exit 0
45+
fi
46+
47+
if [ "$(jq '.pull_requests | length' <<<"$workflow_run")" -ne 1 ]; then
48+
echo "Workflow run is not associated with exactly one PR; skipping."
49+
exit 0
50+
fi
51+
52+
pr_number="$(jq -r .pull_requests[0].number <<<"$workflow_run")"
53+
run_head_sha="$(jq -r .head_sha <<<"$workflow_run")"
54+
run_head_repo="$(jq -r '.head_repository.full_name // empty' <<<"$workflow_run")"
55+
pr="$(gh api "repos/$GH_REPO/pulls/$pr_number")"
56+
57+
if [ -z "$run_head_repo" ] ||
58+
[ "$(jq -r .base.repo.full_name <<<"$pr")" != "$GH_REPO" ] ||
59+
[ "$(jq -r '.head.repo.full_name // empty' <<<"$pr")" != "$run_head_repo" ] ||
60+
[ "$(jq -r .head.sha <<<"$pr")" != "$run_head_sha" ]; then
61+
echo "PR #$pr_number no longer matches the workflow run head; skipping."
62+
exit 0
63+
fi
64+
65+
if [ "$(jq -r .state <<<"$pr")" != "open" ] ||
66+
! jq -e 'any(.labels[]?; .name == "invalid")' >/dev/null <<<"$pr"; then
67+
echo "PR #$pr_number is not open with the invalid label; skipping."
68+
exit 0
69+
fi
70+
71+
gh api -X PATCH "repos/$GH_REPO/pulls/$pr_number" -f state=closed
72+
73+
reconcile-invalid-prs:
74+
if: >
75+
github.repository == 'github/copilot-cli' &&
76+
(github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
77+
runs-on: ubuntu-latest
78+
permissions:
79+
pull-requests: write
80+
concurrency:
81+
group: close-invalid-pr-reconciliation
82+
cancel-in-progress: false
83+
steps:
84+
- name: Close open PRs with the invalid label
85+
env:
86+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
87+
GH_REPO: ${{ github.repository }}
88+
run: |
89+
set -euo pipefail
90+
91+
gh api --paginate "repos/$GH_REPO/pulls?state=open&per_page=100" \
92+
--jq '.[] | select(any(.labels[]?; .name == "invalid")) | .number' |
93+
while read -r pr_number; do
94+
pr="$(gh api "repos/$GH_REPO/pulls/$pr_number")"
95+
96+
if [ "$(jq -r .state <<<"$pr")" = "open" ] &&
97+
jq -e 'any(.labels[]?; .name == "invalid")' >/dev/null <<<"$pr"; then
98+
gh api -X PATCH "repos/$GH_REPO/pulls/$pr_number" -f state=closed
99+
fi
100+
done
Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,42 @@
11
name: Close issue/PR on adding invalid label
22

3-
# **What it does**: This action closes issues that are labeled as invalid in the repo.
3+
# **What it does**: This action closes invalid issues and signals invalid PRs to a trusted writer.
44

55
on:
66
issues:
77
types: [labeled]
8-
pull_request_target:
8+
pull_request:
99
types: [labeled]
1010

11-
permissions:
12-
contents: read
13-
issues: write
14-
pull-requests: write
11+
permissions: {}
1512

1613
jobs:
17-
close-on-adding-invalid-label:
18-
if:
19-
github.repository == 'github/copilot-cli' && github.event.label.name ==
20-
'invalid'
14+
close-issue-on-adding-invalid-label:
15+
if: >
16+
github.repository == 'github/copilot-cli' &&
17+
github.event_name == 'issues' &&
18+
github.event.label.name == 'invalid'
2119
runs-on: ubuntu-latest
22-
20+
permissions:
21+
issues: write
2322
steps:
2423
- name: Close issue
25-
if: ${{ github.event_name == 'issues' }}
2624
env:
27-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
28-
URL: ${{ github.event.issue.html_url }}
29-
run: gh issue close $URL
25+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26+
GH_REPOSITORY: ${{ github.repository }}
27+
ISSUE_NUMBER: ${{ github.event.issue.number }}
28+
run: gh api -X PATCH "repos/$GH_REPOSITORY/issues/$ISSUE_NUMBER" -f state=closed
3029

31-
- name: Close PR
32-
if: ${{ github.event_name == 'pull_request_target' }}
30+
signal-invalid-pr-label:
31+
if: >
32+
github.repository == 'github/copilot-cli' &&
33+
github.event_name == 'pull_request' &&
34+
github.event.label.name == 'invalid'
35+
runs-on: ubuntu-latest
36+
permissions: {}
37+
steps:
38+
- name: Record invalid PR label signal
3339
env:
34-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35-
URL: ${{ github.event.pull_request.html_url }}
36-
run: gh pr close $URL
40+
PR_NUMBER: ${{ github.event.pull_request.number }}
41+
run: |
42+
echo "Invalid label signal for PR #$PR_NUMBER"

0 commit comments

Comments
 (0)