Motivation
All 9 service Dockerfiles build their environment with uv sync --frozen. --frozen installs exactly what uv.lock pins and never checks the lock against pyproject.toml — so a lock that has drifted out of sync with pyproject is installed silently.
This shipped the wrong dependency to production once already: griddle's pyproject.toml required fastfuels-core>=0.14.0 while its committed uv.lock still pinned 0.10.1 (an uncommitted relock). uv sync --frozen happily installed core 0.10.1, whose older compute_canopy_metrics computed canopy bulk density ~0.060 kg/m³ instead of ~0.044, failing the FuelCalc-reproduction integration test only after deploy. Root cause + fix: #529 / #530.
uv sync --locked installs from the lock but first asserts the lock is up-to-date with pyproject.toml, failing the build loudly on drift instead of shipping a stale dependency. It would have caught this at build time.
Scope
Switch RUN uv sync --frozen → RUN uv sync --locked in every service Dockerfile:
Before flipping each, confirm that service's lock is already consistent (cd services/<svc> && uv lock --check) so the change doesn't turn an existing latent drift into a red build unexpectedly — relock any that fail as part of this work.
Optional stronger guard
Consider also adding a uv lock --check step to each service's CI workflow (before the build job), so lock drift is caught on the PR rather than only at image build. This catches it even earlier and independent of the Docker build. Left out of the required scope above; decide whether it's worth the 9 workflow edits.
Motivation
All 9 service Dockerfiles build their environment with
uv sync --frozen.--frozeninstalls exactly whatuv.lockpins and never checks the lock againstpyproject.toml— so a lock that has drifted out of sync with pyproject is installed silently.This shipped the wrong dependency to production once already: griddle's
pyproject.tomlrequiredfastfuels-core>=0.14.0while its committeduv.lockstill pinned 0.10.1 (an uncommitted relock).uv sync --frozenhappily installed core 0.10.1, whose oldercompute_canopy_metricscomputed canopy bulk density ~0.060 kg/m³ instead of ~0.044, failing the FuelCalc-reproduction integration test only after deploy. Root cause + fix: #529 / #530.uv sync --lockedinstalls from the lock but first asserts the lock is up-to-date withpyproject.toml, failing the build loudly on drift instead of shipping a stale dependency. It would have caught this at build time.Scope
Switch
RUN uv sync --frozen→RUN uv sync --lockedin every service Dockerfile:services/api/Dockerfileservices/etcher/Dockerfileservices/exporter/Dockerfileservices/griddle/Dockerfileservices/lakitu/Dockerfileservices/standgen/Dockerfileservices/treevox/Dockerfileservices/uploader/Dockerfileservices/walle/DockerfileBefore flipping each, confirm that service's lock is already consistent (
cd services/<svc> && uv lock --check) so the change doesn't turn an existing latent drift into a red build unexpectedly — relock any that fail as part of this work.Optional stronger guard
Consider also adding a
uv lock --checkstep to each service's CI workflow (before the build job), so lock drift is caught on the PR rather than only at image build. This catches it even earlier and independent of the Docker build. Left out of the required scope above; decide whether it's worth the 9 workflow edits.