From 41147bd76ad7ea2fb8594ab310e689ce0e3ca6db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Thu, 14 May 2026 17:40:17 +0200 Subject: [PATCH] ci(openapi): hard-fail on spec drift (was warn-only) The Security & Quality workflow ran the OpenAPI drift check with `continue-on-error: true` since v1.4.23 while the Zod registry caught up with the hand-maintained legacy spec. Coverage is now complete and the v1.5 iOS Swift codegen needs the contract pinned, so the gate flips to hard-fail: any route signature change without a regenerated `docs/api/openapi.yaml` blocks the merge. The CI error message points at `pnpm openapi:generate` and the registry under src/lib/openapi/ so the fix is self-evident. --- .github/workflows/security.yml | 16 +++++++--------- scripts/check-openapi.ts | 6 +++--- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 4ba396512..db696fb79 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -41,20 +41,18 @@ jobs: - name: Unit tests run: pnpm test - # v1.4.23 W4 F5c — OpenAPI spec drift check. + # OpenAPI spec drift gate — hard-fail (flipped from warn-only in v1.4.25). # - # `continue-on-error: true` is intentional for v1.4.23: the - # registry covers only the iOS-touched routes today, and the - # legacy hand-maintained spec at docs/api/openapi-v1422-legacy.yaml - # carries the rest. Once the registry hits ~95% coverage in - # v1.4.24+, flip this to a hard gate by removing - # `continue-on-error`. + # The Zod registry is the source of truth for the public API contract. + # Any route signature change must be reflected in `docs/api/openapi.yaml` + # so downstream consumers (notably the v1.5 iOS Swift codegen) stay in + # lockstep. If this step fails, run `pnpm openapi:generate` locally and + # commit the regenerated spec. - name: OpenAPI spec drift check - continue-on-error: true run: | pnpm openapi:generate if ! git diff --exit-code docs/api/openapi.yaml; then - echo "::warning::OpenAPI spec out of date. Run 'pnpm openapi:generate' locally and commit the changes." + echo "::error::OpenAPI drift detected — regenerate the spec via 'pnpm openapi:generate' and commit the result. The Zod registry under src/lib/openapi/ is the source of truth for the public API contract." exit 1 fi echo "::notice::OpenAPI spec in sync with Zod source schemas." diff --git a/scripts/check-openapi.ts b/scripts/check-openapi.ts index ccb870dfc..844320cb3 100644 --- a/scripts/check-openapi.ts +++ b/scripts/check-openapi.ts @@ -3,9 +3,9 @@ * Compare the freshly-generated OpenAPI spec against the committed * `docs/api/openapi.yaml`. Exits non-zero on drift. * - * Used by the CI gate in `.github/workflows/security.yml`. v1.4.23 runs - * the step with `continue-on-error: true` while the registry catches - * up with the hand-maintained spec; v1.4.24+ flips it to hard-fail. + * Used by the CI gate in `.github/workflows/security.yml`. Hard-fails on + * drift since v1.4.25 — the Zod registry is the source of truth for the + * public API contract that the v1.5 iOS Swift codegen consumes. */ import { readFileSync } from "node:fs"; import { resolve } from "node:path";