Python apps lock their dependencies with uv: ADR and setup-repo python-app stack - #28
Merged
Merged
Conversation
The standard installs every Python repo with `uv pip install -r requirements.txt`, which pins direct dependencies and re-resolves the rest on every install. For something that deploys, that lets the image, CI and each developer's venv run different trees: retina-server pinned 15 of the 54 third-party packages its image runs, and a developer venv had drifted from production on pydantic and websockets with nothing in the repo recording either choice. Apps become uv projects with a committed uv.lock, synced with --locked in CI and into a venv in images. Libraries are deliberately out of scope: whether they commit a lock is open in ClickUp 86cb49y4k, where the recommendation is that they should, and this record does not pre-empt it. Ticket: ClickUp 123zgec4jmx. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ADR in the previous commit makes apps uv projects; this is what lets a new repo start that way. `python-app` writes a pyproject.toml with [project], a dev dependency group and `package = false`, and a CI workflow that runs `uv sync --locked`. It ships no requirements files and no lock: the skill generates uv.lock at install time and tells the user to commit it, since CI fails without one. The existing `python` stack is untouched and is described as the library scaffold. pythonpath = ["."] is set because an unpackaged app is never installed, so tests import it from the repo root; that is the ImportError adopting-core-setup-repo documents for the library template. The scaffold test locks, syncs and runs the tests of a freshly scaffolded app when uv is available, which the setup-repo CI job has. Bumps core to 0.6.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Summary
Makes Python apps uv projects with a committed
uv.lock, and givessetup-repoapython-appstack that scaffolds one. The current standard,uv pip install -r requirements.txt, pins only direct dependencies, so a deployed app's image, CI and developer venvs can each run a different tree. retina-server had drifted from production on pydantic and websockets that way.Libraries are out of scope. Whether the five
retina-*libraries commit a lock is open in ClickUp 86cb49y4k, where the recommendation is that they should. This PR leaves that decision to the ticket.Changes
ADR
docs/decisions/2026-09-23-python-apps-lock-with-uv.md: defines an app (a deployed service or tool that no other repo installs) and the rules for it:[project]plus adevgroup, andpackage = false.uv sync --lockedin CI.uv sync --locked --no-devinto a venv in images.[tool.uv.sources]path entries.It also records the costs, and how to seed the first lock from production so that moving to it changes no version.
setup-repo:python-appstack (stack/python-app/pyproject.toml,ci/ci-python-app.yml), which reuses the Python gitignore and pre-commit assets.uv lock && uv syncand says to commit the lock.pythonstack is unchanged and is now described as the library scaffold.Plugin version: core bumped to 0.6.0.
Test coverage
test-python-assets.shandtest-ci-assets.shcheck the new assets. Each new check was made to fail against a deliberately broken asset (a requirements file present,uv pipin the app CI,package = true) before being trusted.test-scaffold.shscaffolds apython-app, then runsuv lock,uv sync --lockedanduv run --locked pyteston it when uv is present, as it is in the setup-repo CI job. Removingpythonpathfrom the asset makes it fail.Review notes
build/backend-uv-project.ClickUp: 123zgec4jmx
🤖 Generated with Claude Code