Search before asking
Description
Two independent defects in the build scripts, both found while working on #980. They are unrelated in mechanism but both sit in the no-uv / fallback paths that CI never exercises, which is why neither has surfaced before. Filing them together since one change can cover both.
1. tools/e2e.sh breaks without uv on PATH
tools/e2e.sh invokes uv by bare name seven times, at :48, :57, :69, :75, :84, :93 and :156, and it has no command -v uv guard anywhere. Its only command -v is for mktemp at :125. So on a machine where uv is not on PATH, every one of those fails with uv: command not found.
This is unlike the sibling scripts. tools/lint.sh:67 and tools/ut.sh:222 both guard their uv usage and fall back to pip, and tools/build.sh installs uv itself before using it. tools/e2e.sh does neither. It only delegates to tools/build.sh at :101 and :114, and both of those are conditional:
if [[ ! -d "e2e-test/target" ]]; then
bash tools/build.sh
fi
...
if [[ ! -f "uv.lock" ]]; then
bash tools/build.sh
fi
So once a build has happened, the delegation is skipped. tools/build.sh -j also never runs the Python half at all, so it never installs uv.
Worth noting what the fix is not: rewriting these to python3 -m uv looks like the obvious parallel to #979, but it would make things worse here. That form requires an importable uv module, which only exists if uv was pip installed. Someone using a standalone uv (the curl installer or homebrew) has a working uv on PATH and no module, so the rewrite would turn a working run into a failing one. #979 deliberately leaves this file alone for that reason.
A guard is the right shape: probe once, prefer the PATH binary, fall back to the interpreter form only when the module is actually importable, and fail with a clear message when neither is available. That also fixes the current failure mode, where the script reports a bare command not found rather than telling you what to install.
2. tools/ut.sh pip fallback passes a log level pytest rejects
tools/ut.sh:282, :285 and :294 pass -o log_cli_level=${LOG_LEVEL:-OFF}, while the uv branch at :240, :249 and :263 passes ${LOG_LEVEL:-CRITICAL}. OFF is not a valid Python logging level name, and pytest rejects it:
$ python3 -m pytest <dir> -o log_cli=true -o log_cli_level=OFF
ERROR: 'OFF' is not recognized as a logging level name for 'log_cli_level'. Please consider passing the logging level num instead.
$ echo $?
4
Exit 4 is a usage error, raised during startup before any test is collected. So whenever the pip fallback path is taken and LOG_LEVEL is unset, the Python test run fails immediately without running a single test. Reproduced against pytest==9.0.3, the version pinned in python/pyproject.toml. The same command with CRITICAL starts normally.
The two branches were presumably meant to behave the same way, so aligning the fallback on CRITICAL looks like the intended value.
Are you willing to submit a PR?
Search before asking
Description
Two independent defects in the build scripts, both found while working on #980. They are unrelated in mechanism but both sit in the no-
uv/ fallback paths that CI never exercises, which is why neither has surfaced before. Filing them together since one change can cover both.1.
tools/e2e.shbreaks withoutuvon PATHtools/e2e.shinvokesuvby bare name seven times, at:48,:57,:69,:75,:84,:93and:156, and it has nocommand -v uvguard anywhere. Its onlycommand -vis formktempat:125. So on a machine whereuvis not on PATH, every one of those fails withuv: command not found.This is unlike the sibling scripts.
tools/lint.sh:67andtools/ut.sh:222both guard theiruvusage and fall back to pip, andtools/build.shinstallsuvitself before using it.tools/e2e.shdoes neither. It only delegates totools/build.shat:101and:114, and both of those are conditional:So once a build has happened, the delegation is skipped.
tools/build.sh -jalso never runs the Python half at all, so it never installsuv.Worth noting what the fix is not: rewriting these to
python3 -m uvlooks like the obvious parallel to #979, but it would make things worse here. That form requires an importableuvmodule, which only exists ifuvwas pip installed. Someone using a standaloneuv(the curl installer or homebrew) has a workinguvon PATH and no module, so the rewrite would turn a working run into a failing one. #979 deliberately leaves this file alone for that reason.A guard is the right shape: probe once, prefer the PATH binary, fall back to the interpreter form only when the module is actually importable, and fail with a clear message when neither is available. That also fixes the current failure mode, where the script reports a bare
command not foundrather than telling you what to install.2.
tools/ut.shpip fallback passes a log level pytest rejectstools/ut.sh:282,:285and:294pass-o log_cli_level=${LOG_LEVEL:-OFF}, while theuvbranch at:240,:249and:263passes${LOG_LEVEL:-CRITICAL}.OFFis not a valid Python logging level name, and pytest rejects it:Exit 4 is a usage error, raised during startup before any test is collected. So whenever the pip fallback path is taken and
LOG_LEVELis unset, the Python test run fails immediately without running a single test. Reproduced againstpytest==9.0.3, the version pinned inpython/pyproject.toml. The same command withCRITICALstarts normally.The two branches were presumably meant to behave the same way, so aligning the fallback on
CRITICALlooks like the intended value.Are you willing to submit a PR?