Skip to content

Python apps lock their dependencies with uv: ADR and setup-repo python-app stack - #28

Merged
Babissimo merged 2 commits into
mainfrom
docs/apps-lock-with-uv
Sep 23, 2026
Merged

Babissimo merged 2 commits into
mainfrom
docs/apps-lock-with-uv

Conversation

@Babissimo

Copy link
Copy Markdown
Contributor

Summary

Makes Python apps uv projects with a committed uv.lock, and gives setup-repo a python-app stack 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 a dev group, and package = false.
    • A committed lock and no requirements files.
    • uv sync --locked in CI.
    • uv sync --locked --no-dev into a venv in images.
    • Submodules as [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:

    • A new python-app stack (stack/python-app/pyproject.toml, ci/ci-python-app.yml), which reuses the Python gitignore and pre-commit assets.
    • The skill asks app or library for any Python repo, and for an app it runs uv lock && uv sync and says to commit the lock.
    • The existing python stack is unchanged and is now described as the library scaffold.
  • Plugin version: core bumped to 0.6.0.

Test coverage

  • Asset tests: test-python-assets.sh and test-ci-assets.sh check the new assets. Each new check was made to fail against a deliberately broken asset (a requirements file present, uv pip in the app CI, package = true) before being trusted.
  • Scaffold test: test-scaffold.sh scaffolds a python-app, then runs uv lock, uv sync --locked and uv run --locked pytest on it when uv is present, as it is in the setup-repo CI job. Removing pythonpath from the asset makes it fail.
  • Locally: all five suites pass.

Review notes

  • Follow-up: the other apps (tower-finder-service, retina-telemetry, retina-gui, node-infra's mender-auto-accept) still install with plain pip and move under ClickUp 123zgec4jn0.
  • First adopter: retina-server, in retina-server branch build/backend-uv-project.

ClickUp: 123zgec4jmx

🤖 Generated with Claude Code

Babissimo and others added 2 commits September 23, 2026 11:50
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>
@Babissimo
Babissimo merged commit 004fcbc into main Sep 23, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant