Fix build-ordering race: track javaagent config as run-task input#376
Merged
Conversation
ryandens
commented
Jul 6, 2026
Owner
Author
|
Addressed in 4b96150. Switched the run task to |
JavaagentApplicationRunPlugin configured the run task's -javaagent arguments via a CommandLineArgumentProvider that resolves the javaagent configuration's files at execution time. That provider is not a tracked task input, so Gradle established no dependency on the tasks that build the agent jars. Under parallel execution the run task could launch with -javaagent:<jar> before that jar had been produced, failing with "Error opening zip file or JAR manifest missing" (reproducible 100% of the time locally via `--rerun-tasks`, and intermittently on CI). Use `dependsOn(javaagentConfiguration)`: a Configuration is Buildable, so this adds the artifact-building task dependencies and fixes the ordering. Unlike `inputs.files(...)`, it does not register the agent jars as tracked inputs, so it avoids tripping Gradle's strict implicit-dependency validation for agent jars that are added to the configuration without a declared builtBy (e.g. the otel example's :app:extendedAgent jar, which is added via project.files(singleFile) and loses its task provenance). A run task is never up-to-date, so input tracking would provide no benefit here anyway. Add a deterministic regression test that asserts, via --dry-run, that :simple-agent:jar is scheduled before :hello-world:run. The existing `can attach to application run task` test also reproduces the race, but only intermittently depending on task scheduling; the new test catches the ordering regression independent of timing (it fails without this fix, passes with it). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per review feedback, register the javaagent configuration as a tracked input of
the run task (inputs.files) rather than a bare dependsOn, matching how
JavaagentApplicationDistributionPlugin wires the start-script task. Input
tracking requires every artifact in the javaagent configuration to carry its
producing-task dependency.
Fix the otel example at the source: JavaagentOTelModificationPlugin added the
extendedAgent output via extendedAgent.outputs.files.singleFile, which resolves
to a plain File and drops the builtBy provenance, so tracking the configuration
as a run-task input tripped Gradle's implicit-dependency validation
(":app:run uses this output of task ':app:extendedAgent' without declaring ...").
Add it via project.files(extendedAgent) instead, so the producing task is
carried as a builtBy dependency and consumers that track the configuration
establish the dependency automatically.
Verified: :otel:functionalTest --rerun-tasks green, the run-task race tests green
across repeated --rerun-tasks runs, and ./gradlew build green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4b96150 to
4dafe32
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
JavaagentApplicationRunPluginwires the run task's-javaagentarguments through aCommandLineArgumentProvider(inJavaForkOptionsConfigurer) that resolves thejavaagentconfiguration's files at execution time. That provider is not a tracked task input, so Gradle established no dependency on the tasks that build the agent jars.Under parallel execution the run task could launch with
-javaagent:<jar>before that jar had been produced:Reproducible 100% locally and intermittently on CI:
./gradlew :plugin:functionalTest --tests "*can attach to application run task*" --rerun-tasksFix
Register the
javaagentconfiguration as a tracked input of the run task:A
ConfigurationisBuildable, so input-tracking makes the run task depend on the tasks that build the agent jars — the same wayJavaagentApplicationDistributionPluginalready wires the start-script task.Downstream fix in the otel modification plugin
Input-tracking requires every artifact added to the
javaagentconfiguration to carry its producing-task dependency (builtBy).JavaagentOTelModificationPluginadded theextendedAgentoutput viaextendedAgent.outputs.files.singleFile, which resolves to a plainFileand drops that provenance — so tracking the configuration as a run-task input tripped Gradle's strict implicit-dependency validation:Fixed at the source by adding it via the task provider, which carries the producing task as a
builtBydependency:project.dependencies.add("javaagent", project.files(extendedAgent))Consumers that track the configuration now establish the
:extendedAgentdependency automatically.Tests
--dry-run, that:simple-agent:jaris scheduled before:hello-world:run. It fails without this fix and passes with it — independent of task-scheduling timing.can attach to application run tasktest also reproduces the race (verified: 3/3 failures without the fix, 3/3 passes with it under--rerun-tasks).Verification
./gradlew :plugin:functionalTest --tests "*can attach to application run task*" --rerun-tasks— green, run repeatedly./gradlew :otel:functionalTest --rerun-tasks— green (implicit-dependency validation no longer tripped; reproduced the failure first, then confirmed the fix)./gradlew build— green (including spotless formatting)🤖 Generated with Claude Code
Note
Fix build-ordering race by tracking javaagent config as a run task input
javaagentconfiguration as an explicit input on theruntask inJavaagentApplicationRunPlugin, so Gradle orders agent-building tasks before the run task.JavaagentOTelModificationPluginto add theextendedAgentartifact viaproject.files(extendedAgent)instead of resolving it to a plainFile, preservingTaskProviderprovenance and itsbuiltBydependency.--dry-runto assert:simple-agent:jaris scheduled before:hello-world:run.Macroscope summarized 4dafe32.