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

Reply via email to