Skip to content

Commit fe59754

Browse files
authored
Merge branch 'main' into review_model
2 parents 6264bf5 + 7e2a5e7 commit fe59754

File tree

4 files changed

+258
-134
lines changed

4 files changed

+258
-134
lines changed
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
name: PR Size Enforcement - Apply
2+
3+
on:
4+
workflow_run:
5+
workflows: ["PR Size Enforcement - Check"]
6+
types: [completed]
7+
8+
permissions:
9+
contents: read
10+
pull-requests: write
11+
12+
jobs:
13+
apply-xl-enforcement:
14+
name: Apply XL PR Enforcement
15+
runs-on: ubuntu-latest
16+
if: github.event.workflow_run.conclusion == 'success'
17+
steps:
18+
- name: Checkout repository
19+
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
20+
21+
- name: Download artifact
22+
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
23+
with:
24+
name: pr-enforcement-result
25+
path: pr-enforcement/
26+
github-token: ${{ secrets.GITHUB_TOKEN }}
27+
run-id: ${{ github.event.workflow_run.id }}
28+
29+
- name: Read enforcement result
30+
id: read
31+
run: |
32+
cat pr-enforcement/result.json
33+
echo "result=$(cat pr-enforcement/result.json)" >> $GITHUB_OUTPUT
34+
35+
- name: Request changes if no justification
36+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
37+
env:
38+
RESULT_JSON: ${{ steps.read.outputs.result }}
39+
with:
40+
script: |
41+
const result = JSON.parse(process.env.RESULT_JSON);
42+
43+
console.log('Enforcement result:', result);
44+
45+
if (!result.needsEnforcement) {
46+
console.log('No enforcement needed, skipping');
47+
return;
48+
}
49+
50+
const prNumber = result.prNumber;
51+
52+
// Check if we already have a review requesting changes
53+
const reviews = await github.rest.pulls.listReviews({
54+
owner: context.repo.owner,
55+
repo: context.repo.repo,
56+
pull_number: prNumber
57+
});
58+
59+
const botReview = reviews.data.find(review =>
60+
review.user.login === 'github-actions[bot]' &&
61+
review.state === 'CHANGES_REQUESTED'
62+
);
63+
64+
if (botReview) {
65+
console.log('Already requested changes in review:', botReview.id);
66+
return;
67+
}
68+
69+
// Read the message template from file
70+
const fs = require('fs');
71+
const template = fs.readFileSync('.github/workflows/pr-size-justification-template.md', 'utf8');
72+
const contributingLink = `https://github.com/${context.repo.owner}/${context.repo.repo}/blob/main/CONTRIBUTING.md#code-quality-expectations`;
73+
const message = template.replace('CONTRIBUTING_LINK', contributingLink);
74+
75+
// Request changes with explanation
76+
await github.rest.pulls.createReview({
77+
owner: context.repo.owner,
78+
repo: context.repo.repo,
79+
pull_number: prNumber,
80+
event: 'REQUEST_CHANGES',
81+
body: message
82+
});
83+
84+
console.log('Created review requesting changes for PR #' + prNumber);
85+
86+
- name: Dismiss review if justification added
87+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
88+
env:
89+
RESULT_JSON: ${{ steps.read.outputs.result }}
90+
with:
91+
script: |
92+
const result = JSON.parse(process.env.RESULT_JSON);
93+
94+
if (!result.shouldDismiss) {
95+
console.log('No dismissal needed, skipping');
96+
return;
97+
}
98+
99+
const prNumber = result.prNumber;
100+
101+
// Find our previous review requesting changes
102+
const reviews = await github.rest.pulls.listReviews({
103+
owner: context.repo.owner,
104+
repo: context.repo.repo,
105+
pull_number: prNumber
106+
});
107+
108+
const botReview = reviews.data.find(review =>
109+
review.user.login === 'github-actions[bot]' &&
110+
review.state === 'CHANGES_REQUESTED'
111+
);
112+
113+
if (botReview) {
114+
await github.rest.pulls.dismissReview({
115+
owner: context.repo.owner,
116+
repo: context.repo.repo,
117+
pull_number: prNumber,
118+
review_id: botReview.id,
119+
message: 'Large PR justification has been provided. Thank you!'
120+
});
121+
122+
console.log('Dismissed previous review:', botReview.id);
123+
124+
// Add a comment confirming unblock
125+
await github.rest.issues.createComment({
126+
owner: context.repo.owner,
127+
repo: context.repo.repo,
128+
issue_number: prNumber,
129+
body: '✅ Large PR justification has been provided. The size review has been dismissed and this PR can now proceed with normal review.'
130+
});
131+
} else {
132+
console.log('No previous blocking review found to dismiss');
133+
}
Lines changed: 34 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,115 +1,54 @@
1-
name: PR Size Enforcement
1+
name: PR Size Enforcement - Check
22

