Skip to content

A diff tool for OpenAPI Specification 3

License

Notifications You must be signed in to change notification settings

speakeasy-api/oasdiff

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CI codecov Go Report Card GoDoc Docker Image Version

OpenAPI Diff

A diff tool for OpenAPI Spec 3.

Features

  • Generate a diff report in YAML, Text/Markdown or HTML
  • Run from Docker
  • Embed in your go program
  • Compare specs from the file system or over http/s
  • Compare specs in YAML or JSON format
  • Comprehensive diff including all aspects of OpenAPI Specification: paths, operations, parameters, request bodies, responses, schemas, enums, callbacks, security etc.
  • Detect breaking changes (Beta feature. Please report issues)

Build

git clone https://github.com/Tufin/oasdiff.git
cd oasdiff
go build

Usage

./oasdiff -help

-base string
    path of original OpenAPI spec in YAML or JSON format
-breaking-only
    display breaking changes only
-exclude-description
    exclude changes to descriptions
-exclude-examples
    exclude changes to examples
-fail-on-diff
    fail with exit code 1 if a difference is found
-filter string
    regex to filter result paths (optional)
-format string
    output format: yaml, text or html (default "yaml")
-prefix string
    path prefix that exists in base spec but not the revision (optional)
-revision string
    path of revised OpenAPI spec in YAML or JSON format
-summary
    display a summary of the changes instead of the full diff

All arguments can be passed with one or two leading minus signs.
For example -breaking-only and --breaking-only are equivalent.

Usage Examples

YAML diff of local files:

./oasdiff -base data/openapi-test1.yaml -revision data/openapi-test2.yaml

The default output format is YAML.
No output means that the diff is empty, or, in other words, there are no changes.

Text/Markdown diff of local files:

./oasdiff -format text -base data/openapi-test1.yaml -revision data/openapi-test2.yaml

The Text/Markdown diff report provides a simplified view of the changes.
To view all details, use the default format: YAML.

HTML diff of local files:

./oasdiff -format text -base data/openapi-test1.yaml -revision data/openapi-test2.yaml

The HTML diff report provides a simplified view of the changes.
To view all details, use the default format: YAML.

Text/Markdown diff of http files:

./oasdiff -format text -base https://raw.githubusercontent.com/Tufin/oasdiff/main/data/openapi-test1.yaml -revision https://raw.githubusercontent.com/Tufin/oasdiff/main/data/openapi-test3.yaml

Display breaking changes only:

./oasdiff -breaking-only -format text -base https://raw.githubusercontent.com/Tufin/oasdiff/main/data/openapi-test1.yaml -revision https://raw.githubusercontent.com/Tufin/oasdiff/main/data/openapi-test3.yaml

Display changes to endpoints containing /api in the path:

./oasdiff -breaking-only -format text -filter "/api" -base https://raw.githubusercontent.com/Tufin/oasdiff/main/data/openapi-test1.yaml -revision https://raw.githubusercontent.com/Tufin/oasdiff/main/data/openapi-test3.yaml

Display change summary:

./oasdiff -breaking-only -summary -base https://raw.githubusercontent.com/Tufin/oasdiff/main/data/openapi-test1.yaml -revision https://raw.githubusercontent.com/Tufin/oasdiff/main/data/openapi-test3.yaml

Running with Docker

To run with docker just replace the ./oasdiff command by docker run --rm -t tufin/oasdiff, for example:

docker run --rm -t tufin/oasdiff -format text -base https://raw.githubusercontent.com/Tufin/oasdiff/main/data/openapi-test1.yaml -revision https://raw.githubusercontent.com/Tufin/oasdiff/main/data/openapi-test3.yaml

Comparing local files with Docker:

docker run --rm -t -v $(pwd)/data:/data:ro tufin/oasdiff -base /data/openapi-test1.yaml -revision /data/openapi-test3.yaml

Replace $(pwd)/data by the path that contains your files. Note that the -base and -revision paths must begin with /.

Output example - Text/Markdown

./oasdiff -format text -base data/openapi-test1.yaml -revision data/openapi-test5.yaml

New Endpoints: None


Deleted Endpoints: 2


POST /register POST /subscribe

Modified Endpoints: 2


GET /api/{domain}/{project}/badges/security-score

  • Modified query param: filter
    • Content changed
      • Modified media type: application/json
        • Schema changed
          • Required changed
            • New required property: type
  • Modified query param: image
  • Modified query param: token
    • Schema changed
      • MaxLength changed from 29 to
  • Modified header param: user
    • Schema changed
      • Schema added
    • Content changed
      • Deleted media type: application/json
  • Modified cookie param: test
    • Content changed
      • Modified media type: application/json
        • Schema changed
          • Type changed from 'object' to 'string'
  • Responses changed
    • New response: default
    • Deleted response: 200
    • Modified response: 201
      • Content changed
        • Modified media type: application/xml
          • Schema changed
            • Type changed from 'string' to 'object'

GET /api/{domain}/{project}/install-command

  • Deleted header param: network-policies
  • Responses changed
    • Modified response: default
      • Description changed from 'Tufin1' to 'Tufin'
      • Headers changed
        • Deleted header: X-RateLimit-Limit

Output example - YAML

./oasdiff -base data/openapi-test1.yaml -revision data/openapi-test5.yaml

info:
  title:
    from: Tufin
    to: Tufin1
  contact:
    added: true
  license:
    added: true
  version:
    from: 1.0.0
    to: 1.0.1
paths:
  deleted:
    - /register
    - /subscribe
  modified:
    /api/{domain}/{project}/badges/security-score:
      operations:
        modified:
          GET:
            tags:
              deleted:
                - security
            parameters:
              modified:
                cookie:
                  test:
                    content:
                      mediaTypeModified:
                        application/json:
                          schema:
                            type:
                              from: object
                              to: string
                header:
                  user:
                    schema:
                      schemaAdded: true
                    content:
                      mediaTypeDeleted:
                        - application/json
                query:
                  filter:
                    content:
                      mediaTypeModified:
                        application/json:
                          schema:
                            required:
                              stringsdiff:
                                added:
                                  - type
                  image:
                    examples:
                      deleted:
                        - "0"
                  token:
                    schema:
                      maxLength:
                        from: 29
                        to: null
            responses:
              added:
                - default
              deleted:
                - "200"
              modified:
                "201":
                  content:
                    mediaTypeModified:
                      application/xml:
                        schema:
                          type:
                            from: string
                            to: object
      parameters:
        deleted:
          path:
            - domain
    /api/{domain}/{project}/install-command:
      operations:
        modified:
          GET:
            parameters:
              deleted:
                header:
                  - network-policies
            responses:
              modified:
                default:
                  description:
                    from: Tufin1
                    to: Tufin
                  headers:
                    deleted:
                      - X-RateLimit-Limit
            servers:
              added:
                - https://www.tufin.io/securecloud
endpoints:
  deleted:
    - method: POST
      path: /register
    - method: POST
      path: /subscribe
  modified:
    ? method: GET
      path: /api/{domain}/{project}/badges/security-score
    : tags:
        deleted:
          - security
      parameters:
        modified:
          cookie:
            test:
              content:
                mediaTypeModified:
                  application/json:
                    schema:
                      type:
                        from: object
                        to: string
          header:
            user:
              schema:
                schemaAdded: true
              content:
                mediaTypeDeleted:
                  - application/json
          query:
            filter:
              content:
                mediaTypeModified:
                  application/json:
                    schema:
                      required:
                        stringsdiff:
                          added:
                            - type
            image:
              examples:
                deleted:
                  - "0"
            token:
              schema:
                maxLength:
                  from: 29
                  to: null
      responses:
        added:
          - default
        deleted:
          - "200"
        modified:
          "201":
            content:
              mediaTypeModified:
                application/xml:
                  schema:
                    type:
                      from: string
                      to: object
    ? method: GET
      path: /api/{domain}/{project}/install-command
    : parameters:
        deleted:
          header:
            - network-policies
      responses:
        modified:
          default:
            description:
              from: Tufin1
              to: Tufin
            headers:
              deleted:
                - X-RateLimit-Limit
      servers:
        added:
          - https://www.tufin.io/securecloud
security:
  deleted:
    - bearerAuth
servers:
  deleted:
    - tufin.com
tags:
  deleted:
    - security
    - reuven
externalDocs:
  deleted: true
components:
  schemas:
    added:
      - requests
    modified:
      network-policies:
        additionalPropertiesAllowed:
          from: true
          to: false
      rules:
        additionalPropertiesAllowed:
          from: null
          to: false
  parameters:
    deleted:
      header:
        - network-policies
  headers:
    deleted:
      - new
    modified:
      test:
        schema:
          additionalPropertiesAllowed:
            from: true
            to: false
      testc:
        content:
          mediaTypeModified:
            application/json:
              schema:
                type:
                  from: object
                  to: string
  requestBodies:
    deleted:
      - reuven
  responses:
    added:
      - default
    deleted:
      - OK
  securitySchemes:
    deleted:
      - OAuth
    modified:
      AccessToken:
        type:
          from: http
          to: oauth2
        scheme:
          from: bearer
          to: ""
        OAuthFlows:
          added: true

Embedding into your Go program

diff.Get(&diff.Config{}, spec1, spec2)

See full example: main.go

Notes

  1. Output Formats

    • The default output format, YAML, provides a full view of all diff details.
      Note that no output in YAML format signifies that the diff is empty, or, in other words, there are no changes.
    • Other formats: text, markdown and HTML, are designed to be more user-friendly by providing only the most important parts of the diff, in a simplified format.
      If you wish to include additional details in non-YAML formats, please open an issue.
  2. Paths vs. Endpoints
    OpenAPI Specification has a hierarchial model of Paths and Operations (HTTP methods).
    oasdiff respects this heirarchy and displays a hierarchial diff with path changes: added, deleted and modified, and within the latter, "modified" section, another set of operation changes: added, deleted and modified. For example:

    paths:
        deleted:
            - /register
            - /subscribe
        modified:
            /api/{domain}/{project}/badges/security-score:
                operations:
                    modified:
                        GET:

    oasdiff also outputs an alternate simplified diff per "endpoint" which is a combination of Path + Operation, for example:

    endpoints:
        deleted:
            - method: POST
              path: /subscribe
            - method: POST
              path: /register
        modified:
            ?   method: GET
                path: /api/{domain}/{project}/badges/security-score
            :   tags:
                    deleted:
                        - security

Notes for Developers

  1. oasdiff expects OpenAPI References to be resolved.
    References are normally resolved automatically when you load the spec. In other cases you can resolve refs using Loader.ResolveRefsIn.

  2. Use configuration to exclude certain types of changes:

Work in progress

  1. Patch support: currently supports Descriptions and a few fields in Schema

Requests for enhancements

  1. OpenAPI 3.1 support: see Tufin#52

Credits

This project relies on the excellent implementation of OpenAPI 3.0 for Go: kin-openapi

About

A diff tool for OpenAPI Specification 3

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Go 99.8%
  • Dockerfile 0.2%