-
Notifications
You must be signed in to change notification settings - Fork 16
103 lines (90 loc) · 3.47 KB
/
pr-size.yml
File metadata and controls
103 lines (90 loc) · 3.47 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
name: PR Size Check and Label
# Uses pull_request_target so it works on fork PRs (write access to labels).
# Safe because this workflow only reads PR metadata — it never checks out untrusted code.
on:
pull_request_target:
branches: [main]
jobs:
label-size:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Calculate PR size and apply label
uses: actions/github-script@v8
with:
script: |
const prNumber = context.payload.pull_request.number;
const { owner, repo } = context.repo;
// Fetch file-level stats so we can exclude generated/lock files
const files = await github.paginate(github.rest.pulls.listFiles, {
owner,
repo,
pull_number: prNumber,
per_page: 100
});
const EXCLUDED = [
/package-lock\.json$/,
/yarn\.lock$/,
/pnpm-lock\.yaml$/,
/\.snap$/
];
let additions = 0;
let deletions = 0;
for (const file of files) {
if (EXCLUDED.some(re => re.test(file.filename))) continue;
additions += file.additions;
deletions += file.deletions;
}
const totalChanges = additions + deletions;
// Remove existing size labels (catch 404 in case of race)
const labels = await github.rest.issues.listLabelsOnIssue({
owner, repo, issue_number: prNumber
});
for (const label of labels.data) {
if (label.name.startsWith('size/')) {
try {
await github.rest.issues.removeLabel({
owner, repo, issue_number: prNumber, name: label.name
});
} catch (e) {
if (e.status !== 404) throw e;
}
}
}
// Determine size label
let sizeLabel;
if (totalChanges <= 20) sizeLabel = 'size/xs';
else if (totalChanges <= 100) sizeLabel = 'size/s';
else if (totalChanges <= 500) sizeLabel = 'size/m';
else if (totalChanges <= 1000) sizeLabel = 'size/l';
else sizeLabel = 'size/xl';
// Ensure the label exists before applying it
const LABEL_COLORS = {
'size/xs': '3CBF00',
'size/s': '5D9801',
'size/m': 'FBCA04',
'size/l': 'E67409',
'size/xl': 'D93F0B'
};
try {
await github.rest.issues.getLabel({ owner, repo, name: sizeLabel });
} catch (e) {
if (e.status === 404) {
await github.rest.issues.createLabel({
owner, repo,
name: sizeLabel,
color: LABEL_COLORS[sizeLabel],
description: `PR size: ${sizeLabel.split('/')[1].toUpperCase()}`
});
} else {
throw e;
}
}
await github.rest.issues.addLabels({
owner, repo, issue_number: prNumber, labels: [sizeLabel]
});
core.info(`PR has ${totalChanges} changed lines (excluding lockfiles/snapshots) → ${sizeLabel}`);
if (sizeLabel === 'size/xl') {
core.warning(`PR is large (${totalChanges} lines). Consider splitting into smaller PRs.`);
}