Taking out Netflix’s gradle-lint-plugin for a spin

Dependency management is a complex thing. A typical gradle project has several dependencies, each of which in turn has multiple other dependencies and so on. This continues and what forms as a result is called a dependency graph. While this is great, unused dependencies is a big problem. For instance, say your project depends on dependency A which then depends on B, C and D. Your project also depends directly with another dependency E which in turn depends on F and G. The dependency graph would look something like this:

Your Project -> A -> (B, C, D)
Your Project -> E -> (F, G)

Now, your project probably only uses code in A which only then directly depends on some code in B. Also, maybe you also have some code that depends on E but that code in E doesn’t depend directly on neither F, nor G. This means that C, D, F and G are your unused dependencies.

If you knew this from the start, you could just exclude those libraries. However, tracking this manually is incredibly difficult as the more complex the libraries are, the more complex the web of inter-dependencies becomes. I’ve been looking for an automated solution to this for a while and recently, I found that Netflix has a plugin that could help. This is called the gradle-lint-plugin.

Its part of Netflix’s OSS and is available on github to download. Its artifacts are available in JCenter maven repository.

To test it out, I quickly got a gradle project up and running by following the spring boot tutorial. To make things a slightly more interesting, I added the
org.apache:httpcomponents:httpclient library as a dependency in my
build.gradle file:

I ran the gradle clean build command to assess the initial size of the build. As expected, the war file was massive at 14.3 megabytes. For a small project that has a simple healthcheck endpoint, this is huge. So, to streamline this, I followed the gradle-lint-plugin guide to use and apply the plugin. I added some rules of my own too. Here’s what my
build.gradle file looks like:

Excellent! It found the unused dependencies. I was quite pleased with this result so I ran
gradle fixGradleLint command. According to the wiki, this command should fix the issues that it found by making changes to the
build.gradle file. Unfortunately, this didn’t work as it resulted in an error.

I’ve already raised a github issue to draw their attention to this problem. For information on progress, feel free to watch or add to the issue.

So, even if the automated fix didn’t work, I wasn’t done yet. I looked around in the
build directory looking for something that I can use to apply for the fix myself. After all, since
gradle lintGradle and
gradle fixGradleLint are two separate commands, independent of each other, it must store some form of state somewhere. Fortunately I found it. It stores its state in a file called
lint.patch directly under the
build directory at the root of your project.

Hurrah! I quickly opened it. It was a normal git patch file. While looking at it, I was slightly confused with the additions that it was making. Here’s what mine looked like:

Looking at that file, I could immediately tell that it was adding some compile time dependencies and was removing one httpcomponents dependency. While I agree with the removal of the httpcomponents dependency, I was slightly confused why it wasn’t replacing the existing spring-boot dependencies with the ones it was adding. It should’ve replaced them because having both provides no benefit. What its trying to add is more specific than the dependencies that are already there! To prove myself right, I removed all the existing
compile dependencies (expect
testCompile ones) and added the ones that it was going to add from the patch file. Here’s what the dependency section of my
build.gradle looked like:

I quickly ran
gradle clean build and sure enough, this time the build size had shrunk to almost a third of its original size – 5.5 megabytes! Also, the
lintGradle task at the end of the build didn’t report any errors.

I can certainly see the value of this plugin in a continuous integration system as unused libraries cause host of memory related issues like lack of permgen space in java web containers. Also, its better to let developers focus on core development and let the periphery issues such as these be handled by an automated plugin like this one.

I hope the developers on the github project fix the issues related to the
fixGradleLint task soon.