Skip to content

Commit f143cd8

Browse files
fix(console): keep the build-identity define out of the other ui test projects (#26197)
<!-- claude-projects-attribution: {"github_login":"os-steve"} --> _Requested by **Steve** · [project thread](https://claude.ai/code/project/chan_01FdL1XeUyvVNxLreh3F4Qi9?thread=cmsg_01FdL1XeUyvVNxLreh3F4Qi989Xx1AWqCMG6VmVHPtUXrt)_ Fixes #26126 Clause-②: no (build/test configuration only; no exported type or runtime contract change; the console production build keeps its version stamp) Metadata-protocol: none ## What changes `ui/apps/console/vitest.config.ts` now drops every `import.meta.env.*` / `process.env.*` key from the console Vite config's `define` before merging it into the console test project. `ui/apps/console/vite.config.ts` is untouched, so `vite build` still bakes `import.meta.env.VITE_APP_VERSION` (the build's `VITE_APP_VERSION`, else the git short sha) exactly as before. `buildIdentity-12970.test.ts` is unchanged; it stays the pin. ## Mechanism (measured, vitest 4.1.10 in `ui/node_modules`) 1. Vitest's `vitest:project` plugin runs `deleteDefineConfig` in each project's Vite `config` hook. That function writes every `import.meta.env.*` / `process.env.*` define into the **main process's** `process.env` and deletes it from the define. 2. `resolveProjects` initialises the projects concurrently (`limitConcurrency(availableParallelism)`), so the console project's config hook races the other projects' Vite config resolution. 3. A project whose Vite config resolves **after** that hook has run picks `VITE_APP_VERSION` up in its own env snapshot (Vite reads `VITE_*` from `process.env`). `buildIdentity.ts` reads `(import.meta as ...).env`, which Vite serves from that snapshot, so `getConsoleBuild()` returns the sha instead of `null`. Which project wins the race is timing, which is why the queue build for #26019 went red and earlier builds did not. A throwaway probe in a `unit` worker (base config, `VITE_APP_VERSION` unset in the shell) read `process.env.VITE_APP_VERSION === 'c35f1762' (that tree's HEAD)` in 6 of 6 runs while the import-meta read stayed `null`: the leak into `process.env` is deterministic, and the red depends on the resolution order. ## Measurement | leg | config | result | |---|---|---| | race forced: a throwaway 4 s `config` hook on the `unit` project, so it resolves after the console project | main's console `vitest.config.ts` | **red**: `AssertionError: expected 'c35f1762' (that tree's HEAD) to be null` (1 failed, 10 passed), the same failure as queue run 40325012039 | | same forced race | this PR | **green**: 11 passed | | CI-identical leg, `CI=true pnpm --dir ui run test --shard=10/16` (unfiltered, all projects incl. console; the leg that holds `buildIdentity-12970` and 9 console files) | this PR at the merge with main (`b0841718`) | `buildIdentity-12970` passed; 363/364 files, 4955 passed. The one red was `check-i18n-dead-keys.test.ts` timing out at 15 s while the gate sweep loaded the box; it passes when run alone | | same leg | main's console `vitest.config.ts` | `buildIdentity-12970` passed (the race was won that time); one unrelated red, see Acceptance notes | So the natural race did not lose in 2 targeted runs, 6 probe runs and 1 shard run here. The red was reproduced deterministically only by forcing the resolution order. The probe and the delay hook were throwaway and are not in the diff. Narrowing declared: one shard of 16, not the whole suite, because a full local run takes several hours on this box; CI's Test UI runs all 16 legs. ## Acceptance notes - `ui/packages/app-shell/src/preview/__tests__/DraftChangesPanel.securityLink.test.tsx` ("offers the named item as a control that asks for that surface, inside Studio") fails 3 of 3 times when run alone on main `601c7738` and on this branch, and it failed in the base shard leg. It is not touched by this diff (the dom project never sees the removed define). Handed to the seat; it may show up on this PR's Test UI. - A shell that exports `VITE_APP_VERSION` before `vitest run` still turns the "reads null" case red. That is the test reading its build environment as written, not the leak, and nothing in CI exports it. ## Local gates (head `b0841718`) - `node scripts/pm/dispatch-gates.mjs --commands`: 27 families, each run, all exit 0; `--ran` reconciliation: 27 derived, 27 run, 0 NOT-MEASURED (a derived zero). - `eslint apps/console/vitest.config.ts`: exit 0. `tsc -b tsconfig.node.json --force` in `ui/apps/console` (the program that type-checks this file): exit 0. - Console build: `pnpm --filter '@object-ui/console^...' build`, then `CI=true vite build` in `ui/apps/console` with `VITE_APP_VERSION` unset: lock verdict exit 0, 10273 modules. The bundle still bakes the stamp: `dist/assets/index-*.js` carries `VITE_APP_VERSION:` with value `b0841718` (the git short sha of HEAD). --- _Generated by [Claude Code](https://claude.ai/code/session_01KpXmBvpnCGgpgx8hNbqsso)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 054652b commit f143cd8

2 files changed

Lines changed: 26 additions & 1 deletion

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@object-ui/console': patch
3+
---
4+
5+
fix(console): the console's build-identity define no longer leaks into the other ui test projects
6+
7+
Clause-②: no (build/test configuration only; no exported type or runtime contract change; the console production build keeps its version stamp)
8+
Metadata-protocol: none
9+
10+
The console's Vite config bakes `import.meta.env.VITE_APP_VERSION` (the build's version, else the git short sha) as a `define`. The console's vitest project merges that config, and vitest moves every `import.meta.env.*` / `process.env.*` define into the main process's `process.env` while it resolves a project's config, so every other ui test project's workers inherited the console's git sha. App-shell's `getConsoleBuild()` then read that sha instead of `null`, and `buildIdentity-12970`'s "reads null" case went red in full ui runs. The console's vitest config now drops those keys from the merged Vite config. `vite build` still bakes the version exactly as before.

‎ui/apps/console/vitest.config.ts‎

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,23 @@ import rootConfig from '../../vitest.config.mts';
77
// (objectui#3384).
88
import viteConfig from './vite.config.ts';
99

10+
// The console BUILD bakes its identity as a `define` on
11+
// `import.meta.env.VITE_APP_VERSION` (objectui#12970) — and vitest does not
12+
// scope such a define to the project that declares it. While it resolves a
13+
// project's config it moves every `import.meta.env.*` / `process.env.*` define
14+
// into the main process's `process.env` (`deleteDefineConfig` in vitest's
15+
// cli-api chunk), which the workers of EVERY project inherit. So the console's
16+
// git sha surfaced in app-shell's `getConsoleBuild()` and turned
17+
// `buildIdentity-12970`'s "reads null" case red in full runs, depending on
18+
// shard layout (#26126). Those defines stay in the build and stop here; no
19+
// console test reads them.
20+
const LEAKS_INTO_PROCESS_ENV = /^(import\.meta\.env|process\.env)\./;
21+
const testDefine = Object.fromEntries(
22+
Object.entries(viteConfig.define ?? {}).filter(([key]) => !LEAKS_INTO_PROCESS_ENV.test(key))
23+
);
24+
1025
export default mergeConfig(
11-
mergeConfig(rootConfig, viteConfig),
26+
mergeConfig(rootConfig, { ...viteConfig, define: testDefine }),
1227
defineConfig({
1328
test: {
1429
// The root config no longer sets global setupFiles (they moved into the

0 commit comments

Comments
 (0)