diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 633b8a0166d..658c5eb6ee8 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -197,6 +197,12 @@ jobs: pnpm-lock.yaml mobile/pnpm-lock.yaml + - name: Set up Bun for localization checks + if: needs.code_paths.outputs.static_analysis == 'true' + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 + with: + bun-version-file: config/bun-version + # Keep each check in its own log while sharing this runner. - name: Lint if: '!cancelled()' diff --git a/config/scripts/pr-preflight-gates.test.mjs b/config/scripts/pr-preflight-gates.test.mjs index 7ba8a881d8f..37b2b923081 100644 --- a/config/scripts/pr-preflight-gates.test.mjs +++ b/config/scripts/pr-preflight-gates.test.mjs @@ -183,6 +183,7 @@ it('pins every foreground and background step to its selected phase', () => { (step) => !step.background && /outputs\.(static_analysis|typecheck)/.test(step.if ?? '') ) expect(foreground.map((step) => [step.name ?? step.run ?? step.uses, step.if])).toEqual([ + ['Set up Bun for localization checks', staticPhase], ['Reject low-evidence patterns', staticPhase], ['Enforce type-aware code-quality baseline', staticPhase], [ diff --git a/config/scripts/verify-localization-catalogs.test.mjs b/config/scripts/verify-localization-catalogs.test.mjs index 038bf34254e..d83eaf1dcff 100644 --- a/config/scripts/verify-localization-catalogs.test.mjs +++ b/config/scripts/verify-localization-catalogs.test.mjs @@ -1,7 +1,8 @@ import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' -import { join } from 'node:path' +import { join, resolve } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' +import { runProcessSync } from './script-child-process.mjs' import { main as verifyTogether } from './verify-localization-catalogs.mjs' import { main as verifyCatalog } from './verify-localization-catalog.mjs' import { main as verifyRuntimeCatalog } from './generate-runtime-required-english-catalog.mjs' @@ -31,6 +32,38 @@ afterEach(async () => { }) describe('combined localization verification', () => { + it.each([ + ['valid catalogs', undefined, undefined, 0], + ['missing reference', `${renderer}/greeting.ts`, "translate('missing', 'Missing')", 1], + ['missing runtime entry', runtimePath, '{}', 1] + ])( + 'runs the real CLI with the same Node and Bun verdict: %s', + async (_name, file, contents, code) => { + const root = await fixture() + if (file) { + await writeFile(join(root, file), contents) + } + const results = [] + for (const program of [process.execPath, 'bun']) { + const result = runProcessSync({ + program, + args: [resolve(import.meta.dirname, 'verify-localization-catalogs.mjs')], + cwd: root, + env: { ...process.env, ORCA_BACKGROUND_LAUNCH: '1' }, + timeoutMs: 10000 + }) + expect(result.code, result.stderr).toBe(code) + expect(result.timedOut).toBe(false) + results.push({ stdout: result.stdout, stderr: result.stderr }) + } + expect(results[1].stdout.split('\n').sort()).toEqual(results[0].stdout.split('\n').sort()) + expect(results[1].stderr.split('\n').sort()).toEqual(results[0].stderr.split('\n').sort()) + expect(`${results[0].stdout}${results[0].stderr}`).toContain( + code === 0 ? 'Verified 2 localization key references' : 'Run `pnpm run sync:localization' + ) + } + ) + it.each([ ['valid catalogs', undefined, undefined, 0, 0], ['missing reference', `${renderer}/greeting.ts`, "translate('missing', 'Missing')", 1, 1], diff --git a/package.json b/package.json index 3a9c39ca92f..87db822a98f 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,7 @@ "verify:cli-bin": "node config/scripts/verify-cli-bin.mjs", "verify:built-skills-cli": "node config/scripts/verify-skills-cli-runtime.cjs out", "verify:renderer-boot-graph": "node config/scripts/verify-renderer-boot-graph.mjs", - "verify:localization-catalogs": "node config/scripts/verify-localization-catalogs.mjs", + "verify:localization-catalogs": "bun config/scripts/verify-localization-catalogs.mjs", "verify:localization-catalog": "node config/scripts/verify-localization-catalog.mjs", "sync:localization-catalog": "node config/scripts/verify-localization-catalog.mjs --fix", "verify:localization-runtime-catalog": "node config/scripts/generate-runtime-required-english-catalog.mjs",