Repository navigation
Keep watch alive after rebuild errors - #8641
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
26da9d5 to
38467bf
Compare
96c35a5 to
9760751
Compare
38467bf to
527e72a
Compare
9760751 to
9f7e428
Compare
527e72a to
95cbeca
Compare
9f7e428 to
a90a656
Compare
95cbeca to
08c262a
Compare
a90a656 to
766e69a
Compare
08c262a to
23913a4
Compare
766e69a to
35b5524
Compare
23913a4 to
4cc230a
Compare
35b5524 to
60b4bb6
Compare
4cc230a to
784f83f
Compare
60b4bb6 to
5cea2cf
Compare
784f83f to
bb678d0
Compare
5cea2cf to
7132187
Compare
bb678d0 to
52e838b
Compare
7132187 to
a32a29e
Compare
a4a65f3 to
3e45f81
Compare
rescript
@rescript/belt
@rescript/darwin-arm64
@rescript/linux-arm64
@rescript/linux-x64
@rescript/runtime
@rescript/win32-x64
commit: |
Signed-off-by: Florian Hammerschmidt <florianh89@gmail.com>
5e7c5a1 to
3377441
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3377441a3d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Signed-off-by: Florian Hammerschmidt <florianh89@gmail.com>
|
@codex review |
|
Codex Review: Didn't find any major issues. Keep them coming! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Signed-off-by: Florian Hammerschmidt <florianh89@gmail.com>
Signed-off-by: Florian Hammerschmidt <florianh89@gmail.com>
|
Developer playground preview: https://rescript-lang.github.io/rescript/dev-playground/?version=pr-8641 |
Verdict: approve with nits. No correctness bugs found in the watch loop. Init errors propagate instead of panicking.
|
Signed-off-by: Florian Hammerschmidt <florianh89@gmail.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #8641 +/- ##
=======================================
Coverage 81.13% 81.13%
=======================================
Files 456 456
Lines 63750 63750
=======================================
Hits 51724 51724
Misses 12026 12026 🚀 New features to boost your workflow:
|
Log the source event path and its requested compile type once, then wait for the edited source to request full initialization and for an error after that event. Delayed config failures can no longer satisfy the recovery assertion before the edit is processed. Signed-off-by: Florian Hammerschmidt <florianh89@gmail.com>
|
The follow-ups document the exit-code change and dependency-install recovery limit, renumber the tests, and remove duplicate diagnostics. The recovery regression now waits for the source event and a subsequent initialization failure; disabling recovery makes it fail and reproduces stale output. Automatic detection of newly installed or replaced dependencies remains a follow-up; editing a watched source or touching |
Retain the overlapping-source regression, renumber the recovery scripts, and update parity checks for Rust recovery and dependency error exits. Preserve and document the existing OCaml differences. Signed-off-by: Florian Hammerschmidt <florianh89@gmail.com>
cknitt
left a comment
There was a problem hiding this comment.
Checked against current master (applies cleanly, bugs still reproduce: invalid root config panics at watcher.rs:619, missing/malformed dependency exits 2, and lib/build.lock + lib/watch.lock are left behind). The OCaml implementation is not affected. The core watcher fix works for me: no stale output while the config is broken, and a correct rebuild once it's fixed.
A few things before merging:
- Same class of panic remains. Changing the config to
"jsx": {"version": 3}during watch still panics inConfig::get_jsx_args(panic!("JSX version {version} is unsupported")) and again leaves both lock files behind. Turn that into a config error. ADropguard inwith_build_lockthat releases the lock would also make this robust. - Exit code 2 → 1 breaks parity. Rust and OCaml currently both exit 2 for dependency errors (OCaml deliberately,
rescript_ocaml.mlmapsPackage_errorto 2). I'd keep 2 in Rust (e.g. downcast the dependency error inexit_code) instead of documenting a new intentional difference. If we do want 1, change both implementations together, and it's a user-visible change rather than a.fix. - Error messages lost context. The malformed-dependency error no longer names the package (
Could not build package tree for 'bad' at path …→Could not initialize build: Could not read dependency config at …), and the missing-dependency error losesat path '<root>'. Restoring those would also avoid looseningrequire_both_errors_containto per-implementation fragments. - Tests. Test 09 skips the source-retry check for OCaml, so its "no stale output" assertion passes trivially there. The Rust branch depends on the wording of a debug log line. Test 10 edits the shared
testrepo/packages/standaloneconfig, so a temporary fixture like test 07 would be safer. - Minor: dropping
show_progressfrompackages::makealso removes the[1/2] … Error building package treestdout line, which is outside this PR's scope.
Optional follow-up: OCaml recovers automatically when a missing dependency gets installed (it watches resolution candidates); Rust still needs a manual touch, as the description notes.
Reject unsupported JSX versions while reading configuration, and release the build lock through a Drop guard on every return or unwind. Retain dependency failures as typed error context so the CLI preserves exit code 2, package and root-path diagnostics, and the package-tree progress message. Review: Both recovery tests use temporary projects. The invalid-config test records every emitted output across invalid JSON and JSX configurations and recovery, with the same assertions for Rust and OCaml. Disabling Rust's source retry makes it detect stale output without depending on debug-log wording. Validation: Native compiler/CLI and Rust builds, 150 Rust unit tests, all 42 build fixtures, 297 configuration parity cases, 28 focused dependency-error checks, Clippy with warnings denied, formatting, changelog, and shell syntax checks pass. Both recovery scripts pass for both CLIs using isolated polling builds; native filesystem events are unavailable locally and remain for CI. Area: rewatch tests docs Output: unchanged; no generated JavaScript changes Tests: ~rewatch/src/build.rs ~rewatch/src/config.rs ~rewatch/tests/watch/09-watch-recovers-from-invalid-config.sh ~rewatch/tests/watch/10-watch-recovers-new-dependency-config.sh ~rewatch-ocaml/tests/check_command_validation.sh ~rewatch-ocaml/tests/config_acceptance_cases.tsv ~tests/build_tests/weird_deps/input.js ~tests/build_tests/weird_devdeps/input.js PR: #8641 Signed-off-by: Florian Hammerschmidt <florianh89@gmail.com>
Bring in #8902, which waits for duplicate change events to settle before asserting that an unrelated edit retries a failed parse. Keep the reviewed watcher recovery changes and their regressions intact, alongside the merged cleanup and playground API compatibility changes. Validation: Native compiler/CLI and Rust builds, 150 Rust unit tests, Clippy with warnings denied, Rust formatting, canonical suite coverage, changelog, shell syntax, and whitespace checks pass. 47 of 48 OCaml build-system unit cases pass; the native watcher case hits the local filesystem-event EMFILE limit and remains for CI. The retained-parse test matches master exactly. Signed-off-by: Florian Hammerschmidt <florianh89@gmail.com>
The Windows recovery assertions pass, but cleanup can fail when the background launcher exits between the process check and kill. Match the existing watcher test's best-effort launcher cleanup in both new recovery scripts. Shutdown errors from exit_watcher still fail before cleanup removes the fixture. Validation: The native toolchain builds. A focused probe reproduces the old failure in both scripts and verifies the fix for an already-exited launcher, a running launcher, and a failed watcher shutdown. Shell syntax and whitespace checks pass. Signed-off-by: Florian Hammerschmidt <florianh89@gmail.com>
Git Bash's background-process ID is not the native Windows process ID expected by process_is_running. Read the native PID from watch.lock for the recovery test's liveness assertion. Let Bash kill and reap its own launcher without passing that launcher ID through the native-process check. Validation: The native toolchain builds. A focused probe reproduces the false failure with different Bash and native IDs, accepts the live native watcher, and rejects an exited watcher. Both cleanup routines pass the already-exited and running-launcher probes and preserve shutdown failures. Shell syntax and whitespace checks pass. Signed-off-by: Florian Hammerschmidt <florianh89@gmail.com>
cknitt
left a comment
There was a problem hiding this comment.
Rechecked at 0e3814b. All points from my previous comment are addressed:
"jsx": {"version": 3}is now a config error instead of a panic, and the build lock is released by aDropguard.- Dependency errors exit 2 again, matching OCaml.
- Errors name the package and root path again; the parity check uses one shared fragment.
- Recovery tests use temporary projects, detect stale output via
js-post-buildinstead of log wording, and assert the same for Rust and OCaml. - The
[1/2] Error building package tree.line is back.
Verified locally with a build of this head: cargo test passes. In watch mode, invalid root JSON, an unsupported JSX version, a missing dependency and a malformed dependency all keep the watcher alive; a source edit while the config is broken emits nothing, and fixing the config rebuilds with the new suffix. build/clean/format exit 2 for dependency errors and 1 for root config errors and leave no locks behind.
Not blocking: automatic recovery on dependency installation remains a follow-up, as described. Separately, stopping watch with SIGTERM leaves lib/watch.lock behind, but master does the same, so that's not from this PR.
LGTM.
Watch mode could panic or exit when a configuration or source-layout change made full rebuild initialization fail. Initialization errors now propagate through the build lock, are reported, and keep the watcher alive for recovery.
After a failed initialization, source edits retry full initialization until the current configuration can be loaded, preventing compilation with stale suffixes, dependencies, or options. Malformed dependency configurations retain their resolved directory so fixing a newly added workspace dependency can trigger recovery. Unsupported JSX versions return configuration errors, and a Drop guard releases the build lock on errors and unwinding.
Dependency failures preserve exit code
2and package/root-path diagnostic context. The package-tree progress line remains available; the detailed error is reported once.Both recovery tests use temporary projects. The invalid-config test covers invalid JSON and unsupported JSX, records emitted files across recovery, and uses the same assertions for Rust and OCaml. Disabling Rust's source-retry fix makes the test fail with stale output, without relying on debug-log wording.
Recovery limit: installing a missing dependency or replacing a non-local dependency directory does not itself trigger a retry in Rust. Edit a watched source file or touch
rescript.jsonafter installation or replacement. Automatic detection remains a follow-up.Validation: