Imported from yeongseon/azure-functions-openapi-python (
AGENTS.md). Install upstream withnpx skills add yeongseon/azure-functions-openapi-python. Copyright stays with the author.
AGENTS.md
Purpose
azure-functions-openapi provides OpenAPI generation and validation support for Python Azure Functions.
Read First
README.mdCONTRIBUTING.mddocs/agent-playbook.md
Working Rules
Test Coverage
- Maintain test coverage at 95% or above for committed changes and PRs.
- Run
hatch run pytest --cov --cov-report=term-missing -qto verify before submitting changes. - Any PR that drops coverage below 95% must include additional tests to compensate.
- Preserve the package's Python compatibility and public CLI behavior unless the change explicitly updates the contract.
- Keep documentation examples, generated schema expectations, and tests synchronized.
- Prefer focused changes inside the existing extension points.
Documentation & Translations
- English (
README.md) is the canonical source of truth for all documentation. Translated READMEs (README.ko.md,README.ja.md,README.zh-CN.md) are best-effort, community-maintained, and may lag the English source. - Translation sync is not required in the same PR as an English change, and a PR is never blocked by translation drift. Update translations opportunistically; when you do, keep them faithful to the current English source.
- Each translated README carries a staleness banner linking back to the canonical English README. Keep that banner in place so readers always know the translation may be out of date.
PR Workflow
Always issue-first. Before opening any PR:
- Run
gh issue listto check whether a tracking issue already exists for the change. - If no issue exists, create one following the Issue Conventions below before writing any code.
- Open the PR only after the issue exists. The PR body must include
Closes #Nfor every issue it resolves — never open a PR that cannot be traced back to an issue.
Non-negotiable: a PR without a linked issue will be rejected at review.
No merge before the review checklist is complete. Do not merge a PR until every item on its review checklist is checked off; an incomplete checklist blocks merge regardless of CI status.
Issue Conventions
Follow these conventions when opening issues so the backlog stays consistent with sibling DX Toolkit repositories.
Title
- Use Conventional Commit prefixes:
feat:,fix:,docs:,refactor:,test:,chore:,ci:,build:,perf:. - Add a scope qualifier when it narrows the area:
feat(cli):,docs(spec):,refactor(bridge):. - Keep the title imperative, under ~80 characters, no trailing period.
- Do not put
[P0]/[P1]/[P2](or any priority marker) in the title — priority is tracked with apriority:p0/priority:p1/priority:p2label.
Body
Use the following sections, in order, omitting any that do not apply:
## Context
What problem this issue addresses and why now. Note the target release (e.g. vX.Y.Z) here if known.
## Acceptance Checklist
- [ ] Concrete, verifiable items.
## Out of scope
- Items intentionally excluded, with links to the issues that track them.
## References
- PRs, ADRs, sibling issues, external docs.
Labels
- Apply at least one of
bug,enhancement,documentation,chore. - Apply exactly one
priority:p0/priority:p1/priority:p2label to record priority (replaces the old## Prioritybody line). - Add
area:*labels when they exist in the repository. - Use
blockeronly when the issue blocks a release.
Umbrella issues
When splitting a large piece of work into focused issues, keep the umbrella open as a tracker that links each child issue with a checkbox; close it once every child is closed or explicitly deferred.
Single-repo boundary (non-negotiable). An umbrella issue may only track child issues in this same repository. Do not open a tracker here that coordinates, checklists, or drives work in sibling repos (azure-functions-validation-python, azure-functions-logging-python, etc.), and do not ask another repo to host a tracker for this one. Each repository in the DX Toolkit is operated independently — it owns its own backlog, fix, verification, and release cadence.
- A bug that also exists in sibling repos is not one shared work item — it is N independent per-repo issues. File (or ask the maintainer to file) a separate issue in each affected repo; fix and release each on its own timeline.
- Cross-repo audit findings may be referenced from a local issue for context (a plain link is fine), but the local issue must be closeable on this repo's work alone. Never leave an issue here open pending another repo's fix.
- If you catch yourself building a checklist of
owner/other-repo#Nitems to "drive from here," stop — that is the cross-repo umbrella anti-pattern. Close it asnot plannedand let each repo track its own child issue.
Issue-creation access (fleet policy)
Keep issue creation open/unrestricted on every public toolkit repository (issue tracker enabled, no interaction-limits). External bug reports are the only inbound support channel, so restricting issue creation suppresses the signal we most need. Do not enable an interaction limit or restrict issue creation without an explicit, documented reason recorded in an issue first.
Project management model
This repository is issue-based, not milestone-based. Track and group work using issues plus the existing label taxonomy — do not introduce parallel structures.
- Plan and group multi-issue efforts with an umbrella tracker issue (see above) plus the existing
priority:p0/priority:p1/priority:p2labels. Do not create GitHub Milestones — none exist by design, and their absence is an intentional signal, not an oversight. - Do not invent new label taxonomies (e.g.
epic:*,vNext, release-tag labels) to group work. Reusepriority:*,area:*(only where they already exist), and the umbrella issue. Propose any new label in discussion and wait for explicit approval before creating it. - Treat optional or tentative suggestions ("we could…", "it might be nice to…", "~해도 괜찮아") as discussion, not a directive. Confirm intent before making any structural change to how work is tracked (milestones, labels, project boards, issue hierarchies).
- Before adding any organizational structure, check whether the repository already has an established convention. A category being empty or unused (zero milestones, no
epic:*labels) is evidence to follow the existing pattern, not to introduce a new one.
Validation
make testmake lintmake typecheckmake build
Release Process
- Version is managed via
hatch(dynamic fromsrc/azure_functions_openapi/__init__.py). - Do NOT manually edit version strings. Use the Makefile targets below. The public-API test reads
__version__againstimportlib.metadata.version(...), so no test changes are needed when bumping.
Commands
make release-patch— bump patch version, update changelog, tag, and pushmake release-minor— bump minor version, update changelog, tag, and pushmake release-major— bump major version, update changelog, tag, and pushmake release VERSION=x.y.z— set explicit version, update changelog, tag, and pushmake tag-release VERSION=x.y.z— create and push an annotated tag (used internally by release targets)
Flow
make release-patch(or-minor/-major) onmain- This runs:
hatch version→git commit→make changelog→git commit→git tag→git push - Tag push triggers the Publish to PyPI GitHub Actions workflow. Verification is a pre-publish gate, not a post-publish check. The
publishjob runs only afterbuild → lib-tests → cookbook-smoke → cookbook-host-smoke → verify-azure-certificationall pass, and it uploads the exact artifact that was tested (it never rebuilds). - Update
docs/changelog.mdseparately if needed (different format fromCHANGELOG.md).
Tiered runtime verification (what gates a release)
Release verification is layered; each tier catches a different failure class, and every tier is a pre-publish gate:
| Tier | Runs where | Catches |
|---|---|---|
lib-tests |
publish-pypi.yml (per publish) | library unit regressions |
cookbook-smoke |
publish-pypi.yml (per publish) | downstream import/registration drift |
cookbook-host-smoke |
publish-pypi.yml (per publish) | candidate wheel installs cleanly and a real func host + Azurite boots with it present, no cloud. NOTE: the cookbook HTTP examples do not import this package, so this is a host-boot smoke, not proof of this package's own runtime behavior (tracked separately) |
verify-azure-certification |
publish-pypi.yml (per publish) | requires a fresh, SHA+version-matched real-Azure certification for the exact release commit |
Azure Release Certification (e2e-azure.yml) |
workflow_dispatch, per release |
cloud-only drift — deploys to real Azure, runs live e2e, records a certification artifact. Certified per release, not per publish. |
Real-Azure certification (required once per release, before the final tag). Before pushing the release tag, dispatch the e2e-azure workflow on the exact release commit and version:
gh workflow run e2e-azure.yml --ref main -f ref=<release-sha> -f version=<x.y.z>- The run deploys to real Azure, executes the live e2e suite, and uploads the
azure-certartifact (keyed by commit SHA + version). verify-azure-certificationinpublish-pypi.ymllater requires a successful, SHA+version-matched, non-stale (<14 day) certification for the release commit; without it the publish gate fails and the version stays unpublished.
- Verify the release against the dogfood cookbook. Once Publish to PyPI succeeds, confirm the downstream consumer still passes on the freshly published version:
- In
azure-functions-cookbook-python, upgrade to the new release (hatch run pip install -U "azure-functions-openapi>=X.Y,<1") and runmake test. - Treat any new
RuntimeWarning/DeprecationWarningsurfaced by this library during the cookbook run as a release-blocking signal — decorator-order and API-drift problems are reported as warnings, so a clean run (zero warnings from this package) is part of the release gate. - If the cookbook pins a lower bound (
azure-functions-openapi>=X.Y,<1), bump it to the new minor in the same verification PR so examples are tested against the version they advertise. - A release is not considered done until the cookbook passes on the published version.
- In
Branch Hygiene
- Merged PR branches are deleted automatically ("Automatically delete head branches" is enabled on this repository); keep that setting on.
- When merging from the CLI, always pass
--delete-branch(e.g.gh pr merge --squash --delete-branch) so the head branch is removed. - Never delete
mainorgh-pages, and never delete a branch that still has an open PR. - Run
git fetch -pperiodically to prune stale local tracking refs.