-
Notifications
You must be signed in to change notification settings - Fork 95
136 lines (121 loc) · 5.23 KB
/
Copy pathpr-ready-for-review-label.yml
File metadata and controls
136 lines (121 loc) · 5.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
name: PR Ready for Review Label
on:
workflow_run:
workflows:
- "Build and Lint"
- "Playwright Tests"
- "Pull Request Convention Checks"
- "Spell Check"
types:
- completed
# This is a dangerous event trigger as it causes the workflow to run in the
# context of the target repository.
# Avoid checking out the head of the pull request or building code from the
# pull request whenever this trigger is used.
# Since we only label pull requests, do not have a checkout step in this
# workflow, and restrict permissions on the token, this is an acceptable
# use of this trigger.
pull_request_target:
types:
- opened
- reopened
- synchronize
- ready_for_review
- converted_to_draft
concurrency:
group: pr-ready-label-${{ github.workflow }}-${{ github.event.pull_request.number || github.event.workflow_run.head_sha }}
cancel-in-progress: true
jobs:
pr_ready_label_evaluation:
name: Evaluate required checks and toggle label
runs-on: ubuntu-latest
permissions:
pull-requests: write
checks: read
contents: read
steps:
- name: Resolve target PR number
id: prs
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
if [[ "${{ github.event_name }}" == "pull_request_target" ]]; then
pr_number="${{ github.event.pull_request.number }}"
else
# workflow_run.pull_requests is empty for fork PRs; resolve via commit -> PR lookup.
pr_number="$(gh api "repos/${{ github.event.repository.full_name }}/commits/${{ github.event.workflow_run.head_sha }}/pulls" \
--jq '[.[] | select(.state == "open") | .number] | first // empty')"
fi
echo "pr_number=${pr_number}" >> "$GITHUB_OUTPUT"
- name: Evaluate required checks and toggle label
if: ${{ steps.prs.outputs.pr_number != '' }}
shell: bash
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ steps.prs.outputs.pr_number }}
run: |
set -euo pipefail
# Keep in sync with required status checks in branch protection on the default branch.
required_checks=(
"Build & Lint"
"Spell check"
"Spell check PR title"
"Verify PR contains one or more linked issues"
"Verify PR title follows conventional commit standards"
"playwright-tests (1)"
"playwright-tests (2)"
"playwright-tests (3)"
"playwright-tests (4)"
)
repo="${{ github.event.repository.full_name }}"
label="R-ready-for-review"
pr_json="$(gh api "repos/${repo}/pulls/${PR_NUMBER}")"
pr_state="$(jq -r '.state' <<<"$pr_json")"
is_draft="$(jq -r '.draft' <<<"$pr_json")"
pr_head_sha="$(jq -r '.head.sha' <<<"$pr_json")"
if [[ "$pr_state" != "open" ]]; then
echo "PR #${PR_NUMBER} is not open (state=$pr_state); skipping."
exit 0
fi
if [[ "$is_draft" == "true" ]]; then
echo "PR #${PR_NUMBER} is a draft; ensuring label is absent."
gh --repo "$repo" pr edit "$PR_NUMBER" --remove-label "$label"
exit 0
fi
# A workflow_run completion for an outdated SHA must not overwrite the latest state.
if [[ "${{ github.event_name }}" == "workflow_run" && "${{ github.event.workflow_run.head_sha }}" != "$pr_head_sha" ]]; then
echo "workflow_run head_sha does not match PR head; skipping stale evaluation."
exit 0
fi
checks_json="$(gh api "repos/${repo}/commits/${pr_head_sha}/check-runs?per_page=100" \
--jq '[.check_runs[] | {name, status, conclusion, started_at}]')"
all_green=true
reason=""
for ctx in "${required_checks[@]}"; do
# max_by picks the unambiguous latest started_at; sort_by|last is
# ordering-ambiguous when rapid re-runs land with near-identical
# timestamps.
match="$(jq --arg n "$ctx" '[.[] | select(.name == $n)] | max_by(.started_at) // empty' <<<"$checks_json")"
if [[ -z "$match" || "$match" == "null" ]]; then
all_green=false; reason="missing: $ctx"; break
fi
status="$(jq -r '.status' <<<"$match")"
conclusion="$(jq -r '.conclusion' <<<"$match")"
if [[ "$status" != "completed" ]]; then
all_green=false; reason="pending: $ctx (status=$status)"; break
fi
case "$conclusion" in
success|skipped|neutral) ;;
*) all_green=false; reason="failed: $ctx (conclusion=$conclusion)"; break ;;
esac
done
# GitHub CLI returns a successful exit code whether or not the label is already attached/absent.
if $all_green; then
echo "PR #${PR_NUMBER}: all required checks green; adding '$label'."
gh --repo "$repo" pr edit "$PR_NUMBER" --add-label "$label"
else
echo "PR #${PR_NUMBER}: not ready ($reason); removing '$label' if present."
gh --repo "$repo" pr edit "$PR_NUMBER" --remove-label "$label"
fi