Repository navigation
Conversation
Add tests that find every workflow job running pytest or coverage, follow the scripts and Make targets each job runs, and require that the job installs nothing with pip, runs every test command through uv run --frozen, and selects Python 3.12. They also require make install to sync the locked dev environment, the Make test targets to run through it, and the two operational database workflows to keep an explicit install for the bare python they run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
make install now runs uv sync --frozen --extra dev, and make test, make test-env-vars, make debug-test, make debug and make debug-asgi run through uv run --frozen --extra dev, so local runs and CI use the versions uv.lock pins, as the Cloud Run image does. The Makefile exports UV_PYTHON=3.12 unless it is already set, matching the Cloud Run image rather than the 3.14 that .python-version selects. The v1 Cloud SQL migration and household mirror event workflows run their scripts with setup-python's bare python, which does not read the .venv that make install now creates, so they now install with an explicit pip install -e ".[dev]" and behave as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Test and Test environment variables jobs set up uv, set UV_PYTHON=3.12, install with make install (uv sync --frozen --extra dev) and run their tests through uv run --frozen --extra dev, so pull request tests use the versions the Cloud Run image installs instead of the newest releases on PyPI. make test still writes coverage.xml in the repository root for the Codecov upload. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The staging deploy job's release tests and staging integration tests, the parallel live simulation tests and the production candidate smoke tests now set up uv, set UV_PYTHON=3.12, install with make install and run pytest through uv run --frozen --extra dev. The live and smoke test jobs no longer pip install unpinned pytest, pytest-xdist and httpx. pytest-xdist joins the dev extra so the two-worker live tests can run from the lock; uv lock (uv 0.12.1, as in the Cloud Run image) adds only pytest-xdist 3.8.0 and execnet 2.1.2. The lock test now skips comment lines, which are not executed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Alembic v1 check now sets up uv, installs with make install and runs pytest and alembic through uv run --frozen --extra dev instead of the unlocked pip install -e ".[dev]" that make install used to run. The Alembic v2 check and the cross-database integration tests already synced uv.lock, but ran uv run without --frozen, which re-resolves when the lock is out of date, and ran on the Python 3.14 that .python-version selects. They now sync and run with --frozen --extra dev on UV_PYTHON=3.12. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The versioning job installed the newest towncrier with pip. towncrier is in the dev extra, so build_changelog.sh and make changelog now run it through uv run --frozen --extra dev, after uv lock has refreshed the lock with the new project version, and the versioning job sets UV_PYTHON=3.12. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The README's setup steps now say that make install builds .venv from uv.lock on Python 3.12 and that the Make targets run through uv run, and the testing skill describes the locked test environment and what a CI test job must do. Add the changelog fragment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Self-review fixes. The lock test module passes each workflow job as a WorkflowJob named tuple instead of an unnamed 4-tuple read by index; the module still fails 29 of its 32 tests against origin/master and passes all 32 here. The README now lists the Make targets that run through uv run instead of claiming every Python-running target does, since quality-guards, format and the version bump in changelog do not. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
build_changelog.sh now runs towncrier through uv run --frozen --extra dev, so its test puts a fake uv on PATH instead of a fake towncrier and expects the uv run call. Found by the full make test run: the test failed against the changed script; it now passes, and fails against the previous script. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 21, 2026
anth-volk
added this pull request to stack #3998
October 21, 2026 20:43
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3995 +/- ##
===========================================
+ Coverage 49.24% 86.00% +36.76%
===========================================
Files 243 259 +16
Lines 14398 15777 +1379
Branches 2343 2628 +285
===========================================
+ Hits 7090 13569 +6479
+ Misses 6682 1456 -5226
- Partials 626 752 +126 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3993
Summary
The Cloud Run image for the Public API installs from
uv.lock(uv sync --frozen --no-dev --no-editable), but the CI test jobs installed withpip install -e ".[dev]", which resolves the newest releases on PyPI. For example, PR #3933's run 39629243016 installed SQLAlchemy 2.1.6 and psycopg 3.3.6 (the lock pins 2.0.49 and 3.3.4), and six tests failed only in CI. This PR makes every CI test job install fromuv.lockand run its tests throughuv run --frozenon Python 3.12, the version the Cloud Run image runs.A separate PR adds a daily workflow that relocks
uv.lockand opens a PR, so dependency upgrades still get tested in CI.Python version
.python-versionpins 3.14, so uv used 3.14 even afteractions/setup-pythoninstalled 3.12. The Type-check API v2 job's log shows uv downloading CPython 3.14.8. Every job changed here setsUV_PYTHON: "3.12", and the Makefile exportsUV_PYTHON ?= 3.12.Install sites
make installpip install -e ".[dev]"uv sync --frozen --extra devmake test,test-env-vars,debug-test,debug,debug-asgipython -m coverage,pytest,flask,uvicornuv run --frozen --extra dev ...make changelog(towncrier step)towncrieruv run --frozen --extra dev towncrierpr.ymlTestmake install(pip),make testmake install(locked),make test(locked)pr.ymlTest environment variablesmake install(pip), barepytestmake install,uv run --frozen --extra dev pytestpush.ymlversioningpip install towncrier(unpinned)build_changelog.shrunsuv run --frozen --extra dev towncrierafteruv lockpush.ymlstaging deploy (release tests, staging integration tests)make install(pip), barepython -m pytestmake install,uv run --frozen --extra dev python -m pytestpush.ymlparallel live staging testspip install pytest pytest-xdist httpx(unpinned)make install;run_live_staging_tests.shusesuv run --frozen --extra devpush.ymlproduction candidate smoke testspip install pytest httpx(runner's system Python, unpinned)make install,uv run --frozen --extra dev python -m pytestalembic-v1-check.ymlmake install(pip), barepython -m pytest/python -m alembicmake install,uv run --frozen --extra dev ...alembic-v2-check.yml,v2-integration-check.ymluv sync --frozen,uv runwithout--frozen, Python 3.14uv sync --frozen --extra dev,uv run --frozen --extra dev, Python 3.12pytest-xdistis added to the dev extra so the two-worker live tests can run from the lock.uv lockwas run with uv 0.12.1, the version in the Cloud Run image, to keep lock revision 3; it adds onlypytest-xdist3.8.0 andexecnet2.1.2.Left outside the lock
migrate-v1-cloud-sql.ymlandprocess-v1-household-mirror-event.ymlnow run an explicit unlockedpip install -e ".[dev]"(the commandmake installused to run), so they behave exactly as before. Their scripts run the barepythonfromactions/setup-python, and that interpreter doesn't see the.venvthatmake installnow creates. Moving them to the lock means running their scripts throughuv runand verifying their database credentials and Cloud SQL Auth Proxy wiring against real databases, so it is left for a separate, verified change. They still run against whatever versions are newest on PyPI, the same mismatch that caused Refactor the application package within ruff's complexity limits #3933's failure.pip install "shellcheck-py==0.11.0.1"(quality-guards jobs inpr.ymlandpush.yml) stays pinned. shellcheck-py is not a project dependency, and the quality-guards job runs only standard-library guard code without installing the project.install_locked_ruff.sh(lint jobs) still installs ruff with pip, but at the version read fromuv.lock. ruff has no Python dependencies.pip install requests uvinupdate-policyengine-bundle.yamlis unchanged. It is a bot workflow that updates pins and relocks, not a test job.seed-v2-database.yml(operational, against real databases) and the Type-check API v2 job already sync from the lock but still runuv runwithout--frozenand on Python 3.14. Neither runs tests, so neither is changed here.docker/Dockerfile(the generic image) installspolicyengine[models]==6.7.5with pip and is out of scope.Coverage and Codecov
make teststill runscoverage run -a --branch -m pytest ...followed bycoverage xml -i, now throughuv run, from the repository root, socoverage.xmlis written wherecodecov/codecov-action@v5finds it. The coverage version doesn't change:policyengine-canadarequirescoverage<7, so both the old pip install (run 39629243016 builtcoverage-6.5.0-cp312from the sdist) and the lock use coverage 6.5.0.Environment variables
Each changed job's environment variables, with their provider.
uv runpasses the parent environment through to the test process unchanged. I checked this locally: values set beforeuv run, beforemakeand beforeenv -u ... makeall reached the Python process, and the variable removed withenv -ustayed removed.UV_PYTHON(new): a literal in each changed job'senv:, plus the Makefile default.OLD_SIMULATION_GATEWAY_URL: repository variable, set at workflow level inpr.ymlandpush.yml.pr.ymlTest environment variables and Test:POLICYENGINE_DB_PASSWORD,CODECOV_TOKEN,GCP_WORKLOAD_IDENTITY_PROVIDER,GCP_DEPLOY_SERVICE_ACCOUNT: repository secrets.POLICYENGINE_GITHUB_MICRODATA_AUTH_TOKEN,PE_UK_PRIVATE_HF_READ_TOKEN(exposed asHUGGING_FACE_TOKEN),OPENAI_API_KEY: organization secrets visible to this repository.env:, as before.google-github-actions/auth(workload identity) writes the credentials file and exportsGOOGLE_APPLICATION_CREDENTIALSand related variables throughGITHUB_ENV, so later steps, includinguv run, inherit them.push.ymlversioning:APP_IDandAPP_PRIVATE_KEYare organization secrets, unchanged. towncrier reads no environment variables.push.ymlstaging deploy:POLICYENGINE_DB_PASSWORD(repository secret);POLICYENGINE_GITHUB_MICRODATA_AUTH_TOKEN,OPENAI_API_KEY,PE_UK_PRIVATE_HF_READ_TOKEN, andGATEWAY_AUTH_ISSUER,GATEWAY_AUTH_AUDIENCE,GATEWAY_AUTH_CLIENT_ID,GATEWAY_AUTH_CLIENT_SECRET_RESOURCE(organization secrets);RUNTIME_CACHE_*(literals).run_release_tests.shstill removes the deployment settings withenv -u, andUV_PYTHONis not among them.API_BASE_URLandSTAGING_API_TEST_PROBE_IDcome from step outputs;V2_MIGRATION_DATABASE_URL,STAGING_AUTH0_TEST_CLIENT_ID,_CLIENT_SECRET,_USERNAMEand_PASSWORDarestagingenvironment secrets;STAGING_AUTH0_TEST_DOMAIN,_AUDIENCEand_REALMarestagingenvironment variables.push.ymlparallel live tests:API_BASE_URLandSTAGING_API_TEST_PROBE_IDcome from the outputs of the job it needs and run identifiers.push.ymlproduction candidate smoke tests:API_BASE_URLandSTAGING_API_TEST_PROBE_IDcome from step outputs. The job-level variables are unchanged and come from theproductionenvironment and the repository.CODECOV_TOKENis passed explicitly by the calling workflows, unchanged.Not verified from here: whether each secret's value is current, since only the names can be listed. These variables are also used by changed jobs but aren't listed as repository, environment or organization variables:
vars.POLICYENGINE_DB_USERandvars.POLICYENGINE_DB_NAME, used in the deploy steps, which this PR doesn't change.Testing
tests/unit/test_locked_test_environments.pyfinds every workflow job that runs pytest or coverage, follows the.github/**/*.shscripts and Make targets it runs, and requires that the job:uv run --frozen;UV_PYTHON: "3.12".It also checks:
make installisuv sync --frozen --extra devand that the Make test targets run through the lock;Red-green results by commit:
origin/master. The failures were the Makefile commands, the pip andmake installinstalls, barepytest/python -m pytest, the missingUV_PYTHON, and the operational jobs still usingmake install.pr.yml: the 6pr.ymljob tests pass.push.yml: allpush.ymljob tests pass. The 6 failures left were the Alembic v1/v2 and cross-database jobs. The existing live-test assertion now expectsmake install. While doing this I found and fixed one detection error: the lock test was reading comment lines as executed commands.uv runnow asserts the locked commands.pip install towncrierin the versioning job, and passes after the change.origin/masterand passes 32/32 at this commit. The README now lists the Make targets that run throughuv run, instead of claiming all of them do.uv. It failed in the full run, fails against the previous script, and passes now.Other checks, all run in the locked environment (
uv run --frozen --extra dev --python 3.12):ruff format --check .andruff check .with the ruff pinned inuv.lock(0.15.12): pass.python scripts/run_quality_guards.py: migration-contracts, rules-registry and ci-scripts pass.python -m scripts.rules guard --base-ref origin/master: passes.python -m scripts.rules render: no changes.uv lock --check: consistent.# noqaadded.make test, Python 3.12.13, the locked environment):test_build_changelog_uses_the_pyproject_version, which put a faketowncrieronPATH, but the script now callsuv run. Commit 9 fakesuvinstead. That test fails against the old script, and the module passes (10/10) at this commit.coverage xml -ion the run's.coveragedata wrotecoverage.xml(coverage 6.5.0) in the repository root.CI was not awaited because of the ongoing GitHub Actions incident.
🤖 Generated with Claude Code