Hi all,
After the successful packaging of Gradle 4.5 with the help of Claude
Opus, I set it to work on improvements I had in mind for
gradle-debian-helper. Gradle-based packages require maintaining a number
of patches to disable plugins (and the tasks or configuration blocks
associated with them) and subprojects. Ideally, we'd like to disable
them using a declarative syntax to avoid patching the build files.
Claude's understanding of Gradle's internals helped me deliver exactly that.
Before uploading gradle-debian-helper 3.0, I'd like to present the idea
and get your feedback, since it'll shape the way we package Gradle-based
packages from now on.
gradle-debian-helper 3.0 supports a new debian/gradle.ignoreRules file
with two columns. It looks like this:
# plugins and extensions
com.gradle.build-scan buildScan
com.diffplug.gradle.spotless spotless
org.shipkit.java bintrayUpload,publishing
com.github.spotbugs spotbugs,com.github.spotbugs.SpotBugsTask
# script plugins
gradle/errorprone.gradle
# subproject
:osgi-test
# standalone block
- jmh
The first column specifies either:
* a plugin identifier, whichever way the script declares it:
apply plugin: 'jacoco'
plugins { id "com.gradle.build-scan" version "2.2.1" }
* the fully qualified name of a plugin class, when the plugin
is declared with a class name:
apply plugin: com.example.gradle.SomePlugin
* the path of a script plugin:
apply from: 'gradle/license.gradle'
* a project of the build (as listed with an include directive
in the settings.gradle file) prefixed with a colon.
* a dash, to declare standalone blocks to ignore
The second column is a comma-separated list of tasks or extensions
related to the plugin that are also ignored:
jmh {
fork = 1
}
tasks.withType(com.github.spotbugs.SpotBugsTask) {
reports { xml.enabled = false }
}
Under the hood, Gradle has been patched to intercept plugin and project
declarations, similarly to the way dependency declarations are already
intercepted. Neat trick for the plugins registered by class name, the
missing class is dynamically generated and implements an empty plugin.
To disable the extension blocks, the Debian plugin registers stub
extensions that simply do nothing when called. This works for Groovy
files only; for Kotlin files, gradle-kotlin-dsl has been patched to
ignore the blocks when the file is parsed.
In practice, this new tool dramatically reduces the number of patches
for some packages. For example, with the mockito package, all 7 patches
of the build files are now replaced by this single gradle.ignoreRules file:
# Ignored plugins
com.gradle.build-scan buildScan
com.diffplug.gradle.spotless spotless
org.shipkit.java bintrayUpload,publishing
gradle/root/coverage.gradle
gradle/license.gradle
gradle/errorprone.gradle
# Ignored projects
:deprecatedPluginsTest
:extTest
:kotlinTest
:kotlinReleaseCoroutinesTest
:android
:junitJupiterExtensionTest
:module-test
:memory-test
:errorprone
:junitJupiterParallelTest
:osgi-test
There are some limitations though: even if blocks are ignored or
silenced, some statements may still try to interact with them and will
fail. For example, a value read back out of an ignored block:
jmh {
resultFormat = 'CSV'
}
task report {
doLast { println jmh.resultFormat }
}
Let me know how it looks to you and if you have further improvement ideas.
Emmanuel Bourg