Guide

The oasdiff GitHub Action, step by step

Last checked 2026-11-0910 min read

The oasdiff GitHub Action is a set of free GitHub Actions from the oasdiff project that compare the OpenAPI spec in a pull request with the spec on the base branch and report breaking changes. This guide sets up its breaking action, explains each line of the workflow, shows where the results appear (annotations, the step output, a review link), and ends with what to do with each finding. The last step, telling the teams that call a changed endpoint, is where Graphwake comes in.

ExampleGitHub Actions · pull request #1284
  • Check out code2s
  • Run tests41s
  • Graphwake spec check1s
  • graphwake: spec sent (pull request #1284)
  • Build1m 12s
Build passed
In Graphwake: impact 79 HighThe teams that consume the endpoints were told.

If Graphwake can’t be reached, the step logs it and exits cleanly. The build carries on.

One step sends the spec. It never blocks a build. GitHub Actions, GitLab CI, Azure DevOps, Bitbucket Pipelines and Jenkins.
On this page
  1. What you need
  2. Step 1: add the workflow
  3. Step 2: decide what fails the job
  4. One failure fail-on does not control
  5. Step 3: open a pull request and read the output
  6. If specs must not leave your runners
  7. Step 4: tune it
  8. Step 5: what to do with the output
  9. Where Graphwake fits
  10. When the oasdiff Action alone is enough
  11. Next steps
  12. Questions

What you need

  • A GitHub repository with an OpenAPI 3 spec committed to it. The examples use openapi.yaml in the repository root; change the path to yours.
  • If your spec is generated from code, a build step that writes it to a file first. The action compares files, not code.
  • Nothing else: the free actions run the oasdiff CLI inside your runner, with no account and no token.

The repository oasdiff/oasdiff-action holds several actions, one per folder. This guide uses breaking. The others:

ActionWhat it doesFails the job
oasdiff/oasdiff-action/breaking@v0Breaking changes (errors and warnings), as annotations on the pull requestOnly with fail-on
oasdiff/oasdiff-action/changelog@v0Every change that can affect clients, breaking or notNo fail-on input
oasdiff/oasdiff-action/diff@v0The full diff, including description-only editsOnly with fail-on-diff: true
oasdiff/oasdiff-action/validate@v0Checks one spec against the OpenAPI rulesOn errors by default
See who your next breaking change reaches.Paste a spec URL or add one CI step. 7-day free trial. Cancel before day 7 and you pay nothing.
Start free trial

As read on the action’s README and action.yml files on 2026-11-09 (latest release v0.1.23). @v0 is a moving tag that follows every stable v0.x.y release; pin a release tag if you want to choose when to upgrade.

Step 1: add the workflow

Create .github/workflows/oasdiff.yaml with the README’s quick start:

yaml
name: oasdiff
on:
  pull_request:
    branches: [ "main" ]
permissions:
  contents: read
  pull-requests: write
jobs:
  breaking-changes:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - run: git fetch --depth=1 origin ${{ github.base_ref }}
      - uses: oasdiff/oasdiff-action/breaking@v0
        with:
          base: 'origin/${{ github.base_ref }}:openapi.yaml'
          revision: 'HEAD:openapi.yaml'
          fail-on: WARN
          github-token: ${{ github.token }}
From the oasdiff-action README, checked 2026-11-09. Replace openapi.yaml with your spec’s path in both places.
  1. on: pull_request

    Runs on every pull request into main. To skip pull requests that do not touch the spec, add paths: [ "openapi.yaml" ] under pull_request.

  2. permissions

    contents: read to check out the code. pull-requests: write lets the action post the review link as a pull request comment. Without it, the link goes to the job summary instead.

  3. actions/checkout, then git fetch

    Checkout gives you the pull request. The git fetch --depth=1 line fetches only the base branch, so the action can read the old spec from git. A full history (fetch-depth: 0) is not needed.

  4. base and revision

    Both use oasdiff’s <git ref>:<path> syntax: the spec on the base branch, and the spec in the commit being tested. Each also accepts a plain file path or an http(s) URL.

  5. fail-on

    Decides whether the job fails. Step 2 covers it. Leave it out and the action only reports.

  6. github-token

    The token used to post the review link as a comment. On pull requests from forks the token is read-only, so the link falls back to the job summary.

Step 2: decide what fails the job

oasdiff sorts each breaking change into a level: error (a client that followed the old contract can stop working), warning (it might; a human should look) and info (shown by changelog, not by breaking). fail-on picks the lowest level that fails the job:

fail-onJob fails whenUse it when
Not set (the default)Never because of a change foundYou are trying the action out, or the check should inform and not stop anyone
ERRThere is at least one errorYou want a hard stop on changes oasdiff is sure about
WARNThere is at least one error or warningEvery possible break needs a decision before the merge (the quick start’s choice)
Note

One failure fail-on does not control

If oasdiff cannot run at all, the step fails whatever fail-on says: a spec that does not parse, a file missing on one side, an external $ref it is not allowed to load. oasdiff exits with 2 or higher there, and the action passes that on. For a check that must never fail the job, add continue-on-error: true to the step as well; the non-blocking setup shows it.

Step 3: open a pull request and read the output

Change the spec on a branch and open a pull request. The examples below come from a sample openapi.yaml where the pull request makes a new query parameter region required on GET /orders, removes the old limit parameter, and drops the required status field from the GET /orders/{id} response.

1. Annotations on the pull request

The action makes a second oasdiff pass with --format githubactions. GitHub turns each line into an annotation on the Files changed tab and in the run’s summary, titled with the oasdiff rule ID:

text
::error title=new-required-request-parameter,file=openapi.yaml,line=24,col=12::in API GET /orders added the new required `query` request parameter `region`
::error title=response-required-property-removed,file=openapi.yaml::in API GET /orders/{id} removed the required property `status` from the response with the `200` status
::warning title=request-parameter-removed,file=openapi.yaml::in API GET /orders deleted the `query` request parameter `limit`
Example: the annotation lines for the sample change, from oasdiff 1.34.1. The action’s image ships oasdiff v1.37.0, so wording can differ slightly.

An added parameter has a line in the new file, so its annotation sits on that line. A removed field or parameter has no line in the new file, so its annotation has no position and GitHub shows it at the top of the file. Read the run summary as well as the diff view.

2. The full report

The step output breaking holds only the first line, the count (No breaking changes when there are none). For the whole report, set output-to-file: oasdiff-breaking.txt and upload that file as an artifact, or run the CLI locally:

text
3 changes: 2 error, 1 warning, 0 info
error	[new-required-request-parameter] at openapi.yaml
	in API GET /orders
		added the new required `query` request parameter `region`

error	[response-required-property-removed] at openapi.yaml
	in API GET /orders/{id}
		removed the required property `status` from the response with the `200` status

warning	[request-parameter-removed] at openapi.yaml
	in API GET /orders
		deleted the `query` request parameter `limit`
		This is a warning because some clients may return an error when receiving an unexpected parameter. It is recommended to deprecate the parameter first.
Example: oasdiff breaking main:openapi.yaml HEAD:openapi.yaml on the sample branch, oasdiff 1.34.1.

When there are breaking changes, the action uploads the two specs to oasdiff.com and posts a link to a side-by-side review in the job summary, and as a comment when the token allows. The specs are encrypted in CI first and the key stays in the link, so the server cannot read them; the link expires after 7 days. The URL is also the step output review_url.

Note

If specs must not leave your runners

Set review: false. Nothing is uploaded and no comment is posted; the detection and the annotations work the same.

Step 4: tune it

Keep settings in a .oasdiff.yaml file in the repository root instead of in each workflow. The actions read it after checkout; inputs set in the workflow’s with: win over the file.

yaml
# .oasdiff.yaml (repository root)
fail-on: ERR
err-ignore: ./oasdiff-err-ignore.txt
fail-on and err-ignore are keys from the README’s example. severity-levels (also there) raises or silences single rules.

When a breaking change is intended and agreed, an ignore file stops it from failing every later run. Each line is the method and path, then the change text as oasdiff printed it (warn-ignore does the same for warnings):

text
# oasdiff-err-ignore.txt: one accepted breaking change per line, with the PR that accepted it
# PR #1290: region is required from v2; the two known callers already send it
GET /orders added the new required `query` request parameter `region`
Example ignore file. With it, oasdiff 1.34.1 no longer reports the region change on the sample branch; the other two still show.

Two more inputs worth knowing. allow-external-refs is false in the action (the CLI’s default is true), so an untrusted pull request cannot make the runner fetch URLs; set it to true if your spec is split across files or references external URLs. composed: true compares many spec files at once; the side-by-side review is not available in that mode.

Step 5: what to do with the output

A red job tells the author something broke. It does not tell anyone what to do next. For each finding:

  1. Error: look for an additive change first

    Many errors have a non-breaking version: a new optional parameter instead of a required one, a new field next to the old one, a new endpoint or version. Ask for that first.

  2. Error you keep: name who calls the endpoint

    If the change has to break, list the teams that call the endpoint and tell them before the merge, with what changes and when. Then add the line to the ignore file in the same pull request, so the reason is in the history.

  3. Warning: decide and write it down

    request-parameter-removed is breaking only if the server rejects input it does not know. Check, and put the answer in the pull request description.

  4. No breaking changes: still read the changelog

    New endpoints and fields do not break anyone, but consumers may want them. The changelog action lists them.

The reviewer’s side of this, with a copyable pull request template, is the API breaking change checklist for pull requests. What each rule ID means, with before/after snippets, is in OpenAPI breaking changes.

Where Graphwake fits

The action answers “what changed?” in the pull request. Step 5’s hardest line, “list the teams that call the endpoint”, is not in the spec. Graphwake keeps that list for you: its CI step checks the spec on every pull request, and Graphwake tells the teams that call each changed endpoint.

  • Breaking first, quiet by default

    Breaking changes alert, and removed endpoints and response fields always do. Additions stay quiet unless a team opts in.

  • Who is affected, per endpoint

    Consumer teams subscribe to the endpoints they call. The affected teams come from that map, not from memory.

  • Told while it is still a pull request

    With alerts on open pull requests turned on in settings, the subscribed teams hear about a breaking change before the merge, in Slack, Microsoft Teams or email.

  • Runs next to the action

    Graphwake’s CI step sends the spec and never fails or blocks a build, so the oasdiff Action can keep its own fail-on.

Good to know

When the oasdiff Action alone is enough

  • Every caller of the API is in the same repository, so the pull request’s reviewers are the people who need to know.
  • You want the merge to stop on a breaking change: fail-on does that, and oasdiff Pro adds approval per change.
  • You only need a diff and a changelog. The free actions cover that, with no account.

Next steps

Questions

What is the oasdiff GitHub Action called?

It is a repository of actions: oasdiff/oasdiff-action/breaking@v0 for breaking changes, plus changelog, diff and validate under the same path, all in the oasdiff/oasdiff-action repository.

Does the oasdiff Action fail the build on a breaking change?

Only if you set fail-on (ERR or WARN). Without it, the action reports and passes. It still fails if oasdiff cannot run, for example on a spec that does not parse.

Does the oasdiff Action send my spec anywhere?

By default, when it finds changes, it uploads both specs to oasdiff.com encrypted, for the side-by-side review link; the server cannot read them. Set review: false and nothing leaves the runner.

Can I ignore a breaking change we agreed on?

Yes. Put the method, path and change text in a file and pass it as err-ignore (errors) or warn-ignore (warnings), in the workflow or in .oasdiff.yaml.

Is the oasdiff Action free?

The breaking, changelog, diff and validate actions are free and need no account. oasdiff Pro adds per-change approval and a merge gate.

Pick an endpoint. See who it reaches. 7-day free trial. Cancel before day 7 and you pay nothing.

Start free trial

Sources and last verified

Sources checked on 2026-11-09.