From e8239a2d70fa24629068718ab10fc1c34d999c17 Mon Sep 17 00:00:00 2001 From: Christoph Knittel Date: Fri, 6 Nov 2026 20:53:29 +0000 Subject: [PATCH 1/4] Check for dead code in CI The build-compiler job that builds the playground now runs make dead-code after the playground build, so new dead code fails CI. It installs reanalyze 2.27.0, the first release that analyzes the native and the browser build trees together, from its tag until the opam-repository package is merged. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Kbf3gLDo8mBJKpNE25WAwT Signed-off-by: Christoph Knittel --- .github/workflows/ci.yml | 9 +++++++++ changes/dead-code-ci.internal.md | 1 + scripts/dead_code.sh | 4 ++-- 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 changes/dead-code-ci.internal.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5295d3733c..5593e8154e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -275,6 +275,15 @@ jobs: if: matrix.build_playground run: opam exec -- make playground + # Runs after the playground build, whose browser-profile tree it + # analyzes together with the native one. + - name: Check for dead code + if: matrix.build_playground + run: | + opam pin add --yes --no-action reanalyze git+https://github.com/rescript-lang/reanalyze.git#v2.27.0 + opam install --yes reanalyze + opam exec -- make dead-code + - name: Test playground compiler if: matrix.build_playground run: yarn workspace playground test diff --git a/changes/dead-code-ci.internal.md b/changes/dead-code-ci.internal.md new file mode 100644 index 0000000000..5fcb549ce3 --- /dev/null +++ b/changes/dead-code-ci.internal.md @@ -0,0 +1 @@ +- Check in CI that reanalyze reports no dead code in the OCaml sources. diff --git a/scripts/dead_code.sh b/scripts/dead_code.sh index a89fecdd15..8ecfe65596 100755 --- a/scripts/dead_code.sh +++ b/scripts/dead_code.sh @@ -4,8 +4,8 @@ # anything. # # Usage: REANALYZE=/path/to/reanalyze.exe ./scripts/dead_code.sh -# (defaults to reanalyze.exe on PATH; needs a reanalyze that analyzes several -# build trees together, rescript-lang/reanalyze#224) +# (defaults to reanalyze.exe on PATH; needs reanalyze 2.27.0 or later, which +# analyzes several build trees together: opam install reanalyze) set -euo pipefail cd "$(dirname "$0")/.." From 165433fff788cb18426d6456b0c495527e1abc8a Mon Sep 17 00:00:00 2001 From: Christoph Knittel Date: Fri, 6 Nov 2026 21:27:47 +0000 Subject: [PATCH 2/4] Build reanalyze from its tag instead of installing it with opam In CI, opam install reanalyze recompiled the whole restored switch (62 packages, about 4 minutes): opam misses the musl system package of the static switch and treats that as a system change. The step now clones the v2.27.0 tag and builds reanalyze with dune in the existing switch (seconds), and passes it to make dead-code with REANALYZE. This also works unchanged once the opam package is published. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Kbf3gLDo8mBJKpNE25WAwT Signed-off-by: Christoph Knittel --- .github/workflows/ci.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5593e8154e..de3860ccff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -276,13 +276,16 @@ jobs: run: opam exec -- make playground # Runs after the playground build, whose browser-profile tree it - # analyzes together with the native one. + # analyzes together with the native one. reanalyze is built from its + # release tag in the existing switch: an opam install would recompile + # the restored static switch, whose musl system package opam misses. - name: Check for dead code if: matrix.build_playground + shell: bash run: | - opam pin add --yes --no-action reanalyze git+https://github.com/rescript-lang/reanalyze.git#v2.27.0 - opam install --yes reanalyze - opam exec -- make dead-code + git -c advice.detachedHead=false clone --quiet --depth 1 --branch v2.27.0 https://github.com/rescript-lang/reanalyze.git "$RUNNER_TEMP/reanalyze" + (cd "$RUNNER_TEMP/reanalyze" && opam exec -- dune build -p reanalyze @install) + REANALYZE="$RUNNER_TEMP/reanalyze/_build/install/default/bin/reanalyze.exe" opam exec -- make dead-code - name: Test playground compiler if: matrix.build_playground From a5ed3613ac58c2f86331733abaa9ef31476e5074 Mon Sep 17 00:00:00 2001 From: Christoph Knittel Date: Fri, 6 Nov 2026 21:40:27 +0000 Subject: [PATCH 3/4] Run opam exec from the repository when building reanalyze CI's opam switch is local to the repository, and opam exec finds it from the current directory: run from inside the reanalyze clone it failed with "No switch is currently set". opam exec now runs from the repository and changes into the clone itself. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Kbf3gLDo8mBJKpNE25WAwT Signed-off-by: Christoph Knittel --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de3860ccff..263f9fd05e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -284,7 +284,9 @@ jobs: shell: bash run: | git -c advice.detachedHead=false clone --quiet --depth 1 --branch v2.27.0 https://github.com/rescript-lang/reanalyze.git "$RUNNER_TEMP/reanalyze" - (cd "$RUNNER_TEMP/reanalyze" && opam exec -- dune build -p reanalyze @install) + # opam exec finds the repository's local switch from the current + # directory, so it changes directory itself. + opam exec -- sh -c 'cd "$RUNNER_TEMP/reanalyze" && dune build -p reanalyze @install' REANALYZE="$RUNNER_TEMP/reanalyze/_build/install/default/bin/reanalyze.exe" opam exec -- make dead-code - name: Test playground compiler From dfec1cd986be3ee08cf90553a53259b7f1effb34 Mon Sep 17 00:00:00 2001 From: Christoph Knittel Date: Sat, 7 Nov 2026 16:01:14 +0000 Subject: [PATCH 4/4] Make reanalyze a test dependency reanalyze 2.27.0 is on opam now, so it becomes a pinned test dependency in rescript.opam like ocamlformat and ounit2 (not on Windows, like js_of_ocaml: the check runs on Linux). opam install . --deps-only --with-test installs it for developers, and CI builds it into the cached switch, so the dead-code step just runs make dead-code instead of building reanalyze from its tag. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Kbf3gLDo8mBJKpNE25WAwT Signed-off-by: Christoph Knittel --- .github/workflows/ci.yml | 13 +++---------- dune-project | 8 +++++++- rescript.opam | 1 + scripts/dead_code.sh | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 263f9fd05e..292275ed2f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -276,18 +276,11 @@ jobs: run: opam exec -- make playground # Runs after the playground build, whose browser-profile tree it - # analyzes together with the native one. reanalyze is built from its - # release tag in the existing switch: an opam install would recompile - # the restored static switch, whose musl system package opam misses. + # analyzes together with the native one. reanalyze is a test + # dependency, installed with the switch. - name: Check for dead code if: matrix.build_playground - shell: bash - run: | - git -c advice.detachedHead=false clone --quiet --depth 1 --branch v2.27.0 https://github.com/rescript-lang/reanalyze.git "$RUNNER_TEMP/reanalyze" - # opam exec finds the repository's local switch from the current - # directory, so it changes directory itself. - opam exec -- sh -c 'cd "$RUNNER_TEMP/reanalyze" && dune build -p reanalyze @install' - REANALYZE="$RUNNER_TEMP/reanalyze/_build/install/default/bin/reanalyze.exe" opam exec -- make dead-code + run: opam exec -- make dead-code - name: Test playground compiler if: matrix.build_playground diff --git a/dune-project b/dune-project index 7ae75344d2..2930333848 100644 --- a/dune-project +++ b/dune-project @@ -61,7 +61,13 @@ (and (<> :os "win32") :with-test - (= 6.5.0))))) + (= 6.5.0))) + ; make dead-code + (reanalyze + (and + (<> :os "win32") + :with-test + (= 2.27.0))))) (package (name analysis) diff --git a/rescript.opam b/rescript.opam index 9edebe7a03..132e77e1b3 100644 --- a/rescript.opam +++ b/rescript.opam @@ -27,6 +27,7 @@ depends: [ "ocaml-lsp-server" {with-dev-setup & >= "1.23.0"} "js_of_ocaml" {os != "win32" & with-test & = "6.5.0"} "wasm_of_ocaml-compiler" {os != "win32" & with-test & = "6.5.0"} + "reanalyze" {os != "win32" & with-test & = "2.27.0"} ] build: [ ["dune" "subst"] {dev} diff --git a/scripts/dead_code.sh b/scripts/dead_code.sh index 8ecfe65596..d9e072812d 100755 --- a/scripts/dead_code.sh +++ b/scripts/dead_code.sh @@ -4,8 +4,8 @@ # anything. # # Usage: REANALYZE=/path/to/reanalyze.exe ./scripts/dead_code.sh -# (defaults to reanalyze.exe on PATH; needs reanalyze 2.27.0 or later, which -# analyzes several build trees together: opam install reanalyze) +# (defaults to reanalyze.exe on PATH. reanalyze is a test dependency in +# rescript.opam, installed by opam install . --deps-only --with-test.) set -euo pipefail cd "$(dirname "$0")/.."