EPBDS-16211 stop the library watcher emptying static/ - #50
Merged
Merged
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
Three tests in
css.pipeline.parity.test.jsfailed intermittently on astatic/all.cssthat had existed moments earlier.The cause
Found by experiment, not by reasoning:
webpack --watch(fromwatch-lib) is running alongside jest;css.semantic-parity.test.jswritesoverride/_semantic.lessto measure what each import contributes to the compiled CSS;CleanRootStatictappedwatchRun, so every rebuild emptied the rootstatic/payload beforePostBuildCopyrefilled 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
fsprobes on every sync, async andfs.promisesdeletion API never fire, andchmod 500on the directory only silences it, because the wipe runs withforce: true.Worth saying plainly: the watcher was mine, left over from the
watch-libwork earlier in this ticket, not something a user would normally have running. ThewatchRuntap was a genuine hazard regardless — it opens a window on every source change for anyone runningwatch-lib.The fix
The hook taps
beforeRunonly. A one-shotbuild-libstill 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 astatic/that is never momentarily absent.Acceptance
With a watcher running throughout the run:
static/after the parity suitecss.semantic-paritybuild-liboutput unchanged — CSS still sha256dcdb0a40a6d8ee79929bc40a9335b04f8222e7a235a872242c87ecffa9332723.jsdom 167 suites / 2540 tests;
lint:js,lint:css,css:fixture:check, both docs checks,build-libandbuild-cssgreen.The comment in
css.pipeline.parity.test.jsthat 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