Skip to content

Commit 9a87a66

Browse files
mydeaclaude
andcommitted
ci: Fail when a Playwright version drifts from the pinned one
All packages and E2E apps must declare the exact `@playwright/test` version of `@sentry-internal/test-utils`. The check runs in the Lint job. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 7d04f91 commit 9a87a66

2 files changed

Lines changed: 57 additions & 0 deletions

File tree

‎.github/workflows/build.yml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,8 @@ jobs:
346346
run: yarn lint:es-compatibility
347347
- name: Lint types
348348
run: yarn lint:types
349+
- name: Check Playwright versions
350+
run: node ./scripts/check-playwright-versions.mjs
349351

350352
job_check_lockfile:
351353
name: Check lockfile
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/* eslint-disable no-console */
2+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
3+
import { join } from 'node:path';
4+
5+
// Every package, including each E2E app, must use this exact version.
6+
// `install-playwright` installs browsers for the declared version, so a drifting app would test against other browsers.
7+
const REFERENCE_PACKAGE_JSON = 'dev-packages/test-utils/package.json';
8+
const PLAYWRIGHT_PACKAGES = ['@playwright/test', 'playwright', 'playwright-core'];
9+
const DEPENDENCY_FIELDS = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
10+
const PACKAGE_DIRS = ['packages', 'dev-packages', 'dev-packages/e2e-tests/test-applications'];
11+
12+
const rootDir = join(import.meta.dirname, '..');
13+
14+
/** @param {string} path */
15+
function readPackageJson(path) {
16+
return JSON.parse(readFileSync(join(rootDir, path), 'utf8'));
17+
}
18+
19+
const expected = readPackageJson(REFERENCE_PACKAGE_JSON).devDependencies['@playwright/test'];
20+
21+
if (!/^\d+\.\d+\.\d+$/.test(expected)) {
22+
console.error(`@playwright/test in ${REFERENCE_PACKAGE_JSON} must be an exact version, got "${expected}".`);
23+
process.exit(1);
24+
}
25+
26+
const packageJsonPaths = ['package.json'];
27+
for (const dir of PACKAGE_DIRS) {
28+
for (const entry of readdirSync(join(rootDir, dir), { withFileTypes: true })) {
29+
const path = join(dir, entry.name, 'package.json');
30+
if (entry.isDirectory() && existsSync(join(rootDir, path))) {
31+
packageJsonPaths.push(path);
32+
}
33+
}
34+
}
35+
36+
const mismatches = [];
37+
for (const path of packageJsonPaths) {
38+
const packageJson = readPackageJson(path);
39+
for (const field of DEPENDENCY_FIELDS) {
40+
for (const name of PLAYWRIGHT_PACKAGES) {
41+
const version = packageJson[field]?.[name];
42+
if (version !== undefined && version !== expected) {
43+
mismatches.push(` ${path}: ${field}["${name}"] is "${version}"`);
44+
}
45+
}
46+
}
47+
}
48+
49+
if (mismatches.length) {
50+
console.error(`All Playwright dependencies must be pinned to "${expected}" (from ${REFERENCE_PACKAGE_JSON}):`);
51+
console.error(mismatches.join('\n'));
52+
process.exit(1);
53+
}
54+
55+
console.log(`All Playwright dependencies are pinned to ${expected}.`);

0 commit comments

Comments
 (0)