Skip to content

Commit a23f212

Browse files
committed
fix(ci): raise the python floor to 3.12 and stop the bridge audit serializing the batch
Two review findings, both real. MIN_PYTHON was 3.10, chosen for the `match` statements the compiler suite generates. But two of the three guarded tests also use PEP 701 f-strings -- reusing the outer quote, and embedding `#` -- which are 3.12. Verified on a real 3.11 interpreter: the match-guard test passes, the other two fail with `f-string: unmatched '('` and `f-string expression part cannot include '#'`, which is exactly the raw SyntaxError the guard exists to prevent. A 3.10 floor let them through and failed anyway. The audit parallelization did not speed CI up -- it slowed it down. Serially the 21 audits took ~31s; concurrently the batch took 39.2s wall, because check:desktop-bridge went from 1s to 39.2s and became the entire wall clock while the other 20 finished in 9s. It is the only audit that shells out through `bunx`, which re-resolves the package against the shared install cache -- a network-backed sticky-disk mount on CI. Cheap when it runs alone, serialized behind the others when they run together. Spawning the resolved compiler entry point directly removes that layer. Verified the audit still fails on a breaking bridge change rather than passing faster by doing less.
1 parent bbde273 commit a23f212

2 files changed

Lines changed: 24 additions & 4 deletions

File tree

packages/testing/src/environment/index.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,18 @@
1313
*/
1414
import { spawnSync } from 'node:child_process'
1515

16-
/** Python 3.10 is the floor: the compiler suite generates `match` statements. */
17-
export const MIN_PYTHON: readonly [number, number] = [3, 10]
16+
/**
17+
* Python 3.12 is the floor, set by PEP 701 f-strings rather than by `match` statements.
18+
*
19+
* The compiler suite generates `match` (3.10) but also f-strings that reuse the outer quote
20+
* and embed `#`. On 3.11 those raise `f-string: unmatched '('` and `f-string expression part
21+
* cannot include '#'` — exactly the raw SyntaxError this guard exists to prevent — so a 3.10
22+
* floor would have let two of the three guarded tests through and failed anyway.
23+
*/
24+
export const MIN_PYTHON: readonly [number, number] = [3, 12]
1825

1926
/** Reasons to pass to vitest's `ctx.skip(...)` so the report says why, not just that. */
20-
export const PYTHON_SKIP_REASON = 'needs python3 >= 3.10; macOS ships 3.9'
27+
export const PYTHON_SKIP_REASON = 'needs python3 >= 3.12 (PEP 701 f-strings); macOS ships 3.9'
2128
export const RIPGREP_SKIP_REASON = 'needs ripgrep (`rg`) on PATH'
2229

2330
const warned = new Set<string>()

scripts/check-desktop-bridge-contract.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,21 @@
3131
import { spawnSync } from 'node:child_process'
3232
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'
3333
import { readFile, writeFile } from 'node:fs/promises'
34+
import { createRequire } from 'node:module'
3435
import { tmpdir } from 'node:os'
3536
import { dirname, join, resolve } from 'node:path'
3637
import { fileURLToPath } from 'node:url'
3738
import { formatGeneratedSource } from './format-generated-source'
3839

3940
const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url))
4041
const ROOT = resolve(SCRIPT_DIR, '..')
42+
43+
/** The native TypeScript 7 compiler entry point, resolved once. */
44+
const TSC_ENTRY = join(
45+
dirname(createRequire(import.meta.url).resolve('typescript/package.json')),
46+
'bin',
47+
'tsc'
48+
)
4149
const BRIDGE_SOURCE_PATH = resolve(ROOT, 'packages/desktop-bridge/src/index.ts')
4250
const PROTOCOL_SOURCE_PATH = resolve(ROOT, 'packages/browser-protocol/src/index.ts')
4351
const TERMINAL_PROTOCOL_SOURCE_PATH = resolve(ROOT, 'packages/terminal-protocol/src/index.ts')
@@ -173,7 +181,12 @@ function checkCompatibility(): { compatible: boolean; output: string } {
173181
try {
174182
writeFileSync(join(dir, 'compat.ts'), compatSource)
175183
writeFileSync(join(dir, 'tsconfig.json'), JSON.stringify(tsconfig, null, 2))
176-
const result = spawnSync('bunx', ['tsc', '-p', dir, '--pretty', 'false'], {
184+
// Spawned as a resolved module path rather than via `bunx`. `bunx` re-resolves the
185+
// package on every call against the shared install cache, which on CI is a network-backed
186+
// sticky-disk mount — cheap when this audit runs alone, but it serialized behind the
187+
// other audits once they started running concurrently and took this step from 1s to 39s,
188+
// making it the entire wall clock of the batch.
189+
const result = spawnSync(process.execPath, [TSC_ENTRY, '-p', dir, '--pretty', 'false'], {
177190
cwd: ROOT,
178191
encoding: 'utf8',
179192
})

0 commit comments

Comments
 (0)