Skip to content

fix: run gettext after dialyzer so they stop sharing _build - #97

Merged
jimsynz merged 2 commits into
mainfrom
fix/keep-gettext-extraction-out-of-dialyzers-way
Aug 27, 2026
Merged

fix: run gettext after dialyzer so they stop sharing _build#97
jimsynz merged 2 commits into
mainfrom
fix/keep-gettext-extraction-out-of-dialyzers-way

Conversation

@jimsynz

@jimsynz jimsynz commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

What

Make the gettext tool in .check.exs depend on dialyzer as well as
ex_unit, so mix gettext.extract no longer runs alongside mix dialyzer.

Why

mix gettext.extract --check-up-to-date re-expands the gettext macros by
force-recompiling the project (mix compile --force-elixir +
mix compile.elixir --force). A forced recompile empties
_build/dev/lib/bb_example_wx200/ebin and .../consolidated before refilling
them. Measured locally, that window is about two seconds:

41.59 ebin=21 consolidated=0
41.70 ebin=1  consolidated=0
43.47 ebin=21 consolidated=0
43.76 ebin=21 consolidated=27

ex_check was running that tool in parallel with mix dialyzer. Elixir's build
lock serialises the two compiles, but dialyzer reads beams after it releases
the lock — first when checking the PLT, then when it globs the ebin to build its
file list. If the wipe lands in either phase, dialyzer fails:

:dialyzer.run error: File not found:
  .../_build/dev/lib/bb_example_wx200/consolidated/Elixir.Collectable.beam
  files: [],
:dialyzer.run error: Analysis failed with error:
No .beam files to analyze (no --src specified?)
Halting VM with exit status 1

This is what has been failing the bb_example_wx200 job in bb's Test
Subprojects
workflow (beam-bots/bb#245). That workflow deletes
_build/*/*.plt.hash before mix check, which forces dialyxir's full PLT
re-check — turning a sub-second exposure into a ~20 second one, so the collision
happens nearly every run there. bb_example_so101 has the same pair of tools
and fails the same way (a fix for it is on its own branch).

Verification

Locally, with BB_VERSION=local and the PLT hash deleted to match bb's CI:

  • Beforemix gettext.extract overlapping mix dialyzer reproduces the
    failure above byte for byte, including the same Elixir.Collectable.beam and
    the empty files: [].

  • Aftermix check --no-retry puts the forced recompile in the last three
    seconds of the run, after dialyzer has finished:

    check start 32:45
    33:21 ebin=21 cons=0
    33:21 ebin=1  cons=0
    33:24 ebin=21 cons=0
    check end   33:24
    

    mix check --no-retry passes; reuse fails only on this machine, where pipx
    isn't on the asdf path.

The deps: [:ex_unit, :dialyzer] restates :ex_unit because ex_check replaces
the option rather than merging it.

Picks up the fix for CVE-2026-64941, an open redirect in
Phoenix.LiveView.validate_local_url!/2 via ASCII tab, LF and CR.
Pulls phoenix 1.8.10 alongside it as a co-requisite.
`mix gettext.extract --check-up-to-date` force-recompiles the project so the
gettext macros re-expand. A forced recompile empties
`_build/dev/lib/bb_example_wx200/ebin` and `.../consolidated` for a second or
two before refilling them, and `ex_check` was running that tool alongside
`mix dialyzer`.

Elixir's build lock serialises the two compiles, but not dialyzer's beam
reads, which happen after it releases the lock. When the wipe lands in that
phase, dialyzer either fails to read a consolidated protocol beam or enumerates
an empty ebin and halts with "No .beam files to analyze".

Making `gettext` depend on `dialyzer` moves the forced recompile to the end of
the run, when nothing else is reading the build directory.
@jimsynz
jimsynz merged commit a0bc1b1 into main Aug 27, 2026
17 checks passed
@jimsynz
jimsynz deleted the fix/keep-gettext-extraction-out-of-dialyzers-way branch August 27, 2026 22:38
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