Skip to content

fix(tests): restore CI compat with pyjwt 2.13 and fastapi 0.137 - #206

Merged
Zingzy merged 2 commits into
mainfrom
fix/ci-pyjwt-fastapi-test-compat
Jun 14, 2026
Merged

fix(tests): restore CI compat with pyjwt 2.13 and fastapi 0.137#206
Zingzy merged 2 commits into
mainfrom
fix/ci-pyjwt-fastapi-test-compat

Conversation

@Zingzy

@Zingzy Zingzy commented Jun 14, 2026

Copy link
Copy Markdown
Member

Why

The dependency upgrade in #204 turned main CI red — 7 tests fail in the Tests & Coverage job. This is test-only; production is unaffected (routing verified working, Deploy to Production passed on the same commit, and all 1647 non-affected tests stayed green). The fail-fast matrix made it look like a flaky single-version failure — really every Python version fails identically; the first to trip cancels the rest.

Root causes (both from #204 bumps)

  1. pyjwt 2.12.1 → 2.13.0 now raises InvalidKeyError: HMAC key must not be empty. The 4 JWT tests in tests/integration/test_security.py sign with jwt_secret, which is "" in CI (no JWT_SECRET env var, and .env is gitignored). 2.12.1 silently tolerated the empty key.
  2. fastapi 0.136.1 → 0.137.0 no longer flattens include_router() routes into app.routes; they now appear as _IncludedRouter wrapper nodes. The 3 route smoke tests in tests/smoke/test_routes_registered.py filter app.routes for APIRoute and found zero.

Fix (test-only, ~40 lines, 2 files)

  • tests/conftest.py: os.environ.setdefault("JWT_SECRET", ...) before any test builds AppSettings(), so token signing/verification have a non-empty key everywhere.
  • tests/smoke/test_routes_registered.py: walk the _IncludedRouter tree (accumulating .include_context.prefix) to reconstruct full paths + methods (incl. auto-HEAD), with a clean fallback to flat APIRoutes on older FastAPI.

Verification

1654 passed in 16.02s   (was 1647 passed, 7 failed)

The 7 previously-failing tests now pass; no other test changed. No production code touched.

Summary by Sourcery

Restore CI test compatibility with updated pyjwt and FastAPI dependencies by adjusting JWT test configuration and route discovery logic.

Bug Fixes:

  • Ensure tests use a non-empty JWT secret so pyjwt 2.13 token signing and verification succeed in CI.
  • Update route discovery in smoke tests to correctly traverse included routers under FastAPI 0.137 while remaining compatible with older versions.

Tests:

  • Refine helper for collecting API routes in smoke tests to handle nested included routers and reconstructed method sets across FastAPI versions.
  • Set a default JWT_SECRET in test configuration to stabilize JWT-related integration tests across environments.

Summary by CodeRabbit

  • Tests
    • Updated the test configuration to ensure JWT signing uses a stable, non-empty secret in the test environment.
    • Improved route-registration checks to correctly validate registered API paths and HTTP methods across different FastAPI routing layouts.

The dependency upgrade (#204) bumped pyjwt 2.12.1->2.13.0 and fastapi
0.136.1->0.137.0, breaking 7 tests. Both are test-only — production is
unaffected (routing verified working, Deploy to Production passed on the
same commit, 1647 non-affected tests stayed green).

- pyjwt 2.13 now raises InvalidKeyError on empty HMAC keys. The JWT
  security tests sign tokens with jwt_secret, which is "" in CI (no
  JWT_SECRET env var and .env is gitignored). Set a non-prod JWT_SECRET
  in the root conftest, before any test constructs AppSettings().

- fastapi 0.137 no longer flattens include_router() routes into
  app.routes; included routers appear as _IncludedRouter wrappers with
  the prefix on .include_context. Rebuild full paths (incl. HEAD) by
  walking that tree in the route-registration smoke test.
Copilot AI review requested due to automatic review settings June 14, 2026 19:45
@sourcery-ai

sourcery-ai Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Test-only fixes to restore CI after upgrading to pyjwt 2.13.0 and fastapi 0.137.0 by ensuring JWT tests use a non-empty secret and updating route discovery logic to handle FastAPI’s new _IncludedRouter structure while remaining backward-compatible.

File-Level Changes

Change Details Files
Ensure JWT-based tests use a non-empty signing key so pyjwt 2.13.0 no longer raises InvalidKeyError in CI.
  • Set a default JWT_SECRET environment variable at test startup when it is missing, before any AppSettings() instantiation.
  • Rely on this default so all tests that sign/verify JWTs behave consistently across local and CI environments.
tests/conftest.py
Update route introspection helper used by smoke tests to work with FastAPI 0.137.0’s nested _IncludedRouter structure while remaining compatible with older FastAPI versions.
  • Introduce a _ResolvedRoute NamedTuple representing a flattened route with full path and methods.
  • Replace the simple APIRoute filter with a recursive _get_api_routes implementation that walks app.routes, accumulating include_router prefixes and collecting APIRoute nodes from nested original_router.routes.
  • Preserve behavior on older FastAPI versions by treating direct APIRoute instances in app.routes as before, while just ignoring non-APIRoute, non-_IncludedRouter entries such as mounts/statics.
tests/smoke/test_routes_registered.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6e56419c-c86d-4141-87d0-5a4c5232b11a

📥 Commits

Reviewing files that changed from the base of the PR and between 30f69af and 6ffb5f3.

📒 Files selected for processing (2)
  • tests/conftest.py
  • tests/smoke/test_routes_registered.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/conftest.py

📝 Walkthrough

Walkthrough

Two test infrastructure fixes: conftest.py sets a default JWT_SECRET environment variable to prevent pyjwt HMAC empty-key errors, and the smoke test's _get_api_routes() is rewritten to recursively traverse the FastAPI routing tree using include_context.prefix, replacing a flat app.routes filter.

Changes

Test Infrastructure Fixes

Layer / File(s) Summary
Default JWT_SECRET in conftest
tests/conftest.py
Adds os.environ.setdefault("JWT_SECRET", "test-jwt-secret-not-for-production") before AppSettings() construction, preventing empty-key HMAC signing failures introduced by newer pyjwt behavior.
Recursive route traversal in smoke test
tests/smoke/test_routes_registered.py
Introduces _ResolvedRoute (NamedTuple with path: str, methods: frozenset[str]) and rewrites _get_api_routes() to recursively walk the FastAPI routing tree, accumulating include_context.prefix values to rebuild fully-qualified paths instead of filtering the flat app.routes list.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐇 A secret for the JWT, a path for every route,
No empty keys to trip me up, no tree left without a sprout.
I hop through nested routers now, accumulating prefix strings,
The smoke test sees the full-formed paths — oh, what recursion brings!
✨ All routes resolved, all tokens signed — a tidy warren rings!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: fixing test compatibility issues with upgraded dependencies (pyjwt 2.13 and fastapi 0.137).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ci-pyjwt-fastapi-test-compat

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@Zingzy Zingzy moved this to 🏗️ In Progress in spoo.me Development Roadmap Jun 14, 2026
@Zingzy Zingzy self-assigned this Jun 14, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Restores test-suite compatibility with recent dependency upgrades (PyJWT 2.13+ and FastAPI 0.137+) so CI passes again without production code changes.

Changes:

  • Set a default non-empty JWT_SECRET for tests to prevent PyJWT 2.13 from rejecting empty HMAC keys.
  • Update smoke-test route discovery to correctly traverse FastAPI 0.137’s included-router wrapper nodes and reconstruct full paths/methods.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
tests/conftest.py Ensures tests have a JWT secret set before AppSettings() is instantiated.
tests/smoke/test_routes_registered.py Reworks route collection to flatten included routers under FastAPI 0.137 while remaining compatible with older versions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/conftest.py Outdated
Comment thread tests/smoke/test_routes_registered.py Outdated
- conftest: set JWT_SECRET when missing OR empty (setdefault would keep an
  explicit JWT_SECRET="", still tripping pyjwt 2.13's empty-key guard).
- smoke: store route methods as an immutable frozenset in _ResolvedRoute
  (a set inside a NamedTuple is mutable and makes the tuple non-hashable).
@Zingzy
Zingzy merged commit 5fb79f9 into main Jun 14, 2026
12 of 13 checks passed
@github-project-automation github-project-automation Bot moved this from 🏗️ In Progress to ✔️ Done in spoo.me Development Roadmap Jun 14, 2026
@Zingzy
Zingzy deleted the fix/ci-pyjwt-fastapi-test-compat branch August 16, 2026 12:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: ✔️ Done

Development

Successfully merging this pull request may close these issues.

2 participants