diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index cdaf544..d826336 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -20,7 +20,7 @@ jobs: - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0 with: enable-cache: true - # Distinguishes this job's cache key from pytest (py3.13)'s. Without + # Distinguishes this job's cache key from the pytest job on the same Python. Without # it both race on the same key and one fails to save. cache-suffix: lint # The ruff and ty hooks are `uv run --no-sync`, so the venv must exist @@ -49,7 +49,7 @@ jobs: matrix: # The supported range, matching requires-python, not a pin: widen it by hand when # a Python is added to or dropped from support. - python-version: ["3.11", "3.12", "3.13", "3.14"] + python-version: ["3.11", "3.12", "3.13", "3.14", "3.15"] steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: diff --git a/README.md b/README.md index e21e962..0320ad8 100644 --- a/README.md +++ b/README.md @@ -140,7 +140,7 @@ tightened. ## CI -Every pull request runs lint, the pytest matrix (Python 3.11 through 3.14), +Every pull request runs lint, the pytest matrix (Python 3.11 through 3.15), and a bootstrap smoke test that generates two projects from the template (one flat, one with DDD layering) and runs the full gate on each, catching any file that uses a placeholder the bootstrap script doesn't know about. diff --git a/decisions/2026-10-13-python-version-matrix.md b/decisions/2026-10-13-python-version-matrix.md new file mode 100644 index 0000000..28fedbf --- /dev/null +++ b/decisions/2026-10-13-python-version-matrix.md @@ -0,0 +1,55 @@ +# Python version matrix follows the development pin + +## Decision: widen the pytest matrix in the same PR that bumps `.python-version` + +When Renovate raises `.python-version` to a new minor Python, that PR also adds +the version to the `pytest` matrix in `.github/workflows/ci.yaml` and updates +the CI section of `README.md`. If the new version fails the matrix, close the +bump PR and keep `.python-version` on the previous minor until the dependencies +catch up. Do not merge the pin without the matrix entry. + +## Context: why it came up + +Renovate bumped `.python-version` from 3.14 to 3.15 (#58) and it merged on +green CI. The pin selects the interpreter for local development and the `lint` +job only; the matrix is listed by hand and stayed at 3.11–3.14. The result was +that the interpreter everyone develops on was outside the range CI tests. + +The matrix comment already says to widen it by hand. Nothing tied that to the +event that makes it due. + +## Alternatives considered + +- **Have Renovate update the matrix too.** A custom regex manager could + rewrite the list. Rejected: adding a supported Python is a support decision, + and a newly released Python is the point where a dependency without wheels + for it breaks `uv sync`. That needs a person to look at the result, which a + bump that also widens the matrix would hide inside one green or red run. +- **Leave the matrix until a separate support review.** Leaves a gap of + unknown length where local `task dev:check` is the only test on the pinned + version, and CI cannot report a failure local runs miss. +- **Keep `.python-version` on the oldest supported Python.** Testing the floor + locally is defensible, but it turns down every Renovate bump forever and + means development never meets the new interpreter until users do. + +## Reasoning + +The bump PR is the one moment the gap opens, and it already arrives as a PR +that needs merging by hand. Making the matrix entry part of accepting it costs +one line and turns the new version's CI run into the check for whether the +pin should move at all. A project whose dependencies are not ready finds out +before the pin lands rather than after. + +## Trade-offs accepted + +- Merging a Python bump is no longer a single click; each project's bump PR + needs the matrix line added by hand. +- One more matrix job per pull request for as long as the old floor is kept. +- uv can lag a CPython release: at 3.15.0 its managed downloads offered only + 3.15.0rc3, so CI tested the release candidate while a Mac with Homebrew's + 3.15.0 tested the final. Accepted as temporary; it clears when uv ships the + final build. + +## Supersedes + +Nothing.