J4 / UPGRADES
← All practice results

p2-04-fastapi

Public GitHub evidence ↗

# p2-04-fastapi — Batch 2 result: RED

Source: `nsidnev/fastapi-realworld-example-app` @ `029eb7781c60d5f563ee8990a0cbfb79b244538c` (MIT).
Owned fork: https://github.com/j4groupfounders/j4-p2b-fastapi
Locked target: fastapi 0.79.1 → 0.142.2.
Final evidence: [37552406701](https://github.com/j4groupfounders/j4-p2b-fastapi/actions/runs/37552406701) (failure); branch SHA `d17bc51c58c5e8f5f9218f5cf671abd4e8fad70e`.

## Outcome
**RED — stopped at the 12-CI-run cap with the migration incomplete.** 90 baseline project tests never fully ran green on the upgrade branch; no characterization or seeded-fault check was reached.

## What was repaired (agent edits, zero human edits)
1. `pyproject.toml`: added an explicit `setuptools` dependency — the GH Actions Python 3.11 bootstrap venv no longer bundles `pkg_resources`, which `aiosql` imports at runtime.
2. `pyproject.toml`: added two `filterwarnings` ignore entries (by message, not module — the stdlib `sre_constants` deprecation is raised with `stacklevel=2`, attributing it to the importing module rather than itself) for `pyparsing`'s transitive `sre_constants` import and for `pkg_resources`'s own "deprecated as an API" notice. The project's own `filterwarnings = ["error", ...]` policy is otherwise untouched — no warnings from app/test code are silenced.
3. `app/api/errors/validation_error.py` and `tests/test_api/test_errors/test_422_error.py`: migrated the renamed `starlette.status.HTTP_422_UNPROCESSABLE_ENTITY` → `HTTP_422_UNPROCESSABLE_CONTENT` (same numeric 422; try/except keeps the old name as a fallback for older starlette). No behavior change.

## Blocker (stop reason)
After the above repairs, project tests progressed from 0 passing (import-time crash) to 7 passing / 83 erroring with:
```
AttributeError: 'FastAPI' object has no attribute 'add_event_handler'
```
FastAPI 0.142.2 removed the deprecated `@app.on_event(...)`/`add_event_handler` startup-event API entirely; `app/main.py` (or a dependency using the same pattern) still calls it. The project needs to be migrated to the ASGI `lifespan` context-manager pattern (`@asynccontextmanager` + `FastAPI(lifespan=...)`). This is a real, bounded, known migration step — not attempted because the 12th and final preregistered CI run was already consumed confirming the blocker; per protocol ("stop early for a clear migration blocker; failed registered attempts remain in the denominator") no further run was spent.

## CI accounting
12 CI runs (3 screening/baseline + 9 upgrade attempts), 12.85 job-minutes, 37.8 wall-minutes (preregistration to terminal run). No paid runner/services/model calls; incremental vendor spend $0.

## Not reached
Characterization/HTTP snapshot replay and the five preregistered seeded faults (tags-content, article-count, http-error-status, validation-status, auth-error-message) were never run — no pass claimed on any of them.

## Next-batch suggestion
Re-register (or extend) with a fresh CI-run budget once `app/main.py`'s startup/shutdown handlers are converted to `lifespan`; the rest of the migration (dependency pins, warning filters, 422 constant) is already done on this branch and did not need further repair.