openapi-drift reads the routes your NestJS, Express, Fastify or Spring code actually declares, compares them with the document, and fails the build when they disagree, in either direction. No AI, no network, no build of your project.
$ openapi-drift check --spec openapi.yaml --source src --prefix /api openapi.yaml: 9 operations under /api src: 12 routes under /api In the code, not in the document (5): GET /api/health (src/health.controller.ts:5) HEAD /api/health (src/health.controller.ts:10) GET /api/legacy/ping (src/health.controller.ts:18) DELETE /api/users/{id} (src/users/users.controller.ts:27) — the path exists with GET, PATCH GET /api/v0/ping (src/health.controller.ts:18) In the document, not in the code (2): POST /api/orders (createOrder) — the path exists with GET GET /api/users/{id}/avatar (getAvatar) Path parameters named differently (1, not a failure): GET /api/orders/{id}/items: document {id}, code {orderId} (src/orders/orders.controller.ts:10) 7 drifts.
Everything built on the document is only as good as the document: generated tests, client SDKs, mocks, the reviewer reading it. A document that drifts from the code makes all of them wrong without anyone noticing.
Routes the code serves but the document does not describe, and operations the document promises but no route serves.
NestJS decorators, Express and Fastify calls and Spring annotations are read from the source text. Nothing is installed or started, so it runs in a second on any CI runner.
/users/{id} and /Users/:userId are the same route; the different parameter names are a note, not a
failure.
| NestJS |
@Controller('users'), @Controller({ path }), @Controller(['a', 'b']) with
@Get, @Post, @Put, @Patch, @Delete, @Head,
@Options, @All. The global prefix (setGlobalPrefix) and URI versions are read from the
code; --prefix is for a value the source does not show.
|
|---|---|
| Express |
app.get('/x', ...), router.post(...), app.route('/x').get().post(),
app.all, with routers mounted by app.use('/prefix', router) in the same file or imported from
another.
|
| Document |
OpenAPI 3.x, YAML or JSON. The base path of servers[0].url is applied. openapi-drift lint lists the
document's own problems first.
|
The action writes the Markdown report to the job summary and exposes the number of drifts; fail-on chooses which
direction fails the job.
- uses: vannt-dev/openapi-drift@v0
with:
spec: openapi.yaml
source: src
prefix: /api # optional
fail-on: any # or spec, code, none
Node.js 22.18 or newer.
$ npm install -g openapi-drift $ openapi-drift check --spec openapi.yaml --source src $ openapi-drift routes --source src # what the code declares $ openapi-drift lint --spec openapi.yaml # the document's own problems