Skip to content

Commit cbb5836

Browse files
sfanahataShannon Anahata
andauthored
feat(docs): automate PR review triage (#19078)
## DESCRIBE YOUR PR Automates priority triage and non-blocking reviewer assignment for docs PRs. **What changes:** - Parses the PR urgency section into mutually exclusive Urgent, Deadline, Needs Triage, or Normal labels. - Adds one non-blocking reminder comment when a ready PR has missing or malformed priority metadata, and removes it after correction. - Requests `getsentry/docs` only for ready, human-authored PRs that are urgent/deadline-based, external, significant changes under `docs/**`, or significant changes overall. - Preserves the existing commented CODEOWNERS specialist assignments without making Docs or specialists required reviewers. - Moves external-PR evaluation to trusted `pull_request_target` workflows with least-privilege tokens and base-SHA validation. - Removes nine unused, overlapping labels. - Updates the PR template to require exactly one urgency selection and ISO `YYYY-MM-DD` deadline dates. Slack alerts and a daily digest will be added in as a part of this workflow in a follow-up PR. ## IS YOUR CHANGE URGENT? - [ ] Urgent deadline (GA date, etc.): YYYY-MM-DD - [ ] Other deadline: YYYY-MM-DD - [x] No deadline: Not urgent, can wait up to 1 week+ ## TEST PLAN - `pnpm exec vitest run scripts/docs-pr-triage.test.mjs scripts/pr-reviewer-assignment.test.mjs scripts/pr-priority-metadata.test.mjs scripts/codeowner-workflow.test.mjs scripts/priority-metadata-workflow.test.mjs` (114 focused tests) - `pnpm test:ci` (346 tests) - Targeted ESLint, Prettier, Node syntax, workflow YAML, and `git diff --check` validation - Real reviewer dry runs against PRs #19031, #19037, #19055, and #19075 - Real metadata dry runs against PRs #19031, #19073, and #19075 - `github-label-sync@2.2.0 --dry-run` verified only four label creations and nine confirmed zero-use deletions ## PRE-MERGE CHECKLIST - [ ] Checked Vercel preview for correctness, including links - [ ] PR was reviewed and approved by any necessary SMEs (subject matter experts) - [ ] PR was reviewed and approved by a member of the [Sentry docs team](https://github.com/orgs/getsentry/teams/docs) ## EXTRA RESOURCES - [Sentry Docs contributor guide](https://docs.sentry.io/contributing/) --------- Co-authored-by: Shannon Anahata <shannonanahata@gmail.com>
1 parent 90caa03 commit cbb5836

18 files changed

Lines changed: 2287 additions & 152 deletions

‎.claude/rules/pr-description.md‎

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,22 @@ When creating pull requests for sentry-docs, use the following format:
1515
## IS YOUR CHANGE URGENT?
1616

1717
Help us prioritize incoming PRs by letting us know when the change needs to go live.
18-
- [ ] Urgent deadline (GA date, etc.): <!-- ENTER DATE HERE -->
19-
- [ ] Other deadline: <!-- ENTER DATE HERE -->
20-
- [x] None: Not urgent, can wait up to 1 week+
18+
Select exactly one option. For deadlines, replace `YYYY-MM-DD` with the due date. You can update this information later by editing the PR description.
19+
20+
- [ ] Urgent deadline (GA date, etc.): YYYY-MM-DD
21+
- [ ] Other deadline: YYYY-MM-DD
22+
- [x] No deadline: Not urgent, can wait up to 1 week+
2123

2224
## SLA
2325

2426
- Teamwork makes the dream work, so please add a reviewer to your PRs.
25-
- Please give the docs team up to 1 week to review your PR unless you've added an urgent due date to it.
27+
- Please give the docs team up to 1 week to review your PR unless you've supplied a deadline.
28+
2629
Thanks in advance for your help!
2730

2831
## PRE-MERGE CHECKLIST
2932

30-
*Make sure you've checked the following before merging your changes:*
33+
_Make sure you've checked the following before merging your changes:_
3134

3235
- [ ] Checked Vercel preview for correctness, including links
3336
- [ ] PR was reviewed and approved by any necessary SMEs (subject matter experts)
@@ -36,7 +39,9 @@ Thanks in advance for your help!
3639

3740
## Notes
3841

39-
- Default urgency to "None" unless the user specifies otherwise
42+
- Keep the "IS YOUR CHANGE URGENT?" section in every PR description
43+
- Default urgency to "No deadline" unless the user specifies otherwise
44+
- Use `YYYY-MM-DD` for urgent and other deadline dates
4045
- Include preview URLs when relevant (Vercel deploys preview URLs automatically)
4146
- Keep the "DESCRIBE YOUR PR" section concise but informative
4247
- Use bullet points for multiple discrete changes

‎.github/PULL_REQUEST_TEMPLATE.md‎

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,28 @@
1-
<!-- Use this checklist to make sure your PR is ready for merge. You may delete any sections you don't need. -->
1+
<!-- Keep the urgency section so automation can prioritize this PR. You may delete other sections you don't need. -->
22

33
## DESCRIBE YOUR PR
4-
*Tell us what you're changing and why. If your PR **resolves an issue**, please link it so it closes automatically.*
54

6-
## IS YOUR CHANGE URGENT?
5+
_Tell us what you're changing and why. If your PR **resolves an issue**, please link it so it closes automatically._
6+
7+
## IS YOUR CHANGE URGENT?
78

89
Help us prioritize incoming PRs by letting us know when the change needs to go live.
9-
- [ ] Urgent deadline (GA date, etc.): <!-- ENTER DATE HERE -->
10-
- [ ] Other deadline: <!-- ENTER DATE HERE -->
11-
- [ ] None: Not urgent, can wait up to 1 week+
10+
Select exactly one option. For deadlines, replace `YYYY-MM-DD` with the due date. You can update this information later by editing the PR description.
11+
12+
- [ ] Urgent deadline (GA date, etc.): YYYY-MM-DD
13+
- [ ] Other deadline: YYYY-MM-DD
14+
- [ ] No deadline: Not urgent, can wait up to 1 week+
1215

1316
## SLA
1417

1518
- Teamwork makes the dream work, so please add a reviewer to your PRs.
16-
- Please give the docs team up to 1 week to review your PR unless you've added an urgent due date to it.
19+
- Please give the docs team up to 1 week to review your PR unless you've supplied a deadline.
20+
1721
Thanks in advance for your help!
1822

1923
## PRE-MERGE CHECKLIST
2024

21-
*Make sure you've checked the following before merging your changes:*
25+
_Make sure you've checked the following before merging your changes:_
2226

2327
- [ ] Checked Vercel preview for correctness, including links
2428
- [ ] PR was reviewed and approved by any necessary SMEs (subject matter experts)

‎.github/labels.yml‎

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,33 @@
1717
color: F6F6F8
1818
description: Pull requests that update a dependency file
1919

20-
# Issue types
20+
# Docs issue categories
21+
- name: Docs
22+
color: ededed
23+
description: Documentation content issues
24+
- name: 'Docs Content'
25+
color: 26b5ce
26+
- name: 'Docs Platform'
27+
color: ededed
28+
description: Documentation site and tooling issues
29+
30+
# Legacy issue types
2131
- name: 'Type: Content'
2232
color: FBCA04
23-
- name: 'Type: Platform'
24-
color: 1D76DB
2533

26-
#
27-
- name: 'Develop'
28-
color: F6F6F8
29-
30-
# Impacts
31-
- name: 'Impact: Large'
32-
color: C83852
33-
- name: 'Impact: Medium'
34-
color: FFB287
35-
- name: 'Impact: Small'
36-
color: '452650'
34+
# PR priorities
35+
- name: 'Priority: Urgent'
36+
color: B60205
37+
description: Docs review is needed immediately for an urgent deadline
38+
- name: 'Priority: Deadline'
39+
color: D93F0B
40+
description: Docs review has a specific non-urgent due date
41+
- name: 'Priority: Needs Triage'
42+
color: FBCA04
43+
description: The PR description is missing valid priority information
44+
- name: 'Priority: Normal'
45+
color: 0E8A16
46+
description: Docs review has no urgent deadline
3747

3848
# Platforms
3949
- name: 'Platform: .NET'
@@ -94,6 +104,10 @@
94104
color: '8D5494'
95105
- name: 'Stale'
96106
color: '8D5494'
107+
- name: 'State: Unreproducible'
108+
color: f2994a
109+
- name: "State: Won't Do"
110+
color: 95a2b3
97111

98112
# Product Areas - www.notion.so/sentry/473791bae5bf43399d46093050b77bf0
99113
- name: 'Product Area: Unknown'
@@ -246,8 +260,9 @@
246260
description: team-web-sdk-backend
247261
- name: 'Team: Workflow'
248262
color: 8D5494
249-
- name: 'All SDKs'
250-
color: 1D76DB
263+
- name: 'Team: SDKs'
264+
color: ededed
265+
description: Issues that affect all or multiple SDK teams
251266
- name: 'SDKs'
252267
color: 1D76DB
253268
- name: 'Develop'
@@ -256,8 +271,6 @@
256271
color: 8D5494
257272
- name: 'Improvement'
258273
color: 8D5494
259-
- name: 'Launch 🚀'
260-
color: 8D5494
261274
- name: 'Product'
262275
color: 8D5494
263276

@@ -282,12 +295,6 @@
282295
color: 1279F1
283296
- name: duplicate
284297
color: F6F6F8
285-
- name: 'Effort: Large'
286-
color: FBCA04
287-
- name: 'Effort: Medium'
288-
color: FBCA04
289-
- name: 'Effort: Small'
290-
color: FBCA04
291298
- name: enhancement
292299
color: F6F6F8
293300
- name: filler
@@ -310,7 +317,7 @@
310317
color: F6F6F8
311318
description: Pull requests that update Javascript code
312319
- name: Mobile
313-
color: '584774'
320+
color: f2c94c
314321
- name: performance
315322
color: '584774'
316323
- name: up-for-grabs
@@ -335,3 +342,21 @@
335342
color: F6F6F8
336343
- name: github_actions
337344
color: F6F6F8
345+
- name: arcade
346+
color: ededed
347+
- name: auth-complex
348+
color: ededed
349+
- name: docs-screenshots
350+
color: ededed
351+
- name: documentation
352+
color: ededed
353+
- name: jared
354+
color: 943CE4
355+
- name: Playwright
356+
color: ededed
357+
- name: Security
358+
color: ededed
359+
- name: stale-image
360+
color: ededed
361+
- name: Supply-Chain-Vuln
362+
color: ededed
Lines changed: 62 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,40 @@
11
name: Codeowner assignment
22

3-
on: [pull_request]
3+
on:
4+
pull_request_target:
5+
types: [opened, edited, reopened, synchronize, ready_for_review]
6+
workflow_dispatch:
7+
inputs:
8+
pr_number:
9+
description: Pull request number to evaluate
10+
required: true
11+
type: number
12+
dry_run:
13+
description: Log reviewer decisions without requesting reviewers
14+
required: true
15+
default: true
16+
type: boolean
17+
18+
permissions:
19+
contents: read
420

521
jobs:
622
codeowner_assignment:
723
name: Codeowner assignment
24+
if: >-
25+
github.event_name == 'workflow_dispatch' ||
26+
github.event.action != 'edited' ||
27+
github.event.changes.body != null
28+
concurrency:
29+
group: >-
30+
codeowner-assignment-${{ github.event.pull_request.number || inputs.pr_number }}-${{
31+
github.event_name == 'workflow_dispatch' && inputs.dry_run && github.run_id ||
32+
github.event.action == 'edited' && github.run_id || 'assignment' }}
33+
cancel-in-progress: true
834
runs-on: ubuntu-latest
9-
permissions:
10-
contents: write
11-
pull-requests: write
35+
timeout-minutes: 5
1236

1337
steps:
14-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
15-
1638
- uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
1739
id: token
1840
with:
@@ -21,116 +43,45 @@ jobs:
2143
owner: ${{ github.repository_owner }}
2244
repositories: |
2345
sentry-docs
46+
permission-pull-requests: write
2447

25-
- name: Parse CODEOWNERS and assign reviewers
26-
id: assign-reviewers
48+
- name: Resolve trusted base commit
49+
id: base
2750
env:
28-
PR_NUMBER: ${{ github.event.number }}
51+
EVENT_BASE_SHA: ${{ github.event.pull_request.base.sha }}
52+
PR_NUMBER: ${{ github.event.pull_request.number || inputs.pr_number }}
53+
REPOSITORY: ${{ github.repository }}
2954
GH_TOKEN: ${{ steps.token.outputs.token }}
3055
run: |
31-
# locate CODEOWNERS file exists
32-
if [[ -f .github/CODEOWNERS ]]; then
33-
codeowner_path=".github/CODEOWNERS"
34-
elif [[ -f CODEOWNERS ]]; then
35-
codeowner_path="CODEOWNERS"
36-
else
37-
echo "CODEOWNERS file not found, skipping."
38-
exit 0
56+
base_sha="$EVENT_BASE_SHA"
57+
if [[ -z "$base_sha" ]]; then
58+
base_sha=$(gh api "repos/$REPOSITORY/pulls/$PR_NUMBER" --jq '.base.sha')
3959
fi
60+
if [[ ! "$base_sha" =~ ^[0-9a-f]{40}$ ]]; then
61+
echo "Invalid base commit SHA" >&2
62+
exit 1
63+
fi
64+
echo "sha=$base_sha" >> "$GITHUB_OUTPUT"
4065
41-
# Get changed files in the PR
42-
CHANGED_FILES=$(gh pr view $PR_NUMBER --json files --jq '.files[].path')
43-
44-
echo "----------------------------------------"
45-
echo "Changed files:"
46-
echo "$CHANGED_FILES" | tr ' ' '\n' | sed 's/^/- /'
47-
echo "----------------------------------------"
48-
49-
# Get existing reviewers
50-
# merge requested teams and users into a single array
51-
REQUESTED_REVIEWERS=$(gh pr view $PR_NUMBER --json reviewRequests --jq '[.reviewRequests[] | if .__typename == "Team" then .slug else .login end]')
52-
echo "Requested reviewers:"
53-
echo "$REQUESTED_REVIEWERS" | tr ' ' '\n' | sed 's/^/- /'
54-
echo "----------------------------------------"
55-
56-
# Parse CODEOWNERS and find commented lines
57-
# Add newline to the end of the file if it doesn't have one, otherwise sed will not read the last line
58-
sed -i -e '$a\' $codeowner_path
59-
60-
while read -r LINE; do
61-
# Skip lines that are not commented, GitHub will take care of un-commented lines
62-
if [[ ! "$LINE" =~ ^# ]]; then continue; fi
63-
64-
# Extract pattern and reviewer from the commented line
65-
PATTERN=$(echo "$LINE" | sed -E 's/^#\s*([^@]+).*$/\1/' | xargs)
66-
# Capture both individual users and GitHub teams reviewers that have "/" in the name
67-
REVIEWERS=$(echo "$LINE" | grep -o "@[a-zA-Z0-9_-]\+\(/[a-zA-Z0-9_-]\+\)\?" | tr '\n' ' ' | xargs)
68-
69-
# Skip if no reviewers found
70-
if [[ -z "$REVIEWERS" ]]; then
71-
continue
72-
fi
66+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
67+
with:
68+
ref: ${{ steps.base.outputs.sha }}
69+
persist-credentials: false
7370

74-
# Convert pattern to a regex for matching
75-
REGEX_PATTERN=$(echo "$PATTERN" | sed -e 's/\./\\./g' -e 's/\*/.*/g' -e 's/\?/./g' -e 's|^/||')
71+
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v4
72+
with:
73+
node-version-file: package.json
7674

77-
# Match changed files to the pattern
78-
for FILE in $CHANGED_FILES; do
79-
# For glob patterns(e.g. "**/"), use a different matching approach
80-
if [[ "$PATTERN" == *"*"* ]]; then
81-
# Special handling for **/ pattern
82-
if [[ "$PATTERN" == "**/"* ]]; then
83-
# Get the filename part after **/
84-
FILENAME=${PATTERN#**/}
85-
# Match either the filename directly or with any path prefix
86-
if [[ "$FILE" == "$FILENAME" ]] || [[ "$FILE" == */"$FILENAME" ]]; then
87-
echo "File $FILE matches glob pattern $PATTERN"
88-
# Assign each reviewer
89-
for REVIEWER in $REVIEWERS; do
90-
# Remove @ symbol from reviewer name
91-
REVIEWER_NAME=${REVIEWER#@}
92-
if [[ "$REQUESTED_REVIEWERS" == *"$REVIEWER_NAME"* ]]; then
93-
echo " - $REVIEWER_NAME is already a requested reviewer, skipping"
94-
else
95-
echo " - Assigning $REVIEWER_NAME to review changes in $FILE"
96-
gh pr edit $PR_NUMBER --add-reviewer "$REVIEWER_NAME"
97-
fi
98-
done
99-
fi
100-
else
101-
# Convert other glob patterns to regex for matching
102-
GLOB_PATTERN=$(echo "$PATTERN" | sed -e 's/\./\\./g' -e 's/\*/.*/g' -e 's/\?/./g')
103-
if [[ "$FILE" =~ $GLOB_PATTERN ]]; then
104-
echo "File $FILE matches glob pattern $PATTERN"
105-
# Assign each reviewer
106-
for REVIEWER in $REVIEWERS; do
107-
# Remove @ symbol from reviewer name
108-
REVIEWER_NAME=${REVIEWER#@}
109-
if [[ "$REQUESTED_REVIEWERS" == *"$REVIEWER_NAME"* ]]; then
110-
echo " - $REVIEWER_NAME is already a requested reviewer, skipping"
111-
else
112-
echo " - Assigning $REVIEWER_NAME to review changes in $FILE"
113-
gh pr edit $PR_NUMBER --add-reviewer "$REVIEWER_NAME"
114-
fi
115-
done
116-
fi
117-
fi
118-
else
119-
# Original directory matching logic
120-
if [[ "$FILE" == ${REGEX_PATTERN}* ]]; then
121-
echo "File $FILE matches pattern $PATTERN"
122-
# Assign each reviewer
123-
for REVIEWER in $REVIEWERS; do
124-
# Remove @ symbol from reviewer name
125-
REVIEWER_NAME=${REVIEWER#@}
126-
if [[ "$REQUESTED_REVIEWERS" == *"$REVIEWER_NAME"* ]]; then
127-
echo " - $REVIEWER_NAME is already a requested reviewer, skipping"
128-
else
129-
echo " - Assigning $REVIEWER_NAME to review changes in $FILE"
130-
gh pr edit $PR_NUMBER --add-reviewer "$REVIEWER_NAME"
131-
fi
132-
done
133-
fi
134-
fi
135-
done
136-
done < $codeowner_path
75+
- name: Evaluate CODEOWNERS and assign reviewers
76+
env:
77+
PR_NUMBER: ${{ github.event.pull_request.number || inputs.pr_number }}
78+
REPOSITORY: ${{ github.repository }}
79+
EVENT_ACTION: ${{ github.event.action || 'workflow_dispatch' }}
80+
DRY_RUN: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || false }}
81+
GH_TOKEN: ${{ steps.token.outputs.token }}
82+
run: |
83+
args=()
84+
if [[ "$DRY_RUN" == "true" ]]; then
85+
args+=(--dry-run)
86+
fi
87+
node scripts/assign-pr-reviewers.mjs "${args[@]}"

0 commit comments

Comments
 (0)