@@ -24,32 +24,32 @@ jobs:
2424 {
2525 name: "size:XS",
2626 color: "0e8a16",
27- description: "0-9 changed lines (additions + deletions ).",
27+ description: "0-9 effective changed lines (test files excluded in mixed PRs ).",
2828 },
2929 {
3030 name: "size:S",
3131 color: "5ebd3e",
32- description: "10-29 changed lines (additions + deletions ).",
32+ description: "10-29 effective changed lines (test files excluded in mixed PRs ).",
3333 },
3434 {
3535 name: "size:M",
3636 color: "fbca04",
37- description: "30-99 changed lines (additions + deletions ).",
37+ description: "30-99 effective changed lines (test files excluded in mixed PRs ).",
3838 },
3939 {
4040 name: "size:L",
4141 color: "fe7d37",
42- description: "100-499 changed lines (additions + deletions ).",
42+ description: "100-499 effective changed lines (test files excluded in mixed PRs ).",
4343 },
4444 {
4545 name: "size:XL",
4646 color: "d93f0b",
47- description: "500-999 changed lines (additions + deletions ).",
47+ description: "500-999 effective changed lines (test files excluded in mixed PRs ).",
4848 },
4949 {
5050 name: "size:XXL",
5151 color: "b60205",
52- description: "1,000+ changed lines (additions + deletions ).",
52+ description: "1,000+ effective changed lines (test files excluded in mixed PRs ).",
5353 },
5454 ];
5555
@@ -131,12 +131,18 @@ jobs:
131131 with :
132132 script : |
133133 const issueNumber = context.payload.pull_request.number;
134- const additions = context.payload.pull_request.additions ?? 0;
135- const deletions = context.payload.pull_request.deletions ?? 0;
136- const changedLines = additions + deletions;
137134 const managedLabels = JSON.parse(process.env.PR_SIZE_LABELS_JSON ?? "[]");
138-
139135 const managedLabelNames = new Set(managedLabels.map((label) => label.name));
136+ // Keep this aligned with the repo's test entrypoints and test-only support files.
137+ const testFilePatterns = [
138+ /(^|\/)__tests__(\/|$)/,
139+ /(^|\/)tests?(\/|$)/,
140+ /^apps\/server\/integration\//,
141+ /\.(test|spec|browser|integration)\.[^.\/]+$/,
142+ ];
143+
144+ const isTestFile = (filename) =>
145+ testFilePatterns.some((pattern) => pattern.test(filename));
140146
141147 const resolveSizeLabel = (totalChangedLines) => {
142148 if (totalChangedLines < 10) {
@@ -162,6 +168,42 @@ jobs:
162168 return "size:XXL";
163169 };
164170
171+ const files = await github.paginate(
172+ github.rest.pulls.listFiles,
173+ {
174+ owner: context.repo.owner,
175+ repo: context.repo.repo,
176+ pull_number: issueNumber,
177+ per_page: 100,
178+ },
179+ (response) => response.data,
180+ );
181+
182+ if (files.length >= 3000) {
183+ core.warning(
184+ "The GitHub pull request files API may truncate results at 3,000 files; PR size may be undercounted.",
185+ );
186+ }
187+
188+ let testChangedLines = 0;
189+ let nonTestChangedLines = 0;
190+
191+ for (const file of files) {
192+ const changedLinesForFile = (file.additions ?? 0) + (file.deletions ?? 0);
193+
194+ if (changedLinesForFile === 0) {
195+ continue;
196+ }
197+
198+ if (isTestFile(file.filename)) {
199+ testChangedLines += changedLinesForFile;
200+ continue;
201+ }
202+
203+ nonTestChangedLines += changedLinesForFile;
204+ }
205+
206+ const changedLines = nonTestChangedLines === 0 ? testChangedLines : nonTestChangedLines;
165207 const nextLabelName = resolveSizeLabel(changedLines);
166208
167209 const { data: currentLabels } = await github.rest.issues.listLabelsOnIssue({
@@ -199,4 +241,15 @@ jobs:
199241 });
200242 }
201243
202- core.info(`PR #${issueNumber}: ${changedLines} changed lines -> ${nextLabelName}`);
244+ const classification =
245+ nonTestChangedLines === 0
246+ ? testChangedLines > 0
247+ ? "test-only PR"
248+ : "no line changes"
249+ : testChangedLines > 0
250+ ? "test lines excluded"
251+ : "all non-test changes";
252+
253+ core.info(
254+ `PR #${issueNumber}: ${nonTestChangedLines} non-test lines, ${testChangedLines} test lines, ${changedLines} effective lines -> ${nextLabelName} (${classification})`,
255+ );
0 commit comments