33
on:
44
pull_request:
55
types: [labeled, unlabeled, opened, edited, synchronize]
66

77
permissions:
88
contents: read
9-
pull-requests: write
109

1110
jobs:
12-
enforce-xl-justification:
13-
name: Enforce XL PR Justification
11+
check-xl-justification:
12+
name: Check XL PR Justification
1413
runs-on: ubuntu-latest
15-
if: contains(github.event.pull_request.labels.*.name, 'size/XL')
1614
steps:
17-
- name: Checkout repository
18-
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
19-
20-
- name: Check for justification
21-
id: check
22-
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
23-
with:
24-
script: |
25-
const prBody = context.payload.pull_request.body || '';
26-
27-
// Look for the justification section header
28-
const hasJustification = /##\s*Large PR Justification/i.test(prBody);
29-
30-
console.log('PR Body length:', prBody.length);
31-
console.log('Has justification section:', hasJustification);
32-
33-
return hasJustification;
34-
35-
- name: Request changes if no justification
36-
if: steps.check.outputs.result == 'false'
15+
- name: Get PR details
16+
id: pr
3717
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
3818
with:
3919
script: |
40-
const prNumber = context.payload.pull_request.number;
41-
42-
// Check if we already have a review requesting changes
43-
const reviews = await github.rest.pulls.listReviews({
44-
owner: context.repo.owner,
45-
repo: context.repo.repo,
46-
pull_number: prNumber
47-
});
48-
49-
const botReview = reviews.data.find(review =>
50-
review.user.login === 'github-actions[bot]' &&
51-
review.state === 'CHANGES_REQUESTED'
52-
);
53-
54-
if (botReview) {
55-
console.log('Already requested changes in review:', botReview.id);
56-
return;
57-
}
58-
59-
// Read the message template from file
60-
const fs = require('fs');
61-
const template = fs.readFileSync('.github/workflows/pr-size-justification-template.md', 'utf8');
62-
const contributingLink = `https://github.com/${context.repo.owner}/${context.repo.repo}/blob/main/CONTRIBUTING.md#code-quality-expectations`;
63-
const message = template.replace('CONTRIBUTING_LINK', contributingLink);
64-
65-
// Request changes with explanation
66-
await github.rest.pulls.createReview({
20+
const pr = await github.rest.pulls.get({
6721
owner: context.repo.owner,
6822
repo: context.repo.repo,
69-
pull_number: prNumber,
70-
event: 'REQUEST_CHANGES',
71-
body: message
23+
pull_number: context.issue.number
7224
});
7325
74-
console.log('Created review requesting changes');
26+
const labels = pr.data.labels.map(l => l.name);
27+
const hasXLLabel = labels.includes('size/XL');
28+
const prBody = pr.data.body || '';
29+
const hasJustification = /##\s*Large PR Justification/i.test(prBody);
7530
76-
- name: Dismiss review if justification added
77-
if: steps.check.outputs.result == 'true'
78-
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
31+
console.log('PR Number:', context.issue.number);
32+
console.log('Has XL label:', hasXLLabel);
33+
console.log('Has justification:', hasJustification);
34+
35+
return {
36+
prNumber: context.issue.number,
37+
hasXLLabel: hasXLLabel,
38+
hasJustification: hasJustification,
39+
needsEnforcement: hasXLLabel && !hasJustification,
40+
shouldDismiss: hasXLLabel && hasJustification
41+
};
42+
43+
- name: Save enforcement result to artifact
44+
run: |
45+
mkdir -p pr-enforcement
46+
echo '${{ steps.pr.outputs.result }}' > pr-enforcement/result.json
47+
cat pr-enforcement/result.json
48+
49+
- name: Upload artifact
50+
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4
7951
with:
80-
script: |
81-
const prNumber = context.payload.pull_request.number;
82-
83-
// Find our previous review requesting changes
84-
const reviews = await github.rest.pulls.listReviews({
85-
owner: context.repo.owner,
86-
repo: context.repo.repo,
87-
pull_number: prNumber
88-
});
89-
90-
const botReview = reviews.data.find(review =>
91-
review.user.login === 'github-actions[bot]' &&
92-
review.state === 'CHANGES_REQUESTED'
93-
);
94-
95-
if (botReview) {
96-
await github.rest.pulls.dismissReview({
97-
owner: context.repo.owner,
98-
repo: context.repo.repo,
99-
pull_number: prNumber,
100-
review_id: botReview.id,
101-
message: 'Large PR justification has been provided. Thank you!'
102-
});
103-
104-
console.log('Dismissed previous review:', botReview.id);
105-
106-
// Add a comment confirming unblock
107-
await github.rest.issues.createComment({
108-
owner: context.repo.owner,
109-
repo: context.repo.repo,
110-
issue_number: prNumber,
111-
body: '✅ Large PR justification has been provided. The size review has been dismissed and this PR can now proceed with normal review.'
112-
});
113-
} else {
114-
console.log('No previous blocking review found');
115-
}
52+
name: pr-enforcement-result
53+
path: pr-enforcement/
54+
retention-days: 1
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: PR Size Labeler - Apply
2+
3+
on:
4+
workflow_run:
5+
workflows: ["PR Size Labeler - Calculate"]
6+
types: [completed]
7+
8+
permissions:
9+
contents: read
10+
pull-requests: write
11+
12+
jobs:
13+
apply-size-label:
14+
name: Apply Size Label
15+
runs-on: ubuntu-latest
16+
if: github.event.workflow_run.conclusion == 'success'
17+
steps:
18+
- name: Download artifact
19+
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
20+
with:
21+
name: pr-size-label
22+
path: pr-size/
23+
github-token: ${{ secrets.GITHUB_TOKEN }}
24+
run-id: ${{ github.event.workflow_run.id }}
25+
26+
- name: Read PR number and size label
27+
id: read
28+
run: |
29+
PR_NUMBER=$(cat pr-size/pr-number.txt)
30+
SIZE_LABEL=$(cat pr-size/label.txt | tr -d '"')
31+
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
32+
echo "size_label=$SIZE_LABEL" >> $GITHUB_OUTPUT
33+
echo "PR #$PR_NUMBER should get label: $SIZE_LABEL"
34+
35+
- name: Remove old size labels
36+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
37+
env:
38+
PR_NUMBER: ${{ steps.read.outputs.pr_number }}
39+
with:
40+
script: |
41+
const prNumber = parseInt(process.env.PR_NUMBER);
42+
const sizeLabels = ['size/XS', 'size/S', 'size/M', 'size/L', 'size/XL'];
43+
44+
const currentLabels = await github.rest.issues.listLabelsOnIssue({
45+
owner: context.repo.owner,
46+
repo: context.repo.repo,
47+
issue_number: prNumber
48+
});
49+
50+
for (const label of currentLabels.data) {
51+
if (sizeLabels.includes(label.name)) {
52+
console.log(`Removing old size label: ${label.name}`);
53+
await github.rest.issues.removeLabel({
54+
owner: context.repo.owner,
55+
repo: context.repo.repo,
56+
issue_number: prNumber,
57+
name: label.name
58+
});
59+
}
60+
}
61+
62+
- name: Add new size label
63+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
64+
env:
65+
PR_NUMBER: ${{ steps.read.outputs.pr_number }}
66+
SIZE_LABEL: ${{ steps.read.outputs.size_label }}
67+
with:
68+
script: |
69+
const prNumber = parseInt(process.env.PR_NUMBER);
70+
const sizeLabel = process.env.SIZE_LABEL;
71+
72+
console.log(`Adding size label: ${sizeLabel} to PR #${prNumber}`);
73+
await github.rest.issues.addLabels({
74+
owner: context.repo.owner,
75+
repo: context.repo.repo,
76+
issue_number: prNumber,
77+
labels: [sizeLabel]
78+
});

0 commit comments

Comments
 (0)