- Introducing Swagger Brake
- Integrating Swagger Brake into Maven/Gradle projects
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
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
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
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
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" } ] }
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):
$ 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
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.
How does it handle authentication?
or would you have to use some curl mechanism to grab the son file?
Very good point. Not yet implemented but it’s on the plate, just didn’t have time to finish it. đŸ™‚
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
It does recognize such breaking changes, yes. It can even recognize nested object changes as well.
Interesting tool!
I am having problems resolving dependency from artifactory, mainly since our repo does not contain metadata information per version… is there a way around this?
eg, getting this error:
16:48:59.034 [main] DEBUG i.r.s.b.m.m.MavenMetadataDownloader – Downloading maven metadata from https://our-repo/artifactory/libs-release-local/com/company/artifact/2.0.83/maven-metadata.xml
16:48:59.120 [main] DEBUG io.redskap.swagger.brake.cli.Cli – Exception occured
io.redskap.swagger.brake.runner.exception.LatestArtifactDownloadException: Error while downloading the latest version of the artifact
Also, is there a way to make it more lenient on removed request/response fields that are optional etc?
Hi Kent. As of today, for having an automatic comparison, the metadata file is required. However, if your current system doesn’t generate the metadata files, you can always fall back to the CLI tool that you can use to write your custom logic of retrieving the “latest” version of your API.