Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
55 changes: 55 additions & 0 deletions decisions/2026-10-13-python-version-matrix.md
Original file line number Diff line number Diff line change
@@ -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.