Skip to content

feat: commit OpenAPI spec with CI freshness check#220

Merged
declan-scale merged 5 commits intomainfrom
declan-scale/openapi-spec
May 5, 2026
Merged

feat: commit OpenAPI spec with CI freshness check#220
declan-scale merged 5 commits intomainfrom
declan-scale/openapi-spec

Conversation

@declan-scale
Copy link
Copy Markdown
Collaborator

@declan-scale declan-scale commented May 5, 2026

Summary

  • Adds agentex/openapi.yaml as the source-of-truth OpenAPI spec for the AgentEx backend.
  • Adds agentex/scripts/generate_openapi_spec.py to regenerate the spec from the FastAPI app.
  • Adds a CI job that regenerates the spec on every PR touching agentex/ and fails if the committed file is stale.
  • Splits the dual-method /forward/name/{agent_name}/{path} route into separate GET and POST handlers so each operation has a unique operationId and the generated spec is deterministic.
  • Pins pyyaml>=6.0,<7 as a real dependency.

Test plan

  • Verify the new openapi-spec CI job passes on this PR
  • Confirm the freshness check fails when the spec is intentionally stale (locally validated)

Greptile Summary

  • Adds agentex/openapi.yaml as the committed source-of-truth spec, a generate_openapi_spec.py script to regenerate it, a make gen-openapi target, and a pre-commit hook that auto-regenerates and stages the file on relevant source changes.
  • Adds a new openapi-spec CI job that regenerates the spec and fails if the committed file is stale; wires the result into the existing ci-status required check. The job now has timeout-minutes: 10.
  • Splits the /forward/name/{agent_name}/{path} route from a single dual-method api_route into dedicated @router.get and @router.post handlers, giving each a unique operationId in the generated spec.

Confidence Score: 5/5

Safe to merge — only a P2 style/consistency suggestion on missing --frozen flags in CI.

No P0 or P1 findings. The single P2 comment is about adding --frozen to uv sync and uv run in CI for consistency with the Makefile; it doesn't affect correctness in the common case. The route split, spec generation script, freshness check logic, and dependency pinning are all correct.

.github/workflows/ci.yml — the missing --frozen flags on the install and run steps.

Important Files Changed

Filename Overview
.github/workflows/ci.yml Adds openapi-spec job (with timeout-minutes: 10) that regenerates and diff-checks the spec; wires it into ci-status. uv sync runs without --frozen, creating a subtle inconsistency with the Makefile's --frozen usage.
agentex/scripts/generate_openapi_spec.py New generator script that imports the FastAPI app and writes its OpenAPI schema to a YAML file. Logic is correct and stable.
agentex/src/api/routes/agents.py Splits the dual-method api_route into separate @router.get and @router.post handlers for the /forward/name/{agent_name}/{path} endpoint; both handlers delegate identically to forward_agent_request, which is correct.
.pre-commit-config.yaml Adds agentex-openapi-spec hook that runs make gen-openapi && git add openapi.yaml on changes to agentex/src/ or the generator script. Uses language: system which requires uv and make on PATH.
agentex/Makefile Adds gen-openapi target using uv run --frozen; clean and consistent with project conventions.
agentex/pyproject.toml Adds pyyaml>=6.0,<7 as a proper pinned runtime dependency so CI resolves it from the lockfile rather than ad-hoc.
agentex/openapi.yaml New generated OpenAPI 3.1.0 spec (~6040 lines); content correctly reflects all routes including the split GET/POST forward handlers with unique operationId values.

Sequence Diagram

sequenceDiagram
    participant Dev as Developer
    participant PC as pre-commit hook
    participant CI as CI openapi-spec job
    participant Repo as Repository

    Dev->>PC: git commit (agentex/src/** changed)
    PC->>PC: cd agentex && make gen-openapi
    PC->>PC: git add openapi.yaml
    PC-->>Dev: commit proceeds (spec auto-staged)

    Dev->>Repo: push PR

    Repo->>CI: trigger (agentex changes detected)
    CI->>CI: uv sync
    CI->>CI: uv run generate_openapi_spec.py
    CI->>CI: git diff --exit-code openapi.yaml
    alt spec is fresh
        CI-->>Repo: openapi-spec job = success
    else spec is stale
        CI-->>Repo: openapi-spec job = failure
    end
    Repo->>CI: ci-status checks openapi-spec.result
Loading

Fix All in Cursor Fix All in Claude Code Fix All in Codex

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
.github/workflows/ci.yml:192-198
The `uv sync` and `uv run` steps don't pass `--frozen`, but the Makefile (the developer-facing equivalent) uses `uv run --frozen`. Without `--frozen`, if `pyproject.toml` has drifted from `uv.lock` (e.g., because a PR bumps a dep and forgets to commit the updated lockfile), uv will silently re-resolve and install a different set of packages — meaning the spec is generated from a different pyyaml version than what the developer committed against. This can produce spurious freshness failures since pyyaml has changed YAML serialization across minor releases.

```suggestion
    - name: Install dependencies
      working-directory: ./agentex
      run: uv sync --frozen

    - name: Regenerate OpenAPI spec
      working-directory: ./agentex
      run: uv run --frozen python scripts/generate_openapi_spec.py --output openapi.yaml
```

Reviews (4): Last reviewed commit: "chore(pre-commit): don't update uv.lock" | Re-trigger Greptile

Adds agentex/openapi.yaml as the source-of-truth Stainless input, plus a
CI job that regenerates the spec on every PR touching agentex/ and fails
if the committed file is stale. Downstream consumers (Stainless build
workflow in scaleapi/agentex) can read this file directly via the public
submodule mirror without re-running spec generation themselves.
@declan-scale declan-scale requested a review from a team as a code owner May 5, 2026 18:11
Comment thread .github/workflows/ci.yml Outdated
Comment thread .github/workflows/ci.yml
- Split the dual-method /forward/name route into separate GET and POST
  handlers. The previous single function with methods=["GET","POST"]
  produced two operations with identical operationIds, making the
  generated spec non-deterministic between runs (route iteration order
  is unstable).
- Pin pyyaml as a real dependency (>=6.0,<7) instead of resolving it
  ad-hoc with --with pyyaml, which would re-resolve to the latest
  release on every CI run and could spuriously fail the freshness check
  if pyyaml ships a serialization change.
- Add timeout-minutes: 10 to the openapi-spec job so a hung uv sync or
  app import can't consume the 6-hour default.
@declan-scale declan-scale merged commit 30904e9 into main May 5, 2026
31 checks passed
@declan-scale declan-scale deleted the declan-scale/openapi-spec branch May 5, 2026 19:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants