Skip to content

Overhaul script plugins as convention plugins #12258

Description

@bric3

Convention Plugins Migration Strategy

Tracking issue: #12258

Updated: 2026-10-02. The instrumentation extraction described below is staged
locally and has not been committed or published as a PR.

Replace Groovy script plugins and parent-driven module configuration with Kotlin
convention plugins. Keep module entry points stable while moving one cohesive
responsibility at a time, preserving artifacts, task behavior, and incremental
builds.

Current state

  • Module entry points already exist under dd-trace-java.module.* in buildSrc.
    The namespace is singular: module, not the earlier proposal's modules.

  • dd-trace-java.conventions.java composes dependency locking and the remaining
    gradle/java_deps.gradle and gradle/java_no_deps.gradle scripts.
    PR #12331 migrated the
    remaining direct consumers, and PR #12333
    moved composition into the convention and deleted gradle/java.gradle.

  • build-logic/conventions already contains the Kotlin, Scala, and SLF4J-simple
    testing conventions, plus dd-trace-java.mass.

  • build-logic also contains the smoke-test application and Testcontainers plugins.
    These are separate from the dd-trace-java.module.smoke-test module convention.

  • Fifteen Groovy scripts remain directly under gradle/:

    codenarc.gradle       ddprof-override.gradle  dependencies.gradle
    forbiddenapis.gradle jacoco.gradle           java_deps.gradle
    java_no_deps.gradle   maven-pom.gradle        publish.gradle
    repositories.gradle  spotless.gradle         spotbugs.gradle
    test-suites.gradle   tries.gradle            util.gradle
    

Instrumentation configuration: staged extraction

dd-trace-java.module.instrumentation now owns the module defaults previously
configured by the subprojects {} block in
dd-java-agent/instrumentation/build.gradle:

  • Apply dd-trace-java.build-time-instrumentation and dd-trace-java.muzzle.
  • Register the advice-scanning, newTaskFor, and request-context rewrite plugins,
    with agent-tooling's buildTimeInstrumentationToolingPlugins artifact on
    buildTimeInstrumentationPlugin.
  • Exclude the vendored SnakeYAML engine from muzzleBootstrap.
  • Disable instrumentation Javadoc and configure the main and instrumentation
    forbidden-API signature files.
  • Supply common annotation processors, compile-only, implementation, and test
    dependencies, including interoperability with core JDK instrumentations.
  • Supply the base dependencies of additional main_javaNImplementation
    configurations, including configurations registered after plugin application.
  • Set -Dtest.dd.latestDepTest=true on latestDepTest, latestDepForkedTest,
    and latestDepTestForkedTest.

The parent still owns dependency aggregation, the instrumentation shadow jar,
index generation, and muzzle-report aggregation. Its small subprojects block
still adds instrumentation projects to the parent, excluding the Redis and Tibco
stub projects. Removing that aggregation is a separate change.

Kotlin DSL and plugin availability

The staged change declares java in the shared Java convention's plugins {}
block so consuming conventions can use generated Java dependency accessors.

Forbidden APIs is available to convention compilation through
implementation(libs.forbiddenapis) in buildSrc/build.gradle.kts. The
instrumentation convention declares id("de.thetaphi.forbiddenapis") and uses
the generated forbiddenApis {} accessor. The redundant root plugin declaration
is removed; other Java modules retain their existing application through
gradle/forbiddenapis.gradle.

The two binary plugins produced by the same buildSrc build still use:

pluginManager.apply("dd-trace-java.build-time-instrumentation")
pluginManager.apply("dd-trace-java.muzzle")

Putting these IDs in this convention's plugins {} block currently fails during
generatePrecompiledScriptPluginAccessors: their implementations are not yet
available there. Keep the runtime application until the implementations are
available on the convention compilation classpath. Moving the implementations
and their composing conventions together to build-logic is a later step.

Version catalogs use versionCatalogs.named("libs"). A lookup such as
findLibrary("autoservice-processor").get() unwraps an Optional and retains the
dependency Provider; it does not eagerly resolve the dependency. Reuse repeated
lookups without introducing generated-catalog classpath workarounds.

Local validation

  • The agent and instrumentation shadow jars are byte-identical to the baseline
    built from the same revision, a959c192be.
  • Warm agent builds preserve the baseline task outcomes.
  • Focused instrumentation tests, main and additional-source-set forbidden-API
    checks, and representative SpotBugs tasks passed during the extraction.
  • Moving java into the shared convention passed forced accessor regeneration
    and Kotlin compilation, followed by the agent build and jar comparison.

