Introducing Swagger Brake

A couple of weeks ago, I could’ve really used just a standalone application to continuously check whether my API is getting broken. Imagine the situation that there are multiple consumers of your REST API and the API is quite big (the Swagger file is 1000 lines long at least), it’s just really hard to track if something is going to break the API or not.

I’ve found one promising tool to check for breaking API changes called swagger-diff. Although it is a usable tool it has a few downsides:

  • It’s not made for extension (and if it is, I don’t know how to do it because it is written in Ruby which I apparently don’t speak)
  • It’s not easy to integrate into the build pipeline
  • It’s only a CLI tool
  • Reporting is not that shiny – a simple JSON output

After not finding any tool which I could use, I decided to tackle the problem by creating one. The tool is called Swagger Brake.

Swagger Brake

The main focus for creating it was to be able to integrate easily to Java based projects, have proper reporting capabilities meaning HTML, JSON, etc. and have extension capabilities for customizing it to everyone’s need.

The core concept of Swagger Brake is to identify any breaking API changes between two Swagger files. The following changes are considered as backward incompatible:

  • If any path is removed or the HTTP verb is changed
  • If any request parameter is removed
  • If any new request parameter is required or an existing one set as required
  • If any request attribute is removed
  • If any response attribute is removed
  • If any enum value is removed

If any of these changes happen, Swagger Brake will report that using the new contract might break existing clients.

There are 3 ways how Swagger Brake can be used (at the moment):

  • Through a command line interface
  • As a Maven plugin
  • As a Gradle plugin

In this article, I’ll cover CLI only and there will be an upcoming article on how to integrate it into a Maven/Gradle build.

Command Line Interface usage

The CLI interface is just a simple JAR file which can be downloaded from the releases page on GitHub under the name swagger-brake-0.1.0-cli.jar. For demonstration purposes, we’ll use an existing definition which is the petstore contract. Let’s download both of them. From the petstore definition, make a copy for further usage and name it petstore_v2.json.

Assuming you now have three files:

  • swagger-brake-0.1.0-cli.jar
  • petstore.json
  • petstore_v2.json

Bring up your favorite terminal (I’m using cmder here) as a preparation. In the context of Swagger Brake, we can talk about old and new APIs. In our case the old API will be petstore.json and the new one will be petstore_v2.json

For the CLI, there are two mandatory parameters which you can guess, the old and new APIs. The old one can be provided with the --old-api=/path/to/api  and the new one can be provided with the --new-api=/path/to/new/api parameters .

When you execute this command, Swagger Brake by default will report to the standard output whether the new API is backward compatible with the new one.

Now let’s spice it up a bit and break our new API. Open up your text editor and completely remove one path from the API. I’m removing POST /pets .

As you can see the last line of the output is that /pets POST has been removed from the contract which in fact is a breaking API change.

Reporting

The reporting can also be customized. There are 3 types of reporting available at the time of writing the article: STDOUT, JSON, HTML. We’ve already seen the standard output reporting, now take a look at the others. The only change needed is to pass two new parameters to the CLI called --output-format=[type]  and --output-path=/path/to/save/report .

A JSON file will appear in the selected folder called swagger-brake.json  and the content is the following:

Now check out how the HTML report looks like:

Latest artifact resolution mechanism

Imagine integrating Swagger Brake into a build pipeline to get a feedback whether the upcoming changes are breaking the existing API. As already mentioned, there are 2 definitions needed to do the check, the old one and the new one. In a pipeline it’s not that easy to get the old API definition (if you can, then use that).

For this reason, it’s a good idea to create artifacts from your Swagger contracts and put it into Nexus/Artifactory. In that case, Swagger Brake can resolve the so called “latest” artifact available in the repository. The latest artifact retrieval is done by analyzing the maven-metadata.xml  files present in the Maven repository.

After the artifact is found, it will be downloaded to the system’s temp directory and it will be scanned through for one of the following files:

  • swagger.json
  • swagger.yaml
  • swagger.yml

If any Swagger definition file can be found, it will be used as the old API.

Using this functionality requires 3 parameters to be provided:

  • --maven-repo-url the repository URL where the “latest” artifact can be found
  • --groupId the groupId of the “latest” artifact
  • --artifactId the artifactId of the “latest” artifact

Example command which is using an Artifactory server on localhost (I’ve used Docker here and an example project):

The expected output is:

Final words

I’ve showed how Swagger Brake CLI can be used to check for breaking API changes. There is a Gradle and Maven plugin available as well which will be covered in an upcoming article. There are tons of ideas how to improve the tool and integrate into other tools (for example Sonar). If you have any ideas what could be useful, just open a GitHub issue and we can discuss it for sure.

In case you have questions/feedback, comment, reach out on Twitter. The source of Swagger Brake can be found on GitHub.

4 Replies to “Introducing Swagger Brake”

  1. nice implementation!
    does it recognize breaking changes in request/reponse objects as well?
    for example renames of attributes in request/response objects or any plans on integrating such checks?

    thanks!
    Stefan

Leave a Reply

Your email address will not be published. Required fields are marked *