Using Spotless to auto-format Gradle Verification Metadata
I've previously written about Spotless being great.
I've recently started working with some codebases that use Gradle Dependency Verification which produces an XML file used for ensuring that the files downloaded by each user of the project are the same, to i.e. reduce risk of malicious artifacts being added to the build.
The gradle/verification-metadata.xml
is meant to be generated by Gradle itself, but sometimes you need to manually edit things i.e. to add artifacts that have a checksum for an architecture you're not currently on.
One problem with this is that inevitably there could be differences in editor, formatting options and whitespace usage that leads to inconsistently formatted XML files.
Therefore, I moved us over to using Spotless to manage this, using:
plugins {
id("com.diffplug.spotless") version $spotlessVersion
}
spotless {
format("xml") {
target("gradle/verification-metadata.xml")
eclipseWtp(com.diffplug.spotless.extra.wtp.EclipseWtpFormatterStep.XML)
endWithNewline()
trimTrailingWhitespace()
}
}
However, by working with this config, we found that the format of the resulting XML was wildly different to Gradle's, which ended up meaning that any edits - manual, or produced by Gradle - would need to have Spotless run on top of it.
That's a sub-par experience, so we wanted to improve it by seeing if we could get Spotless to create the same format that Gradle would.
Having fought this today, I definitely wanted to write it as a form of blogumentation, so future me (and maybe others) can avoid the pain.
This was a particularly painful issue as we're using Spotless' XML formatter via the Eclipse Web Tools Platform, in which Spotless delegates the hard job of formatting XML to Eclipse's tooling, and any style overrides would be defined in an Eclipse-specific configuration file.
However, because the Eclipse Web Tools Platform formatting is generally built for humans to interact with it as an IDE, this means that the settings are mostly meant to be driven through a UI, not to be well-documented for users. And without an Eclipse editor to play around with these settings and then export the configuration metadata, I was without a straightforward way to work this out.
(Towards the end I started downloading Eclipse, as I was finding it particularly awkward, until I found the source code)
To find out how this worked, I was able to piece together a couple of results on GitHub, then hit the search engines for some very specific searches, which then landed me on the source code for the XML formatter options, which ended up giving me the names of the various configuration items that the Eclipse tooling could use to tune the output.
This led to the following gradle/spotless-gradle-verification-metadata-xml.prefs
:
# Tested with Gradle 7.6.x
indentationChar=space
# for some reason, Gradle produces a 3-spaced XML file
indentationSize=3
# make sure that long lines aren't split
lineWidth=2048
# make sure that XML attrs are always on the same line
splitMultiAttrs=false
# Gradle likes to end lines like ` origin="Generated by Gradle"/>`
spaceBeforeEmptyCloseTag=false
And this required being wired in like so:
plugins {
id("com.diffplug.spotless") version $spotlessVersion
}
spotless {
format("xml") {
target("gradle/verification-metadata.xml")
- eclipseWtp(com.diffplug.spotless.extra.wtp.EclipseWtpFormatterStep.XML)
+ eclipseWtp(com.diffplug.spotless.extra.wtp.EclipseWtpFormatterStep.XML).configFile("gradle/spotless-gradle-verification-metadata-xml.prefs")
endWithNewline()
trimTrailingWhitespace()
}
}
This now means Spotless will perform the same resulting output as running ./gradlew --write-verification-metadata sha256 help
, regardless of whether a human's mangled the XML or not.