Skip to content

EPBDS-16211 stop the library watcher emptying static/ - #50

Merged
AlexSamBY merged 2 commits into
masterfrom
fix-clean-root-static
Sep 16, 2026
Merged

AlexSamBY merged 2 commits into
masterfrom
fix-clean-root-static

Conversation

@AlexSamBY

@AlexSamBY AlexSamBY commented Sep 15, 2026

Copy link
Copy Markdown
Member

The bug

Three tests in css.pipeline.parity.test.js failed intermittently on a static/all.css that had existed moments earlier.

The cause

Found by experiment, not by reasoning:

  1. a webpack --watch (from watch-lib) is running alongside jest;
  2. css.semantic-parity.test.js writes override/_semantic.less to measure what each import contributes to the compiled CSS;
  3. that is a source change, so the watcher rebuilds;
  4. CleanRootStatic tapped watchRun, so every rebuild emptied the root static/ payload before PostBuildCopy refilled it.

Reproduced 3/3 with a watcher up, 0/3 without one — which is what made it look like flakiness. Nothing inside jest could see it: the deletion happens in another process, so fs probes on every sync, async and fs.promises deletion API never fire, and chmod 500 on the directory only silences it, because the wipe runs with force: true.

Worth saying plainly: the watcher was mine, left over from the watch-lib work earlier in this ticket, not something a user would normally have running. The watchRun tap was a genuine hazard regardless — it opens a window on every source change for anyone running watch-lib.

The fix

The hook taps beforeRun only. A one-shot build-lib still gets the wipe that clears assets left behind by a rename; watch mode overwrites its outputs on every rebuild anyway, so it loses nothing and gains a static/ that is never momentarily absent.

Acceptance

With a watcher running throughout the run:

before after
static/ after the parity suite 0 files 6 files
css.semantic-parity 11 passed, 3 skipped 14/14

build-lib output unchanged — CSS still sha256 dcdb0a40a6d8ee79929bc40a9335b04f8222e7a235a872242c87ecffa9332723.

jsdom 167 suites / 2540 tests; lint:js, lint:css, css:fixture:check, both docs checks, build-lib and build-css green.

The comment in css.pipeline.parity.test.js that said the mechanism was unexplained now states the mechanism. That suite still reads the file once at load, which keeps it correct regardless of what any concurrent process does.

🤖 Generated with Claude Code

Three tests in `css.pipeline.parity.test.js` failed intermittently on a
`static/all.css` that had existed moments earlier. The cause, found by
experiment rather than reasoning:

  1. a `webpack --watch` (from `watch-lib`) is running alongside jest;
  2. `css.semantic-parity.test.js` writes `override/_semantic.less` to
     measure what each import contributes to the compiled CSS;
  3. that is a source change, so the watcher rebuilds;
  4. `CleanRootStatic` tapped `watchRun`, so every rebuild emptied the
     root `static/` payload before `PostBuildCopy` refilled it.

Reproduced 3/3 with a watcher up and 0/3 without one, which is what made
it look like flakiness. Nothing inside jest could see it: the deletion is
in another process, so `fs` probes on every sync, async and `fs.promises`
deletion API never fire, and `chmod 500` on the directory only silences
it, because the wipe runs with `force: true`.

The hook now taps `beforeRun` only. A one-shot `build-lib` still gets the
wipe that clears assets left by a rename; watch mode overwrites its
outputs on every rebuild anyway, so it loses nothing and gains a
`static/` that is never momentarily absent.

Acceptance, with a watcher running throughout: 6 files before the suite,
6 files after — it was 0 before this change — and the parity suite runs
14/14 instead of skipping three. `build-lib` output unchanged, CSS still
sha256 dcdb0a40a6d8ee79929bc40a9335b04f8222e7a235a872242c87ecffa9332723.

The comment left in `css.pipeline.parity.test.js` saying the mechanism
was unexplained is replaced with the mechanism. That suite keeps reading
the file once at load: correct regardless of what any other process does.
The fix landed in #49; the plan still described it as open in three
places. R15 item 8, F1 step 5's "still open" list and H7 now say what is
true: `webpack.watch.config.mjs` is deleted, `watch-lib` runs the library
config itself, and H7 has two configs to unify rather than three.

Step 5's note also records what fixing watch surfaced — `CleanRootStatic`
tapping `watchRun`, so any source write emptied the root `static/` for
the length of a rebuild. It cost an afternoon and reads as flakiness, so
it is written down where the next person will look.
@AlexSamBY
AlexSamBY merged commit 43acc3e into master Sep 16, 2026
5 checks passed
@AlexSamBY
AlexSamBY deleted the fix-clean-root-static branch September 16, 2026 08:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant