OpenAPI-diff

repository·master·Indexed 22 days ago

https://github.com/openapitools/openapi-diff

A tool to compare two OpenAPI (Swagger) specifications to identify new, deleted, deprecated, or modified endpoints and determine if changes break backward compatibility. It provides a CLI, a Maven plugin, and a Java API (via the OpenApiCompare class), with output formats including JSON, Markdown, HTML, Asciidoc, and plain text.

Tokens
4.7K
Snippets
12
Records
14
Agent score
73%

What's inside openapi-diff

  1. Understand OpenAPI-diff output formats

    master

    OpenAPI-diff provides change analysis in three primary formats depending on your integration needs:

    1. CLI Output: A human-readable text summary displayed in the terminal, categorized by 'What's New', 'What's Deleted', 'What's Deprecated', 'What's Changed', and a final 'Result' indicating if backward compatibility was broken.
    2. Markdown: A structured document suitable for inclusion in pull request comments or documentation, using Markdown syntax to list changes to endpoints, parameters, and return types.
    3. JSON: A machine-readable schema designed for programmatic consumption. It provides detailed objects for newEndpoints, changedOperations, and boolean flags like compatible, incompatible, and different to allow automated CI/CD gating.

    Use the JSON output if you need to build custom tooling or automated breaking-change detectors.

  2. Extend OpenAPI-diff via SPI

    master

    The project uses the Java Service Provider Interface (SPI) to allow for custom extensions. To implement a custom ExtensionDiff:

    1. Create a class that implements org.openapitools.openapidiff.core.compare.ExtensionDiff.
    2. Register your implementation by creating a file named src/main/resources/META-INF/services/org.openapitools.openapidiff.core.compare.ExtensionDiff containing the full qualified class name of your implementation.

    When your library is included with the openapi-diff module, the extension will be triggered automatically during the comparison process.

  3. Install OpenAPI-diff via Maven

    master

    To use OpenAPI-diff as a dependency in your Java project, add the openapi-diff-core artifact to your pom.xml. Ensure you replace ${openapi-diff-version} with the desired version.

    <dependency>
      <groupId>org.openapitools.openapidiff</groupId>
      <artifactId>openapi-diff-core</artifactId>
      <version>${openapi-diff-version}</version>
    </dependency>
  4. Run OpenAPI-diff using Docker

    master

    You can run OpenAPI-diff using the official Docker image openapitools/openapi-diff.

    To run an instance with local files, mount your local directory containing the specifications to the /specs directory in the container using a volume. In the example below, the local directory is mounted as read-only (ro).

    docker run --rm -t \
      -v $(pwd)/core/src/test/resources:/specs:ro \
      openapitools/openapi-diff:latest /specs/path_1.yaml /specs/path_2.yaml
  5. Configure the OpenAPI-diff Maven Plugin

    master

    Use the openapi-diff-maven plugin to integrate API compatibility checks into your Maven build lifecycle. You can configure it to fail the build if backward compatibility is broken or if any changes are detected.

    <plugin>
      <groupId>org.openapitools.openapidiff</groupId>
      <artifactId>openapi-diff-maven</artifactId>
      <version>${openapi-diff-version}</version>
      <executions>
        <execution>
          <goals>
            <goal>diff</goal>
          </goals>
          <configuration>
            <!-- Reference specification (perhaps your prod schema) -->
            <oldSpec>https://petstore3.swagger.io/api/v3/openapi.json</oldSpec>
            <!-- Specification generated by your project in the compile phase -->
            <newSpec>${project.basedir}/target/openapi.yaml</newSpec>
            <!-- Fail only if API changes broke backward compatibility (default: false) -->
            <failOnIncompatible>true</failOnIncompatible>
            <!-- Fail if API changed (default: false) -->
            <failOnChanged>true</failOnChanged>
            <!-- Supply file path for console output to file if desired. -->
            <consoleOutputFileName>${project.basedir}/../maven/target/diff.txt</consoleOutputFileName>
            <!-- Supply json output to file if desired. -->
            <jsonOutputFileName>${project.basedir}/../maven/target/diff.json</jsonOutputFileName>
            <!-- Supply markdown output to file if desired. -->
            <markdownOutputFileName>${project.basedir}/../maven/target/diff.md</markdownOutputFileName>
            <!-- Supply config file(s), e.g. to disable incompatibility checks. Later files override earlier files -->
            <configFiles>
              <configFile>my/config-file.yaml</configFile>
            </configFiles>
            <!-- Supply config properties, e.g. to disable incompatibility checks. Overrides configFiles. -->
            <configProps>
              <incompatible.response.enum.increased>false</incompatible.response.enum.increased>
            </configProps>
          </configuration>
        </execution>
      </executions>
    </plugin>
  6. Use the openapi-diff CLI to compare OpenAPI specifications

    master

    The openapi-diff command-line tool compares two OpenAPI specifications (the old and the new versions) and identifies changes, including backward compatibility breaks.

    Basic Usage:

    openapi-diff <old_spec_path> <new_spec_path>

    Arguments:

    • <old>: Path or URL to the original OpenAPI specification.
    • <new>: Path or URL to the updated OpenAPI specification.

    Exit Codes:

    • 0: Success (no incompatible changes if --fail-on-incompatible is used, or if the spec is unchanged if --fail-on-changed is used).
    • 1: Failure (incompatible changes detected when using --fail-on-incompatible, or changes detected when using --fail-on-changed).
    • 2: Error (parsing failure or unexpected exception).
    # Example: Compare two local files and output a JSON diff
    openapi-diff old_spec.yaml new_spec.yaml --json diff_output.json
    
    # Example: Compare and fail if backward compatibility is broken
    openapi-diff old_spec.yaml new_spec.yaml --fail-on-incompatible
    
    # Example: Only output the diff state (no_changes, incompatible, compatible)
    openapi-diff old_spec.yaml new_spec.yaml --state
  7. Render OpenAPI diffs to different formats in Java

    master

    Once you have a ChangedOpenApi object, you can render the differences into various formats using specific Render classes.

    // HTML
    HtmlRender htmlRender = new HtmlRender("Changelog", "http://deepoove.com/swagger-diff/stylesheets/demo.css");
    FileOutputStream outputStream = new FileOutputStream("testDiff.html");
    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
    htmlRender.render(diff, outputStreamWriter);
    
    // Markdown
    MarkdownRender markdownRender = new MarkdownRender();
    markdownRender.render(diff, outputStreamWriter);
    
    // Asciidoc
    AsciidocRender asciidocRender = new AsciidocRender();
    
    // JSON
    JsonRender jsonRender = new JsonRender();
    jsonRender.render(diff, outputStreamWriter);
  8. Compare OpenAPI specs via Java API

    master

    You can use the OpenApiCompare class to perform comparisons programmatically.

    Basic Comparison:

    ChangedOpenApi diff = OpenApiCompare.fromLocations(oldSpecPath, newSpecPath);

    Custom Path Matching: By default, the DefaultPathMatcher obfuscates path parameter names (e.g., /users/{id} matches /users/{userId}). To use a custom matching strategy, implement the PathMatcher interface and provide it via OpenApiDiffOptions:

    OpenApiDiffOptions options = OpenApiDiffOptions
        .builder()
        .pathMatcher(new MyCustomPathMatcher())
        .build();
    
    ChangedOpenApi diff = OpenApiCompare.fromLocations(oldSpec, newSpec, null, options);
    public class Main {
        public static final String OPENAPI_DOC1 = "petstore_v3_1.json";
        public static final String OPENAPI_DOC2 = "petstore_v2_2.yaml";
            
        public static void main(String[] args) {
            ChangedOpenApi diff = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
        }
    }
  9. Reference the OpenAPI-diff JSON output schema

    master

    When consuming the JSON output programmatically, the following top-level keys are available to assess the differences between two OpenAPI specifications:

    • compatible: Boolean indicating if the changes are backward compatible.
    • incompatible: Boolean indicating if breaking changes were detected.
    • different: Boolean indicating if any differences exist.
    • newEndpoints: An array of objects representing newly added endpoints (includes method, pathUrl, summary, and the full operation object).
    • missingEndpoints: An array of endpoints present in the old spec but missing in the new one.
    • changedOperations: An array of operations that have undergone modifications.
    • deprecatedEndpoints: An array of endpoints that have been marked as deprecated.
    • changedElements: Details on specific element changes.
    • oldSpecOpenApi: The original OpenAPI specification object.
    • newSpecOpenApi: The updated OpenAPI specification object.
    {
        "changedElements": [...],
        "changedExtensions": null,
        "changedOperations": [...],
        "compatible": false,
        "deprecatedEndpoints": [...],
        "different": true,
        "incompatible": true,
        "missingEndpoints": [...],
        "newEndpoints": [
            {
                "method": "GET",
                "operation": {
                    "operationId": "getPetById",
                    "summary": "Find pet by ID",
                    "pathUrl": "/pet/{petId}",
                    "parameters": [...]
                }
            }
        ],
        "newSpecOpenApi": {...},
        "oldSpecOpenApi": {...},
        "unchanged": false
    }
  10. Use the OpenAPI-diff CLI

    master

    The CLI tool compares two OpenAPI 3.x specifications (provided as file paths or HTTP URLs) and outputs the differences.

    Basic Syntax: openapi-diff <old> <new> [options]

    Key Options:

    • --html <file>: Export diff as HTML to the specified file.
    • --json <file>: Export diff as JSON to the specified file.
    • --markdown <file>: Export diff as Markdown to the specified file.
    • --asciidoc <file>: Export diff as Asciidoc to the specified file.
    • --text <file>: Export diff as plain text to the specified file.
    • --fail-on-incompatible: Fail if API changes broke backward compatibility.
    • --fail-on-changed: Fail if API changed but remains backward compatible.
    • --state <state>: Only output diff state: no_changes, incompatible, or compatible.
    • --config-file <file>: Use a .yaml config file to override default behavior.
    • --config-prop <key:value>: Override a specific configuration property (e.g., my.prop:true).
    $ openapi-diff --help