Skip to content

ci: extend Python test matrix to include 3.13 and 3.14 (#349)#354

Merged
cmeans-claude-dev[bot] merged 1 commit into
mainfrom
ci/python-matrix-extension
Apr 21, 2026
Merged

ci: extend Python test matrix to include 3.13 and 3.14 (#349)#354
cmeans-claude-dev[bot] merged 1 commit into
mainfrom
ci/python-matrix-extension

Conversation

@cmeans-claude-dev
Copy link
Copy Markdown
Contributor

@cmeans-claude-dev cmeans-claude-dev Bot commented Apr 21, 2026

Closes #349.

Summary

One-line change in .github/workflows/ci.yml:

```diff
matrix:

  •      python-version: [\"3.10\", \"3.11\", \"3.12\"]
    
  •      python-version: [\"3.10\", \"3.11\", \"3.12\", \"3.13\", \"3.14\"]
    

```

pyproject.toml declares requires-python = \">=3.10\" — the package metadata allows 3.13 and 3.14, but CI never exercised them. That's a source of silent breakage for any self-hoster running the package under a newer Python than we tested.

What stays unchanged

Why this is additive, not redundant, with #348

This PR validates Python versions under actions/setup-python; #348 (merged as PR #350) validates the shipped Docker image. Both are needed for full CI coverage:

  • The matrix catches Python-version-specific code breakage (stdlib removals, syntax/semantics changes, transitive-dep wheel availability for newer Pythons).
  • The docker-smoke catches image-specific breakage (FROM python:X.Y-slim changes, pip install failures inside the slim image, entry-point registration).

Neither substitutes for the other.

Risks and unknowns

This is the "may surface hidden work" case I flagged when we ordered the P3s. Two outcomes for the new matrix entries:

  • Happy path: 3.13 and 3.14 both pass. Merge and move on.
  • Unhappy path: 3.13 or 3.14 fails — likely because a transitive dependency (testcontainers, psycopg, lingua-language-detector, mcp, pgvector, pydantic, etc.) doesn't ship wheels for that Python yet, or a stdlib removal breaks a dep. Each failure is a separate triage: bump a dep to a version that supports the newer Python, or exclude the entry with a note, or declare the >=3.10 floor more strictly as an upper bound in pyproject.toml.

CI on this PR is the load-bearing test. If it's green, #349 is closed. If it's red, we'll have a triage list to work through.

Scope

  • .github/workflows/ci.yml+1, -1 (matrix list)
  • CHANGELOG.md+3 (new ### Added entry under [Unreleased])

No source, no tests, no compose-file changes, no migrations.

References

QA

Prerequisites

None. Pure CI-workflow change.

Automated checks

  • test (3.10/3.11/3.12) — existing entries; expected to remain green.
  • test (3.13) and test (3.14) — new entries; expected to exercise the full pytest tests/ suite against these versions. If any fail, that's the actual finding this PR surfaces.
  • lint, typecheck, codecov/patch — pinned to 3.12; unchanged.
  • docker-smokenot triggered (no Dockerfile / pyproject.toml / uv.lock / .dockerignore / workflow-file-matching-its-trigger change).
  • CodeQL (actions) — will re-scan ci.yml; no new taint-flow sites introduced.

Manual tests

    • YAML parse.
      ```
      python3 -c "import yaml; yaml.safe_load(open('.github/workflows/ci.yml')); print('OK')"
      ```
      Expected: OK.
    • Matrix lists 5 entries in order.
      ```
      grep -A1 '^ matrix:' .github/workflows/ci.yml | tail -1
      ```
      Expected: python-version: [\"3.10\", \"3.11\", \"3.12\", \"3.13\", \"3.14\"].
    • CI runs 5 test jobs on this PR. Verify in the Actions tab that test (3.10), test (3.11), test (3.12), test (3.13), test (3.14) all appear in the check list for this PR.
    • All five test jobs pass. The actual acceptance test — if 3.13 or 3.14 fails, this PR needs follow-up work before it can merge:

      • test (3.13) fails → read the log; common culprits: testcontainers / lingua-language-detector / mcp without a 3.13 wheel
      • test (3.14) fails → same, newer target; 3.14 wheel coverage is generally thinner than 3.13

      Each failure is a separate triage decision (bump the dep, exclude the matrix entry with a note, or tighten requires-python upper bound).

    • Lint/typecheck unchanged. lint and typecheck jobs still use python-version: \"3.12\" — they should continue to run in their existing time envelope. Verify by checking that neither job's duration in this PR's CI is materially different from the last green main CI run.
    • No other files changed. git diff --stat origin/main shows exactly .github/workflows/ci.yml (+1, -1) and CHANGELOG.md (+3). Nothing else.

Acceptance

ci.yml test job matrix changes from:

  python-version: ["3.10", "3.11", "3.12"]

to:

  python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]

pyproject.toml declares `requires-python = ">=3.10"` — the package
metadata allows 3.13 and 3.14 but CI never exercised them. This
closes that gap.

lint / typecheck / codecov jobs remain pinned to 3.12 — one
representative version for static analysis is sufficient.

Complements #348 (docker-smoke workflow). The matrix validates
Python versions under actions/setup-python; docker-smoke validates
the shipped image. Full CI coverage needs both.

Closes #349.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cmeans-claude-dev cmeans-claude-dev Bot requested a review from cmeans as a code owner April 21, 2026 16:53
@github-actions github-actions Bot added Awaiting CI Dev complete, waiting for CI/Codecov to pass before QA Ready for QA Dev work complete — QA can begin review and removed Awaiting CI Dev complete, waiting for CI/Codecov to pass before QA labels Apr 21, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 21, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@cmeans cmeans added the QA Active QA is actively reviewing; Dev should not push changes label Apr 21, 2026
@cmeans
Copy link
Copy Markdown
Owner

cmeans commented Apr 21, 2026

QA Active — reviewing the Python matrix extension (closes #349). Happy path: 3.13 and 3.14 both green on first try.

@github-actions github-actions Bot removed the Ready for QA Dev work complete — QA can begin review label Apr 21, 2026
Copy link
Copy Markdown
Owner

@cmeans cmeans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QA Review — Round 1

Verdict: Ready for QA Signoff.

Clean one-line matrix extension — and the load-bearing acceptance criterion already passed on this PR's own CI: both test (3.13) and test (3.14) are SUCCESS on their first run. No hidden dep/wheel compat issues surfaced. Happy path outcome from #349.

Steps verified

Step Result
1. YAML parse OK
2. Matrix lists 5 entries in order python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] ✓ (see note below — the PR body's grep command for this step has a small indent issue, so I used a corrected version)
3. CI runs 5 test jobs on this PR ✓ — test (3.10), test (3.11), test (3.12), test (3.13), test (3.14) all present in the check list
4. All five test jobs pass ✓ — all five SUCCESS
5. Lint/typecheck unchanged ✓ — lint 28s, typecheck 43s on this PR, consistent with recent main runs; both still pinned to 3.12
6. Diff stat ci.yml (+1, -1), CHANGELOG.md (+3) — exactly as described ✓

Minor observation (non-blocking)

The PR body's step-2 grep uses ^ matrix: (8 spaces), but matrix: sits at 6-space indent in ci.yml:62 inside strategy:matrix:. Running the command returns empty instead of the expected python-version: [...] line. Substantive property (matrix has 5 entries) is correct; only the verification regex is slightly off. Easy tidy if you want to fix it, but since the five matrix entries all actually ran and passed on this PR's CI, the substance of step 2 is demonstrated.

Other notes

  • pyproject.toml declares requires-python = ">=3.10" — metadata already allowed 3.13/3.14; CI now exercises them. No pyproject.toml change needed.
  • docker-smoke skipped as designed (no Dockerfile / pyproject.toml / uv.lock / .dockerignore / workflow-file-matching-its-trigger change).
  • CodeQL (actions) green — no new taint-flow sites introduced.

CI rollup on 5346ccce: all matrix test jobs + lint + typecheck + CodeQL + codecov + license/cla — all SUCCESS.

Maintainer to apply QA Approved.

@cmeans
Copy link
Copy Markdown
Owner

cmeans commented Apr 21, 2026

Audit: applying Ready for QA Signoff as the final act on 5346ccce. Happy-path outcome — both test (3.13) and test (3.14) SUCCESS on first try; #349 closes cleanly with no dep/wheel triage surfaced. Non-blocking observation in the review about the step-2 grep command indent being slightly off (6 vs 8 spaces); matrix content itself is correct. All 6 steps ticked. Removing QA Active, applying Ready for QA Signoff.

@cmeans cmeans added Ready for QA Signoff QA passed — ready for maintainer final review and merge and removed QA Active QA is actively reviewing; Dev should not push changes labels Apr 21, 2026
Copy link
Copy Markdown
Owner

@cmeans cmeans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@cmeans cmeans added QA Approved Manual QA testing completed and passed and removed Ready for QA Signoff QA passed — ready for maintainer final review and merge labels Apr 21, 2026
@cmeans-claude-dev cmeans-claude-dev Bot merged commit 99860de into main Apr 21, 2026
37 checks passed
@cmeans-claude-dev cmeans-claude-dev Bot deleted the ci/python-matrix-extension branch April 21, 2026 17:52
cmeans-claude-dev Bot added a commit that referenced this pull request Apr 21, 2026
Follows up on Dependabot
[#346](#346) (closed
unmerged pending CI matrix coverage).

## Summary

One-line change in `Dockerfile`:

\`\`\`diff
-FROM python:3.12-slim
+FROM python:3.13-slim
\`\`\`

Plus a `CHANGELOG.md` `### Changed` entry.

### Why 3.13 and not 3.14

- **3.13** — GA October 2024, ~5 years of upstream support (EOL October
2029), well-represented in wheel coverage across our deps. Safe bump.
- **3.14** — only GA'd October 2026. Our own suite passes (see #354's
matrix), but transitive tooling outside our direct deps (container
probes, operator scripts, downstream self-hoster environments) lags.
Deferring until 3.14-slim has broader ecosystem saturation — revisit in
a few months.

### Coverage this relies on

- **#354 / #349** (merged `99860de`) — CI test matrix now exercises
3.13, so the Python version the image ships is the Python version the
test suite ran on.
- **#348 / #350** — `docker-smoke.yml` workflow fires on any
`Dockerfile` change, building the image and running import +
console-script smokes inside it. That will validate this PR end-to-end.

### What stays unchanged

- `pyproject.toml` — `requires-python = ">=3.10"`; no metadata change.
- `ci.yml` — `lint` / `typecheck` / `codecov` jobs still pinned to 3.12;
`test` matrix still covers 3.10–3.14.
- `docker-compose.yaml`, `docker-publish.yml` — untouched.
- `uv.lock` — untouched; all deps already support 3.13.

## Risks and unknowns

**Happy path:** `docker-smoke` green → merge. Image is marginally larger
on first pull (new base layer) but subsequent pulls share layers as
usual.

**Unhappy path:** `docker-smoke` catches something that the
`actions/setup-python` matrix didn't. Likeliest culprit would be a
transitive-dep wheel that resolves differently in the slim image's glibc
environment than it does on Ubuntu `ubuntu-latest` runners. Triage
per-finding.

## Scope

- `Dockerfile` — `+1, -1` (FROM line)
- `CHANGELOG.md` — `+3` (new `### Changed` entry under `[Unreleased]`)

No source, no tests, no compose changes, no migrations.

## References

- Follows up on closed Dependabot
[#346](#346)
- Relies on merged
[#354](#354) (3.13 matrix
entry) and merged
[#350](#350) (docker-smoke
workflow)

## QA

### Prerequisites

None. The `docker-smoke.yml` workflow runs automatically on any PR
touching `Dockerfile`.

### Automated checks

- **`docker-smoke` — load-bearing.** Builds the image and runs:
  - `python -c 'import mcp_awareness'`
  - `python -c 'from mcp_awareness import server'`
- `command -v` on all six console scripts (`mcp-awareness`,
`mcp-awareness-migrate`, `mcp-awareness-user`, `mcp-awareness-token`,
`mcp-awareness-secret`, `mcp-awareness-register-schema`)
- positive check that `docker-entrypoint.sh` has a valid shebang and
executable bit
- `test (3.10 / 3.11 / 3.12 / 3.13 / 3.14)` — unchanged by this PR but
re-runs on CI; expected green.
- `lint`, `typecheck`, `codecov/patch` — still pinned to 3.12;
unchanged.
- `CodeQL (actions)` — no workflow files touched; re-scans diff only.

### Manual tests (via MCP tools)

This PR changes the shipped container only. There are no new MCP tools
or behavior changes to exercise — the awareness tool surface is
identical on 3.13-slim as it was on 3.12-slim. Listing the checks here
for reviewer audit:

1. - [x] **`docker-smoke` all four sub-checks pass** on the PR run.
Verify in the Actions tab that each smoke step shows green.

2. - [x] **Container boots cleanly** against a throwaway Postgres (CI
environment or local). Optional belt-and-suspenders sanity check:
     \`\`\`
     docker build -t awareness-test .
docker run --rm awareness-test python -c 'from mcp_awareness import
server; print("ok")'
     \`\`\`
     Expected: `ok` printed, exit 0.

3. - [x] **Image base is Python 3.13.** Verify the built image reports
the expected Python version:
     \`\`\`
     docker run --rm awareness-test python --version
     \`\`\`
     Expected: `Python 3.13.x`.

4. - [x] **No stray file changes.** `git diff --stat origin/main` shows
exactly `Dockerfile` (+1, -1) and `CHANGELOG.md` (+3). Nothing else.

### Acceptance

- ✅ `docker-smoke` green — **load-bearing**
- ✅ Base image aligned with CI-covered Python version (3.13 now in
matrix per #354)
- ✅ `requires-python` floor unchanged; no consumer-facing metadata shift
- ✅ Single-concern diff; no test, source, or compose changes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: cmeans-claude-dev[bot] <3223881+cmeans-claude-dev[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cmeans-claude-dev cmeans-claude-dev Bot mentioned this pull request Apr 22, 2026
cmeans-claude-dev Bot added a commit that referenced this pull request Apr 22, 2026
Patch release stamping six PRs merged to `main` since v0.18.1 on
2026-04-20.

## Summary

Two-file diff:

- `pyproject.toml` — `version` bump `0.18.1` → `0.18.2`
- `CHANGELOG.md` — `[Unreleased]` renamed to `[0.18.2] - 2026-04-21`;
new empty `[Unreleased]` section seeded; comparison-link footer updated

## Why patch

- No new MCP tools, no changed tool signatures, no resource changes.
- No breaking config, no migration, no data-format change.
- `requires-python = ">=3.10"` floor unchanged in `pyproject.toml`.
- Dockerfile base bump (3.12 → 3.13) is runtime-transparent to image
consumers; CI matrix widening (3.13, 3.14) is pure infra.
- OAuth log-redaction is security-hardening with no behavior change on
the happy path.
- `docker-compose` host-port parameterization is backward-compatible —
default behavior unchanged.

Textbook patch bump for a 0.x project.

## Included PRs

| PR | Title | Kind |
|---|---|---|
| [#351](#351) | ci: cascade
env-routing to `pr-labels.yml` + workflow permissions | Security |
| [#352](#352) | fix(oauth):
redact URLs in log output (CodeQL #5-#9) | Security |
| [#350](#350) | ci: add
`docker-smoke` workflow — build + import smoke on Dockerfile PRs | Added
|
| [#353](#353) |
chore(compose): parameterize host port in `docker-compose.yaml` |
Changed |
| [#354](#354) | ci: extend
Python test matrix to include 3.13 and 3.14 | Added |
| [#355](#355) |
chore(docker): bump base image from `python:3.12-slim` to `3.13-slim` |
Changed |

All six merged via their own QA-Approved cycles — nothing in this
release bypasses the standard pipeline.

## What's unchanged

- `docker-compose.yaml` — uses `:latest`, no version bump needed
- `README.md` — tool count (32) and text-mode content unchanged; no
update needed
- `uv.lock` — no dep changes in any of the six PRs

## QA

Lightweight per project convention — all substantive code was tested in
its own PR. Review-only checks:

1. - [x] **`pyproject.toml` version** is `0.18.2`. Verify line 3:
`version = "0.18.2"`.
2. - [x] **CHANGELOG** — `[0.18.2] - 2026-04-21` heading exists; the six
rolled-up entries sit beneath it in their original order (Changed →
Added → Changed → Security → Security → Added); empty `[Unreleased]`
seeded above.
3. - [x] **Comparison links** — `[0.18.2]: …v0.18.1...v0.18.2` added;
`[Unreleased]` now points at `v0.18.2...HEAD`.
4. - [ ] **Scope** — `git diff --stat origin/main` shows exactly
`CHANGELOG.md` (+4, -1) and `pyproject.toml` (+1, -1). Nothing else.
5. - [x] **No accidental content drift in rolled-up entries** — diff
between this branch's `[0.18.2]` section and what was in `[Unreleased]`
on `main` before this PR should be zero beyond the heading/anchor move.

### Acceptance

- ✅ CI green
- ☐ Merge + tag (Dev authorization, executed post-merge)

## Merge + tag (Dev post-merge action)

After merge, Dev runs:

\`\`\`
git checkout main && git pull --ff-only origin main
git tag -a v0.18.2 -m "v0.18.2 — CI matrix widening (3.13/3.14),
Dockerfile to python:3.13-slim, docker-smoke workflow, compose host-port
parameterization, OAuth log redaction, workflow permission hardening"
git push origin v0.18.2
\`\`\`

The tag triggers \`docker-publish.yml\` to build and publish the
\`:v0.18.2\` + \`:latest\` images.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: cmeans-claude-dev[bot] <3223881+cmeans-claude-dev[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

QA Approved Manual QA testing completed and passed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ci: extend Python test matrix to include 3.13 and 3.14

1 participant