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 .

$ java -jar swagger-brake.jar \ --old-api=/c/work/swagger-brake/petstore.json \ --new-api=/c/work/swagger-brake/petstore_v2.json 1 2 3 $ java - jar swagger - brake .jar \ -- old - api = / c / work / swagger - brake / petstore .json \ -- new - api = / c / work / swagger - brake / petstore_v2 .json

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.

Loading old API from C:/work/swagger-brake/petstore.json Loading new API from C:/work/swagger-brake/petstore_v2.json Successfully loaded APIs Starting the check for breaking API changes Check is finished No breaking API changes detected 1 2 3 4 5 6 Loading old API from C : / work / swagger - brake / petstore . json Loading new API from C : / work / swagger - brake / petstore_v2 . json Successfully loaded APIs Starting the check for breaking API changes Check is finished No breaking API changes detected

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 .

Loading old API from C:/work/swagger-brake/petstore.json Loading new API from C:/work/swagger-brake/petstore_v2.json Successfully loaded APIs Starting the check for breaking API changes Check is finished There were breaking API changes Path /pets POST has been deleted 1 2 3 4 5 6 7 Loading old API from C : / work / swagger - brake / petstore . json Loading new API from C : / work / swagger - brake / petstore_v2 . json Successfully loaded APIs Starting the check for breaking API changes Check is finished There were breaking API changes Path / pets POST has been deleted

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 .

$ java -jar swagger-brake.jar \ --old-api=/c/work/swagger-brake/petstore.json \ --new-api=/c/work/swagger-brake/petstore_v2.json \ --output-format=JSON \ --output-path=/c/work/swagger/brake 1 2 3 4 5 $ java - jar swagger - brake . jar \ -- old - api = / c / work / swagger - brake / petstore . json \ -- new - api = / c / work / swagger - brake / petstore_v2 . json \ -- output - format = JSON \ -- output - path = / c / work / swagger / brake

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

{ "pathDeletedBreakingChange" : [ { "path" : "/pets", "method" : "POST", "message" : "Path /pets POST has been deleted" } ] } 1 2 3 4 5 6 7 { "pathDeletedBreakingChange" : [ { "path" : "/pets" , "method" : "POST" , "message" : "Path /pets POST has been deleted" } ] }

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

the repository URL where the “ ” artifact can be found -- groupId the groupId of the “ latest ” artifact

the groupId of the “ ” 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):

$ java -jar swagger-brake.jar \ --new-api=/c/work/swagger-brake/petstore_v2.json \ --maven-repo-url=http://localhost:8081/artifactory/libs-snapshot-local/ \ --groupId=com.arnoldgalovics.blog \ --artifactId=user-service-api 1 2 3 4 5 $ java - jar swagger - brake . jar \ -- new - api = / c / work / swagger - brake / petstore_v2 . json \ -- maven - repo - url = http : //localhost:8081/artifactory/libs-snapshot-local/ \ -- groupId = com . arnoldgalovics . blog \ -- artifactId = user - service - api

The expected output is:

Downloading latest artifact from repository 'http://localhost:8081/artifactory/libs-snapshot-local/' with groupId 'com.arnoldgalovics.blog' artifactId 'user-service-api' Loading old API from C:\Users\[username]\AppData\Local\Temp\swagger-brake7199436794942269700swagger.json Loading new API from C:/work/swagger-brake/petstore_v2.json Successfully loaded APIs Starting the check for breaking API changes Check is finished There were breaking API changes Path /pets POST has been deleted 1 2 3 4 5 6 7 8 Downloading latest artifact from repository 'http://localhost:8081/artifactory/libs-snapshot-local/' with groupId 'com.arnoldgalovics.blog' artifactId 'user-service-api' Loading old API from C : \ Users \ [ username ] \ AppData \ Local \ Temp \ swagger - brake7199436794942269700swagger . json Loading new API from C : / work / swagger - brake / petstore_v2 . json Successfully loaded APIs Starting the check for breaking API changes Check is finished There were breaking API changes Path / pets POST has been deleted

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.