These checks used an isolated Maven-local directory for the agent build because
the normal local repository lacks sisu-guice-3.1.0-no_aop.jar. The token-gated
Akka HTTP 10.6 module was omitted consistently from both compared builds.
The separate IntelliJ/JUnit launcher issue is an environment-dependent follow-up;
its workaround is excluded from this migration.

Ownership and naming

Keep dd-trace-java.module.<role> for module entry points and
dd-trace-java.conventions.<capability> for reusable behavior. Test-only leaves
belong under dd-trace-java.conventions.testing.*. Preserve established feature
plugin IDs such as dd-trace-java.muzzle and dd-trace-java.test-jvm-constraints.

Prefer precompiled Kotlin scripts for composition. Use binary plugins and typed
tasks or extensions where the behavior needs an implementation or a consumer API.
Do not introduce an umbrella extension, feature flag, or helper layer just to
relocate existing configuration.

Keep module defaults in the convention that owns the module role. Aggregation,
packaging, and distribution wiring stay with the project or plugin that produces
the aggregate artifact. In particular, the agent distribution should eventually
compose only the Java, archive, and publishing behavior it needs.

Use build-logic/conventions for independently applied conventions and for
conventions composed within build-logic. Keep conventions needed by existing
buildSrc plugins in buildSrc until their composing plugins can move too.
Project plugin resolution through an included build does not make its classes
available to the parent buildSrc classloader.

Remaining migration sequence

  1. Publish the instrumentation extraction as a focused PR. Preserve the parent
    aggregation and the existing module plugin IDs.
  2. Apply the same ownership split to smoke tests: move module Javadoc policy,
    forbidden-API policy, and agent-jar test wiring out of dd-smoke-tests parent
    configuration. Preserve its shared dependency aggregation and verify Play,
    native-image, and custom application-jar cases separately.
  3. Extract independent leaves from the Java scripts. Split Groovy/Spock support
    from language-neutral test dependencies; migrate CodeNarc with Groovy support.
    Keep Kotlin and Scala as opt-in siblings that react to Groovy when present.
  4. Extract default Java compilation, compiler/toolchain helpers, and additional
    versioned source sets as separate changes. Keep temporary delegating Groovy
    API shims while existing consumers still need them.
  5. Extract archive, Javadoc, JaCoCo, forbidden-API, SpotBugs, Spotless, and testing
    behavior into focused conventions. Preserve JVM test suites, special test
    targets, test jars, task laziness, and toolchain behavior.
  6. Migrate publication/POM handling and repository/shared-dependency policy in
    separate changes. Repositories must be verified across the independent main,
    buildSrc, build-logic, and nested smoke-test builds.
  7. Move the remaining composing conventions and binary plugin implementations
    from buildSrc to build-logic together. Replace imperative plugin application
    with plugins {} where the new classpath supports it.
  8. Delete each obsolete script or compatibility shim once no consumer remains.
    Moving configuration alone does not establish configuration-cache support.

The detailed Java decomposition uses focused conventions for
java-compilation, java-toolchains, java-versioned-source-sets, archives,
javadoc, code-quality, jacoco, and testing. Testing further separates
dependencies, execution, JVM suites, test jars, Testcontainers, and opt-in
language support. Introduce each when its responsibility is extracted.

Verification for each slice

  • Compile the affected convention plugins and configure representative consumers.
  • Exercise the affected behavior, including late-registered tasks/source sets and
    both ordinary and latest-dependency test variants where applicable.
  • For packaging-affecting changes, compare artifacts from the same revision and
    environment. Compare archive contents if an intentional version change prevents
    byte equality.
  • Run the same Gradle command again and compare task outcomes. Investigate an
    unexpected rerun instead of treating a successful build as sufficient.
  • Run the applicable formatting checks and git diff --check.
  • Verify IntelliJ sync when plugin classpaths, Kotlin accessors, or dependency
    models change. Record local repository or credential exclusions explicitly.
  • Claim configuration-cache compatibility only after the relevant invocation
    has been tested with configuration caching enabled.

Related work

Existing issue references are retained here:

Activity

  1. self-assigned this
    on Aug 21, 2026
  2. added theissue type on Aug 21, 2026
  3. changed the title [-]Migration to convention plugins[/-] [+]Overhaul script plugins as convention plugins[/+] on Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions