Skip to content

Commit 01b917a

Browse files
authored
removes ready-for-review label when PR is merged/approved etc. (#513)
* removes ready-for-review label when PR is merged/approved etc. Signed-off-by: Simon Davies <simongdavies@users.noreply.github.com> * fix workflow Signed-off-by: Simon Davies <simongdavies@users.noreply.github.com> --------- Signed-off-by: Simon Davies <simongdavies@users.noreply.github.com>
1 parent aea9d2d commit 01b917a

3 files changed

Lines changed: 132 additions & 0 deletions

File tree

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Ready-for-review (collect)
2+
3+
# Stage 1 of a two-stage pipeline that removes the "ready-for-review" label from
4+
# a pull request once it is no longer awaiting review.
5+
#
6+
# Pull-request and review events originating from FORKED repositories only ever
7+
# receive a read-only GITHUB_TOKEN, so a workflow triggered directly by them
8+
# cannot modify labels.
9+
# This stage therefore performs no privileged work: it
10+
# simply records the pull-request number and hands it to the privileged
11+
# "Ready-for-review (manage)" workflow, which is triggered via `workflow_run`
12+
# and runs with a read-write token. See
13+
# ready-for-review-manage.yml.
14+
on:
15+
pull_request:
16+
types: [closed, converted_to_draft]
17+
pull_request_review:
18+
types: [submitted, dismissed]
19+
20+
# Serialise runs per pull request so that concurrent events cannot race.
21+
concurrency:
22+
group: ready-for-review-collect-${{ github.event.pull_request.number }}
23+
cancel-in-progress: false
24+
permissions:
25+
contents: read
26+
27+
jobs:
28+
collect:
29+
runs-on: ubuntu-latest
30+
steps:
31+
- name: Record the pull-request number
32+
env:
33+
# Always a GitHub-provided integer; present on both the pull_request
34+
# and pull_request_review event payloads.
35+
PR_NUMBER: ${{ github.event.pull_request.number }}
36+
run: |
37+
set -euo pipefail
38+
mkdir -p pr
39+
printf '%s' "$PR_NUMBER" > pr/pr_number
40+
41+
- name: Upload the pull-request number
42+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
43+
with:
44+
name: ready-for-review-pr-number
45+
path: pr/
46+
retention-days: 1
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
name: Ready-for-review (manage)
2+
3+
# Stage 2 of the two-stage "ready-for-review" label pipeline. It is triggered
4+
# when "Ready-for-review (collect)" completes and runs in the context of the
5+
# base repository's default branch, so it receives a read-write GITHUB_TOKEN
6+
# even when the originating event came from a fork. This is what lets us remove
7+
# the label from pull requests opened from forks. See ready-for-review-label.yml.
8+
#
9+
# SECURITY: the collect stage can run from untrusted fork code, so the artifact
10+
# it produces is UNTRUSTED. We therefore:
11+
# * download it into a temporary directory,
12+
# * never check out or execute any pull-request code, and
13+
# * strictly validate the pull-request number (digits only) before use.
14+
# The downstream reusable workflow only ever *removes* the label, and only when
15+
# the PR genuinely meets a removal condition, so the worst a spoofed-but-valid
16+
# number could achieve is removing a single, manually re-addable label from a PR
17+
# that already qualified for removal.
18+
on:
19+
workflow_run:
20+
workflows: ["Ready-for-review (collect)"]
21+
types: [completed]
22+
23+
# Best-effort per-source-branch serialisation. The real PR number is only known
24+
# after the artifact is read, and the reusable workflow already tolerates a
25+
# concurrent label removal (HTTP 404), so this is belt-and-braces.
26+
concurrency:
27+
group: ready-for-review-manage-${{ github.event.workflow_run.head_repository.full_name }}-${{ github.event.workflow_run.head_branch }}
28+
cancel-in-progress: false
29+
30+
permissions:
31+
actions: read # download the artifact from the collect run
32+
contents: read
33+
pull-requests: write # remove the label
34+
issues: write # labels are managed through the issues API
35+
36+
jobs:
37+
read-pr:
38+
runs-on: ubuntu-latest
39+
# Only act on a collect run that actually succeeded.
40+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
41+
outputs:
42+
pr_number: ${{ steps.read.outputs.pr_number }}
43+
steps:
44+
- name: Download the pull-request number
45+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
46+
with:
47+
name: ready-for-review-pr-number
48+
path: ${{ runner.temp }}/pr # temp dir, never the workspace
49+
run-id: ${{ github.event.workflow_run.id }}
50+
github-token: ${{ secrets.GITHUB_TOKEN }}
51+
52+
- name: Read and validate the pull-request number
53+
id: read
54+
env:
55+
ARTIFACT_DIR: ${{ runner.temp }}/pr
56+
run: |
57+
set -euo pipefail
58+
raw="$(cat "${ARTIFACT_DIR}/pr_number")"
59+
# Untrusted input from a potentially fork-triggered run: digits only.
60+
if [[ ! "$raw" =~ ^[0-9]+$ ]]; then
61+
echo "Refusing to act on non-numeric PR number" >&2
62+
printf 'Value was: %q\n' "$raw" >&2
63+
exit 1
64+
fi
65+
echo "pr_number=${raw}" >> "$GITHUB_OUTPUT"
66+
67+
manage-label:
68+
needs: read-pr
69+
# Shared workflow in the org-wide `.github` repository, pinned to a commit SHA.
70+
uses: hyperlight-dev/.github/.github/workflows/manage-ready-for-review.yml@e5e471d927d3a72676ab48433da8a99d15a32ad7
71+
with:
72+
# fromJSON turns the validated digit-string into a numeric input.
73+
pr-number: ${{ fromJSON(needs.read-pr.outputs.pr_number) }}

docs/github-labels.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,19 @@ We use GitHub labels to categorize PRs. Before a PR can be merged, it must be as
77
- **kind/enhancement** - For PRs that introduce new features or improve existing functionality. This label also applies to improvements in documentation, testing, and similar areas. Any changes must be backward-compatible.
88
- **kind/refactor** - For PRs that restructure or remove code without adding new functionality. This label also applies to changes that affect user-facing APIs.
99

10+
## Review readiness
11+
12+
We use the **ready-for-review** label to signal that a PR is waiting for a (re-)review:
13+
14+
- **Add** `ready-for-review` when you open a PR that is ready for review, or when a PR is ready for re-review (for example, once you have addressed requested changes and re-requested review).
15+
- The label is **removed automatically** by the [`Ready-for-review label`](../.github/workflows/ready-for-review-label.yml) workflow once the PR is no longer awaiting that review, specifically when any of the following become true:
16+
- the PR is closed or merged,
17+
- the PR is converted to a draft,
18+
- the PR has two or more approvals, or
19+
- the PR has two or more change requests.
20+
21+
You only ever need to add the label; removal is fully automated.
22+
1023
---
1124

1225
# **Issues**

0 commit comments

Comments
 (0)