feat(api): OpenAPI Pydantic codegen + CI drift check (PLAN 3.5)#10
Merged
feat(api): OpenAPI Pydantic codegen + CI drift check (PLAN 3.5)#10
Conversation
Add datamodel-code-generator, scripts/generate_openapi_models.py, and committed recipes_api/generated/openapi_models.py from packages/openapi. New workflow regenerates models and fails on git diff under generated/. Document pnpm generate:openapi-models in apps/api README; mark PLAN 3.5 done. Made-with: Cursor
There was a problem hiding this comment.
Pull request overview
Implements PLAN §3.5 by adding a reproducible OpenAPI→Pydantic code generation flow for the API package, committing the generated output, and introducing CI to detect spec/codegen drift.
Changes:
- Add a Python script +
pnpmscript to generate Pydantic v2 models frompackages/openapi/openapi.yamlusingdatamodel-code-generator. - Commit generated models under
apps/api/recipes_api/generated/and document regeneration steps. - Add a GitHub Actions workflow that regenerates models in CI and fails if the working tree differs from the committed generated output.
Reviewed changes
Copilot reviewed 6 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| PLAN.md | Marks §3.5 as complete. |
| apps/api/scripts/generate_openapi_models.py | Adds deterministic codegen script (stable flags, Python 3.12 target). |
| apps/api/recipes_api/generated/openapi_models.py | Committed generated Pydantic models mirroring the OpenAPI schemas. |
| apps/api/recipes_api/generated/init.py | Marks the generated package and discourages manual edits. |
| apps/api/README.md | Documents how to regenerate and how CI enforces drift checks. |
| apps/api/pyproject.toml | Adds datamodel-code-generator to API dev extras. |
| apps/api/package.json | Adds generate:openapi-models script for workspace usage. |
| .github/workflows/validate-openapi-python-codegen.yml | Adds CI job to regenerate + diff-check generated models. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Pin actions/setup-python@v6.2.0; set permissions.contents: read. - Fail on untracked/uncommitted files under recipes_api/generated/. - generate_openapi_models: reuse resolve_openapi_spec_path(); derive output path from script location. Made-with: Cursor
Made-with: Cursor
Made-with: Cursor
- Replace separate OpenAPI workflows with single ci.yml job - Add validate_openapi_generated.sh and turbo/root openapi:validate - Document pnpm lint, openapi:generate, openapi:validate in README Made-with: Cursor
- Move static recipes to apps/api/data; resolve_recipes_json_path + required StaticRecipeRepository(data_path=...) - Replace scripts/generate_openapi_models.py with recipes_api/openapi_codegen - Use .venv/bin/python for api package scripts; postinstall via bash -e -c - CI: setup-python before pnpm; pip install -e '.[dev]' into .venv - Harden validate_openapi_generated.sh for shellcheck - Web package: placeholder openapi:generate / openapi:validate for turbo Made-with: Cursor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 20 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
apps/api/pyproject.toml:16
- PR description calls
datamodel-code-generatora dev dependency, but it’s been added to the mainproject.dependencies(runtime) here. If the intent is tooling-only, consider moving it to an extra (e.g.[project.optional-dependencies].codegenordev) and updating thepostinstall/ CI install step to install that extra; otherwise please align the PR description/docs with this being a runtime dependency.
requires-python = ">=3.12"
dependencies = [
"datamodel-code-generator==0.26.5",
"fastapi==0.115.12",
"pyyaml==6.0.2",
"uvicorn[standard]==0.34.3",
]
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…step names Made-with: Cursor
- validate_openapi_generated: use git diff --quiet with actionable messages; PORCELAIN in UPPER_SNAKE_CASE - Rename bundled recipes test to test_resolve_recipes_json_path_loads_recipes Made-with: Cursor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Delivers PLAN §3.5: committed Pydantic models generated from the shared OpenAPI spec, CI that fails on drift, and supporting monorepo tooling so
pnpm/ Turborepo drive Python codegen and checks from the repository root.OpenAPI → Pydantic
datamodel-code-generatoris a normal dependency inapps/api/pyproject.toml.recipes_api/openapi_codegen.pycallsgenerate()programmatically (no reliance on adatamodel-codegenexecutable onPATH).recipes_api/generated/openapi_models.py(+generated/__init__.py).Recipe data layout
recipes.jsonlives underapps/api/data/(moved out ofrecipes_api/).recipes_api/data_paths.resolve_recipes_json_path()resolves the bundled file for editable installs vs wheel (force-includeinpyproject.tomlunchanged in effect).StaticRecipeRepositorynow requiresdata_path;recipes_routeswiresresolve_recipes_json_path().Monorepo scripts (root)
pnpm openapi:generate→turbo run openapi:generate(API runspython -m recipes_api.openapi_codegen).pnpm openapi:validate→turbo run openapi:validate(git drift check on generated output).apps/web: placeholderopenapi:generate/openapi:validateso Turbo has a consistent task graph.**
apps/apipackage scriptsbuild,dev,lint,test,openapi:generateuse.venv/bin/pythonso they matchpostinstall(editable install + deps in the venv).postinstall: create.venvif missing, then.venv/bin/python -m pip install -e .(bash -e -c '…').openapi:validate:bash scripts/validate_openapi_generated.sh(shellcheck-friendlygit statushandling).CI (
.github/workflows/ci.yml)actions/setup-python(3.12) beforepnpm installsopostinstall’s venv uses the intended Python.Install API dev dependencies:.venv/bin/python -m pip install -e ".[dev]"(pytest, etc. in the same env aspnpm test).pnpm lint,pnpm test,pnpm openapi:generate,pnpm openapi:validate.Docs
README.mdandapps/api/README.mdupdated for CI,pnpmscripts, venv, and data paths.Other
PLAN.md: §3.5 marked complete as appropriate for this PR.