Skip to content

Commit 52f56e7

Browse files
fix(ci): restore affected selection coverage
1 parent b5fe362 commit 52f56e7

File tree

2 files changed

+129
-2
lines changed

2 files changed

+129
-2
lines changed

tools/scripts/ci-is-affected.mjs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ import yargs from 'yargs';
55

66
const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
77
const ROOT = resolve(SCRIPT_DIR, '../..');
8+
const GLOBAL_E2E_INPUT_PATTERNS = [
9+
'package.json',
10+
'tools/scripts/ci-is-affected.mjs',
11+
'tools/scripts/e2e-process-utils.mjs',
12+
'tools/scripts/run-manifest-e2e.mjs',
13+
'tools/scripts/run-modern-e2e.mjs',
14+
'tools/scripts/run-metro-e2e.mjs',
15+
'tools/scripts/run-next-e2e.mjs',
16+
'tools/scripts/run-node-e2e.mjs',
17+
'tools/scripts/run-router-e2e.mjs',
18+
'tools/scripts/run-runtime-e2e.mjs',
19+
'scripts/ensure-playwright.js',
20+
];
821

922
const argv = yargs(process.argv.slice(2))
1023
.option('appName', {
@@ -47,6 +60,24 @@ if (base === head) {
4760
process.exit(0);
4861
}
4962

63+
const changedFiles = listChangedFiles(base, head);
64+
65+
if (!changedFiles) {
66+
console.warn(
67+
`Unable to resolve changed files for base=${base} head=${head}. Running e2e by default.`,
68+
);
69+
process.exit(0);
70+
}
71+
72+
const changedGlobalE2EInputs = changedFiles.filter(isGlobalE2EInput);
73+
74+
if (changedGlobalE2EInputs.length > 0) {
75+
console.log(
76+
`Detected shared e2e harness changes (${changedGlobalE2EInputs.join(', ')}). Running e2e CI.`,
77+
);
78+
process.exit(0);
79+
}
80+
5081
const turboResult = spawnSync(
5182
'pnpm',
5283
['exec', 'turbo', 'ls', '--affected', '--output=json'],
@@ -165,6 +196,36 @@ function resolveHead(requestedHead) {
165196
return null;
166197
}
167198

199+
function listChangedFiles(baseRef, headRef) {
200+
const result = spawnSync(
201+
'git',
202+
['diff', '--name-only', '--diff-filter=ACMR', baseRef, headRef],
203+
{
204+
cwd: ROOT,
205+
stdio: 'pipe',
206+
encoding: 'utf-8',
207+
maxBuffer: 1024 * 1024 * 8,
208+
},
209+
);
210+
211+
if (result.status !== 0) {
212+
return null;
213+
}
214+
215+
return result.stdout
216+
.split('\n')
217+
.map((entry) => entry.trim())
218+
.filter(Boolean);
219+
}
220+
221+
function isGlobalE2EInput(relativePath) {
222+
return GLOBAL_E2E_INPUT_PATTERNS.some(
223+
(pattern) =>
224+
relativePath === pattern ||
225+
(pattern.endsWith('/') && relativePath.startsWith(pattern)),
226+
);
227+
}
228+
168229
function expandRefCandidates(ref) {
169230
if (!ref || !ref.trim()) {
170231
return [];

tools/scripts/run-affected-package-tests.mjs

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/usr/bin/env node
22
import { spawnSync } from 'node:child_process';
3+
import { readFileSync } from 'node:fs';
34
import { dirname, resolve } from 'node:path';
45
import { fileURLToPath } from 'node:url';
56

@@ -77,8 +78,12 @@ function parseBaseArg(argv) {
7778
}
7879

7980
function resolveBaseRef(preferredRef) {
81+
const headCommit = resolveGitCommit('HEAD');
8082
if (hasGitRef(preferredRef)) {
81-
return preferredRef;
83+
const preferredCommit = resolveGitCommit(preferredRef);
84+
if (!headCommit || preferredCommit !== headCommit) {
85+
return preferredRef;
86+
}
8287
}
8388

8489
const refs = [];
@@ -96,9 +101,22 @@ function resolveBaseRef(preferredRef) {
96101

97102
for (const ref of refs) {
98103
if (hasGitRef(ref)) {
99-
return ref;
104+
const candidateCommit = resolveGitCommit(ref);
105+
if (!headCommit || candidateCommit !== headCommit) {
106+
return ref;
107+
}
108+
}
109+
}
110+
111+
for (const ref of getPreviousCommitCandidates()) {
112+
if (hasGitRef(ref)) {
113+
const candidateCommit = resolveGitCommit(ref);
114+
if (!headCommit || candidateCommit !== headCommit) {
115+
return ref;
116+
}
100117
}
101118
}
119+
102120
return null;
103121
}
104122

@@ -117,6 +135,28 @@ function hasGitRef(ref) {
117135
return result.status === 0;
118136
}
119137

138+
function resolveGitCommit(ref) {
139+
if (!ref) {
140+
return null;
141+
}
142+
143+
const result = spawnSync(
144+
'git',
145+
['rev-parse', '--verify', '--quiet', `${ref}^{commit}`],
146+
{
147+
cwd: ROOT,
148+
stdio: 'pipe',
149+
encoding: 'utf-8',
150+
},
151+
);
152+
153+
if (result.status !== 0) {
154+
return null;
155+
}
156+
157+
return result.stdout.trim() || null;
158+
}
159+
120160
function getChangedFiles(baseRef, headRef) {
121161
const result = spawnSync('git', ['diff', '--name-only', baseRef, headRef], {
122162
cwd: ROOT,
@@ -187,11 +227,37 @@ function isGlobalPackageTestImpactPath(changedFilePath) {
187227
changedFilePath === 'pnpm-workspace.yaml' ||
188228
changedFilePath === 'turbo.json' ||
189229
changedFilePath === 'tsconfig.base.json' ||
230+
changedFilePath.startsWith('scripts/') ||
231+
changedFilePath.startsWith('tools/scripts/') ||
190232
/^jest\.(?:preset|config)\.[cm]?[jt]s$/.test(changedFilePath) ||
191233
/^babel\.config\.(?:json|[cm]?[jt]s)$/.test(changedFilePath)
192234
);
193235
}
194236

237+
function getPreviousCommitCandidates() {
238+
const refs = new Set();
239+
240+
if (process.env.GITHUB_EVENT_BEFORE) {
241+
refs.add(process.env.GITHUB_EVENT_BEFORE);
242+
}
243+
244+
const eventPath = process.env.GITHUB_EVENT_PATH;
245+
if (eventPath) {
246+
try {
247+
const payload = JSON.parse(readFileSync(eventPath, 'utf-8'));
248+
if (typeof payload?.before === 'string' && payload.before) {
249+
refs.add(payload.before);
250+
}
251+
} catch {
252+
// Ignore invalid GitHub event payloads.
253+
}
254+
}
255+
256+
refs.add('HEAD~1');
257+
258+
return Array.from(refs);
259+
}
260+
195261
function getWorkspacePackages() {
196262
const result = spawnSync(
197263
'pnpm',

0 commit comments

Comments
 (0)