diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e5e51f0..87979c2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -118,6 +118,15 @@ jobs: - name: Tests run: make check-tests PYTEST=pytest + # `make test-e2e` runs its scripts with `uv run --locked`, and Renovate's + # pep723 manager can bump a script's pin but has no step that rewrites its + # lock, so a pin and lock that disagree are caught here, not mid-suite. + - name: Install uv + run: pipx install --python "${{ steps.python.outputs.python-path }}" "uv==$(make -s print-uv-version)" + + - name: Script locks + run: make check-locks LOCK_UV=uv + # The slim and single profiles are projections of the Kubernetes tiers of the # same name, so they go stale when those tiers move and nothing here notices. # dfe-infra is PRIVATE, so the checkout reads it with a short-lived GitHub App diff --git a/Makefile b/Makefile index 353da34..60e9102 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,7 @@ endif # any more (both sweep every profile), and requiring a resolvable profile to STOP # a stack is the same lockout the compose secret comments argue against -- set # DFE_PROFILE to something that does not exist and you could not tear down. -BOOTSTRAP_GOALS := init env-files creds dev-posture help login stack dial modes down clean limits check check-compose check-hardfail check-dockerfile check-docs check-proxy check-python check-tests +BOOTSTRAP_GOALS := init env-files creds dev-posture help login stack dial modes down clean limits check check-compose check-hardfail check-dockerfile check-docs check-locks check-proxy check-python check-tests # Resolve the active profile only when a goal actually needs the compose stack ifneq (,$(filter-out $(BOOTSTRAP_GOALS),$(or $(MAKECMDGOALS),help))) @@ -536,7 +536,7 @@ infra: .env storage-dirs ## Start infrastructure services # --------------------------------------------------------------------------- .PHONY: check -check: check-compose check-hardfail check-dockerfile check-docs check-proxy check-python check-tests ## Run every static check CI runs +check: check-compose check-hardfail check-dockerfile check-docs check-proxy check-python check-tests check-locks ## Run every static check CI runs .PHONY: limits limits: ## Show the resource limits and totals, computed from the resolved config @@ -571,6 +571,20 @@ print-pytest-version: check-tests: ## Run the helper-script unit tests (scripts/tests) $(PYTEST) -q scripts/tests +# Each inline-metadata script runs with `uv run --locked`, and Renovate's pep723 manager rewrites a pin but never its lock, so this fails a pin and lock that disagree. +# Pinned and installed in CI the way RUFF is (LOCK_UV=uv). +UV_VERSION := 0.13.0 +LOCK_UV ?= uvx uv@$(UV_VERSION) + +.PHONY: print-uv-version +print-uv-version: + @echo $(UV_VERSION) + +.PHONY: check-locks +check-locks: ## Assert each inline-metadata script's lock matches its pins (relock with `uv lock --script