Scaffold FastAPI + MySQL + Keycloak service with devcontainer
Sets up the project skeleton: - FastAPI app factory with lifespan, request-id middleware, and RFC 9457 problem+json error handlers - Async SQLAlchemy 2.0 over MySQL (asyncmy), with a constraint naming convention in place before the first migration and async Alembic - Keycloak as a pure resource server: OIDC discovery, cached JWKS with rotation-aware refresh, and require_roles dependencies - Devcontainer running MySQL 8.4 and Keycloak 26.7 as compose siblings, with the realm (clients, roles, test users) imported on first boot - Test suite covering the endpoints plus the token validator itself, exercised against a locally generated RSA keypair - uv packaging, ruff, mypy --strict, pre-commit, Gitea CI, prod Dockerfile Two Keycloak-in-containers traps are handled explicitly and documented in the README: the issuer/internal-URL split (the browser sees localhost:8080, the API sees keycloak:8080) and the audience mapper that stops Keycloak issuing tokens with aud=account. The devices resource is a placeholder proving the routing -> auth -> ORM -> migration path end to end; replace it with the real domain. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
commit
0526d34e42
52 files changed
+4433
No files matched your search
@@ -0,0 +1,54 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:8.4
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: rootpassword
|
||||
MYSQL_DATABASE: v2x_test
|
||||
MYSQL_USER: v2x
|
||||
MYSQL_PASSWORD: v2xpassword
|
||||
ports:
|
||||
- 3306:3306
|
||||
options: >-
|
||||
--health-cmd="mysqladmin ping -h 127.0.0.1 -uroot -prootpassword"
|
||||
--health-interval=5s
|
||||
--health-timeout=5s
|
||||
--health-retries=20
|
||||
|
||||
env:
|
||||
# CI reaches MySQL over the mapped port; Keycloak is never contacted
|
||||
# because the auth tests mint their own tokens against a stub JWKS.
|
||||
DATABASE_URL: mysql+asyncmy://v2x:[email protected]:3306/v2x_test?charset=utf8mb4
|
||||
TEST_DATABASE_URL: mysql+asyncmy://v2x:[email protected]:3306/v2x_test?charset=utf8mb4
|
||||
APP_ENV: test
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: astral-sh/setup-uv@v5
|
||||
with:
|
||||
version: "0.9.7"
|
||||
enable-cache: true
|
||||
|
||||
- run: uv sync --frozen
|
||||
|
||||
- name: Lint
|
||||
run: |
|
||||
uv run ruff check .
|
||||
uv run ruff format --check .
|
||||
|
||||
- name: Type check
|
||||
run: uv run mypy
|
||||
|
||||
- name: Test
|
||||
run: uv run pytest --cov --cov-report=term-missing
|
||||
Reference in new issue
Block a user