Skip to content

Commit b748aa3

Browse files
authored
Add SpotBugs with baseline and baseline generation (amazon-ion#471)
* Upgrade to Gradle 7.6 * Enable SpotBugs with baseline * Add SpotBugs baseline generation to build tasks * Print SpotBugs to console when in CI workflow
1 parent de540a2 commit b748aa3

7 files changed

Lines changed: 2979 additions & 17 deletions

File tree

build.gradle.kts

Lines changed: 63 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@ import java.net.URI
22
import java.time.Instant
33
import java.util.Properties
44

5+
56
plugins {
67
java
78
`maven-publish`
89
jacoco
910
signing
1011
id("org.cyclonedx.bom") version "1.7.2"
11-
// TODO: static analysis. E.g.:
12+
id("com.github.spotbugs") version "5.0.13"
13+
// TODO: more static analysis. E.g.:
1214
// id("com.diffplug.spotless") version "6.11.0"
13-
// id("com.github.spotbugs") version "4.8.0"
1415
}
1516

1617
repositories {
@@ -21,7 +22,6 @@ dependencies {
2122
testImplementation("junit:junit:4.13.1")
2223
testImplementation("org.hamcrest:hamcrest:2.2")
2324
testImplementation("pl.pragmatists:JUnitParams:1.1.1")
24-
// https://mvnrepository.com/artifact/com.google.code.tempus-fugit/tempus-fugit
2525
testImplementation("com.google.code.tempus-fugit:tempus-fugit:1.1")
2626
}
2727

@@ -54,19 +54,70 @@ tasks {
5454

5555
javadoc {
5656
// Suppressing Javadoc warnings is clunky, but there doesn't seem to be any nicer way to do it.
57-
// https://stackoverflow.com/questions/52205209/configure-gradle-build-to-suppress-javadoc-console-warnings
57+
// https://stackoverflow.com/questions/62894307/option-xdoclintnone-does-not-work-in-gradle-to-ignore-javadoc-warnings
5858
options {
59-
(this as CoreJavadocOptions).addStringOption("Xdoclint:none", "-quiet")
59+
this as StandardJavadocDocletOptions
60+
addBooleanOption("Xdoclint:none", true)
61+
addStringOption("Xmaxwarns", "1") // best we can do is limit warnings to 1
62+
}
63+
}
64+
65+
// spotbugs-gradle-plugin creates a :spotbugsTest task by default, but we don't want it
66+
// see: https://github.com/spotbugs/spotbugs-gradle-plugin/issues/391
67+
project.gradle.startParameter.excludedTaskNames.add(":spotbugsTest")
68+
69+
spotbugsMain {
70+
val spotbugsBaselineFile = "$rootDir/config/spotbugs/baseline.xml"
71+
72+
// CI=true means we're in a CI workflow
73+
// https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables
74+
val ciWorkflow = System.getenv()["CI"].toBoolean()
75+
val baselining = project.hasProperty("baseline") // e.g. `./gradlew :spotbugsMain -Pbaseline`
76+
77+
if (!baselining) {
78+
baselineFile.set(file(spotbugsBaselineFile))
79+
}
80+
81+
// The plugin only prints to console when no reports are configured
82+
// See: https://github.com/spotbugs/spotbugs-gradle-plugin/issues/172
83+
if (!ciWorkflow && !baselining) {
84+
reports.create("html").required.set(true)
85+
} else if (baselining) {
86+
// Note this path succeeds :spotbugsMain because *of course it does*
87+
ignoreFailures = true
88+
reports.create("xml") {
89+
// Why bother? Otherwise we have kilobytes of workspace-specific absolute paths, statistics, etc.
90+
// cluttering up the baseline XML and preserved in perpetuity. It would be far better if we could use
91+
// the SpotBugs relative path support, but the way SpotBugs reporters are presently architected they
92+
// drop the `destination` information long before Project.writeXML uses its presence/absence to
93+
// determine whether to generate relative instead of absolute paths. So, contribute patch to SpotBugs or
94+
// write own SpotBugs reporter in parallel or... do this.
95+
// Improvements are definitely possible, but left as an exercise to the reader.
96+
doLast {
97+
// It would be super neat if we had some way to handle this xml processing directly inline, without
98+
// generating a temp file or at least without shelling out.
99+
// Use ant's xslt capabilities? Xalan? Saxon gradle plugin (eerohele)? javax.xml.transform?
100+
// In the mean time... xsltproc!
101+
exec {
102+
commandLine(
103+
"xsltproc",
104+
"--output", spotbugsBaselineFile,
105+
"$rootDir/config/spotbugs/baseline.xslt",
106+
outputLocation.get().toString()
107+
)
108+
}
109+
}
110+
}
60111
}
61112
}
62113

63-
create<Jar>("sourcesJar") sourcesJar@ {
114+
create<Jar>("sourcesJar") sourcesJar@{
64115
archiveClassifier.set("sources")
65116
from(sourceSets["main"].java.srcDirs)
66117
artifacts { sourcesArtifact = archives(this@sourcesJar) }
67118
}
68119

69-
create<Jar>("javadocJar") javadocJar@ {
120+
create<Jar>("javadocJar") javadocJar@{
70121
archiveClassifier.set("javadoc")
71122
from(javadoc)
72123
artifacts { javadocArtifact = archives(this@javadocJar) }
@@ -79,7 +130,7 @@ tasks {
79130
*/
80131
val generateJarInfo by creating<Task> {
81132
doLast {
82-
val propertiesFile = File("$generatedJarInfoDir/${project.name}.properties")
133+
val propertiesFile = File("$generatedJarInfoDir/${project.name}.properties")
83134
propertiesFile.parentFile.mkdirs()
84135
val properties = Properties()
85136
properties.setProperty("build.version", version.toString())
@@ -94,11 +145,11 @@ tasks {
94145
jacocoTestReport {
95146
dependsOn(test)
96147
reports {
97-
xml.isEnabled = true
98-
html.isEnabled = true
148+
xml.required.set(true)
149+
html.required.set(true)
99150
}
100151
doLast {
101-
logger.quiet("Coverage report written to file://${reports.html.destination}/index.html")
152+
logger.quiet("Coverage report written to file://${reports.html.outputLocation.get().toString()}/index.html")
102153
}
103154
}
104155

@@ -131,7 +182,7 @@ publishing {
131182
licenses {
132183
license {
133184
name.set("The Apache License, Version 2.0")
134-
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
185+
url.set("https://www.apache.org/licenses/LICENSE-2.0.txt")
135186
}
136187
}
137188
developers {

0 commit comments

Comments
 (0)