-
-
Notifications
You must be signed in to change notification settings - Fork 153
Expand file tree
/
Copy pathaction.yml
More file actions
214 lines (193 loc) · 7.03 KB
/
action.yml
File metadata and controls
214 lines (193 loc) · 7.03 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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
name: 'PR Size Labeler'
description: 'Label PRs based on the number of lines changed'
inputs:
xs_label:
description: 'Label for extra small PRs'
required: false
default: 'size/xs'
xs_max_size:
description: 'Maximum number of lines changed for XS'
required: false
default: '10'
s_label:
description: 'Label for small PRs'
required: false
default: 'size/s'
s_max_size:
description: 'Maximum number of lines changed for S'
required: false
default: '100'
m_label:
description: 'Label for medium PRs'
required: false
default: 'size/m'
m_max_size:
description: 'Maximum number of lines changed for M'
required: false
default: '500'
l_label:
description: 'Label for large PRs'
required: false
default: 'size/l'
l_max_size:
description: 'Maximum number of lines changed for L'
required: false
default: '1000'
xl_label:
description: 'Label for extra large PRs'
required: false
default: 'size/xl'
xl_max_size:
description: 'Maximum number of lines changed for XL'
required: false
default: '10000'
xxl_label:
description: 'Label for extra extra large PRs'
required: false
default: 'size/xxl'
fail_if_xl:
description: 'Fail the action if the PR is XL'
required: false
default: 'false'
fail_if_xxl:
description: 'Fail the action if the PR is XXL'
required: false
default: 'false'
files_to_ignore:
description: 'Files to ignore (newline or space separated)'
required: false
default: ''
ignore_line_deletions:
description: 'Ignore line deletions when calculating size'
required: false
default: 'false'
ignore_file_deletions:
description: 'Ignore file deletions when calculating size'
required: false
default: 'false'
runs:
using: 'composite'
steps:
- name: Label PR based on size
uses: actions/github-script@v8
with:
github-token: ${{ github.token }}
script: |
const prNumber = context.issue.number;
const owner = context.repo.owner;
const repo = context.repo.repo;
// Get configuration values
const xs_label = '${{ inputs.xs_label }}';
const xs_max_size = parseInt('${{ inputs.xs_max_size }}');
const s_label = '${{ inputs.s_label }}';
const s_max_size = parseInt('${{ inputs.s_max_size }}');
const m_label = '${{ inputs.m_label }}';
const m_max_size = parseInt('${{ inputs.m_max_size }}');
const l_label = '${{ inputs.l_label }}';
const l_max_size = parseInt('${{ inputs.l_max_size }}');
const xl_label = '${{ inputs.xl_label }}';
const xl_max_size = parseInt('${{ inputs.xl_max_size }}');
const xxl_label = '${{ inputs.xxl_label }}';
const fail_if_xl = '${{ inputs.fail_if_xl }}' === 'true';
const fail_if_xxl = '${{ inputs.fail_if_xxl }}' === 'true';
const ignore_line_deletions = '${{ inputs.ignore_line_deletions }}' === 'true';
const ignore_file_deletions = '${{ inputs.ignore_file_deletions }}' === 'true';
// Parse files to ignore
const files_to_ignore = `${{ inputs.files_to_ignore }}`.split(/[\s\n]+/).filter(f => f);
// Get all PR files using pagination
const files = await github.paginate(github.rest.pulls.listFiles, {
owner,
repo,
pull_number: prNumber,
per_page: 100
});
console.log(`Processing ${files.length} files in PR`);
// Calculate total changes
let totalChanges = 0;
for (const file of files) {
// Check if file should be ignored
const filename = file.filename;
let shouldIgnore = false;
for (const pattern of files_to_ignore) {
// Simple pattern matching (could be enhanced with glob patterns)
if (filename === pattern || filename.endsWith(pattern)) {
shouldIgnore = true;
break;
}
}
if (shouldIgnore) {
console.log(`Ignoring file: ${filename}`);
continue;
}
// Check if file was deleted and should be ignored
if (ignore_file_deletions && file.status === 'removed') {
console.log(`Ignoring deleted file: ${filename}`);
continue;
}
// Calculate changes for this file
let fileChanges = file.additions;
if (!ignore_line_deletions) {
fileChanges += file.deletions;
}
totalChanges += fileChanges;
}
console.log(`Total changes: ${totalChanges}`);
// Determine the appropriate label
let newLabel;
if (totalChanges <= xs_max_size) {
newLabel = xs_label;
} else if (totalChanges <= s_max_size) {
newLabel = s_label;
} else if (totalChanges <= m_max_size) {
newLabel = m_label;
} else if (totalChanges <= l_max_size) {
newLabel = l_label;
} else if (totalChanges <= xl_max_size) {
newLabel = xl_label;
} else {
newLabel = xxl_label;
}
console.log(`Assigning label: ${newLabel}`);
// Get all size labels
const allSizeLabels = [xs_label, s_label, m_label, l_label, xl_label, xxl_label];
// Get current labels on the PR
const { data: currentLabels } = await github.rest.issues.listLabelsOnIssue({
owner,
repo,
issue_number: prNumber
});
const currentLabelNames = currentLabels.map(l => l.name);
// Remove old size labels
for (const label of allSizeLabels) {
if (label !== newLabel && currentLabelNames.includes(label)) {
console.log(`Removing label: ${label}`);
try {
await github.rest.issues.removeLabel({
owner,
repo,
issue_number: prNumber,
name: label
});
} catch (error) {
console.log(`Failed to remove label ${label}: ${error.message}`);
}
}
}
// Add the new label
if (!currentLabelNames.includes(newLabel)) {
console.log(`Adding label: ${newLabel}`);
await github.rest.issues.addLabels({
owner,
repo,
issue_number: prNumber,
labels: [newLabel]
});
}
// Fail if XL and configured to do so
if (newLabel === xl_label && fail_if_xl) {
core.setFailed(`PR is too large (${totalChanges} changes). Please consider breaking it up into smaller PRs.`);
}
// Fail if XXL and configured to do so
if (newLabel === xxl_label && fail_if_xxl) {
core.setFailed(`PR is too large (${totalChanges} changes). Please consider breaking it up into smaller PRs.`);
}