This is a fork of the well-known gradle-revapi
plugin from https://github.com/palantir/gradle-revapi and has been moved under the revapi
umbrella.
For additional details please refer to revapi/revapi#296.
A gradle plugin which runs Revapi to warn you when there are breaks to your Java library's public API or ABI.
Using the plugin should be as simple as:
-
Adding the plugin to your buildscript:
buildscript { // ... dependencies { classpath 'org.revapi:gradle-revapi:<latest-version>' } }
-
And then apply the plugin to all the projects you want to ensure API compatibility:
// In my Java project's build.gradle that publishes a jar +apply plugin: 'org.revapi.revapi-gradle-plugin'
-
Revapi will be run as part of
./gradlew check
. Alternatively, you can call./gradlew revapi
directly.
Accidentally releasing API or ABI breaks in java libraries has bad consequences for library consumers. In the case of API breaks, consumers have to perform some kind of manual action to upgrade to newer library versions, which may be difficult.
With ABI breaks, the situation can be even worse, as uses of the library compile but uses in jars of the old API fail at
runtime. An example from Tritium is where a
method was changed from a Map
to a SortedMap
.
This compiles against direct dependencies but transitive dependencies using the older API
would produce a NoSuchMethodError
at runtime, which has caused a number of problems in production code. Similarly,
there was a covariant return type change to docker-compose-rule
(ImmutableDockerComposeRule
-> DockerComposeRule
)
which caused ABI breaks in docker-proxy-rule
,
among projects.
gradle-revapi
should work out of the box for most uses cases once applied. By default it compares against the previous
version of the jar from the project it is applied in by finding the last tag using git describe
. However, if you need
to need to override the artifact to compare against, you can do so:
revapi {
oldGroup = '<artifact-group>'
oldNamed = '<artifact-name>'
oldVersion = '<artifact-version>'
}
Sometimes you may wish to break your API, or feel that the particular API break identified by revapi is acceptable to
release. In these cases, there is an escape hatch you can use which should be automatically recommended to you in the
error message gradle-revapi
produces.
-
To accept a single break, run:
./gradlew revapiAcceptBreak --justification "{why this is ok}" \ --code "{revapi check code}" \ --old "{optional revapi description of old element}" \ --new "{optional revapi description of new element}"
-
To accept all the breaks in a gradle project run:
./gradlew :project:revapiAcceptAllBreaks
-
To accept all the breaks in all gradle projects run:
./gradlew revapiAcceptAllBreaks
Running any of these tasks will add the breaks to the .palantir/revapi.yml
file in the format"
acceptedBreaks:
version:
group:name:
- code: "class"
old: "class OldClass"
new: null
justification: "No one was using this"
Sometimes the previous release will have a successfully applied a git tag but a failed publish build. In this
case gradle-revapi
will fail as it cannot resolve the previous API to compare against. To resolve this, you can
possible to set a version override that will use a different version instead of the last git tag. To do so,
use the
./gradle revapiVersionOverride --replacement-version <last-published-version>
task to use correctly published version instead. This will creare an entry in .palantir/revapi.yml
of the following
format:
versionOverrides:
group:name:version: versionOverride
A new version of the plugin can be released by manually triggering the Release new plugin version
GH action.
If necessary, a new version can also be manually released via ./gradlew publishPlugins
while locally exporting the env variables RELEASE_VERSION
, GRADLE_KEY
, GRADLE_SECRET
.