-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Declare the jar and shadowJar dependencies of the test classpath #11996
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jjh75607
wants to merge
2
commits into
testcontainers:main
Choose a base branch
from
jjh75607:fix/test-depends-on-shaded-jar
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+10
−5
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
Repository: testcontainers/testcontainers-java
Length of output: 16264
🏁 Script executed:
Repository: testcontainers/testcontainers-java
Length of output: 17934
🌐 Web query:
GradleUp Shadow plugin 8.3.9 shadowJar dependsOn jar default archiveClassifier null same output💡 Result:
When you configure the Shadow plugin's shadowJar task to use an empty archiveClassifier (e.g., archiveClassifier.set("")), it forces the shadowJar task to produce a file name that is identical to the standard jar task's output (baseName-version.jar) [1][2]. This causes a conflict because both tasks attempt to write to the same location, potentially causing one to overwrite the other or leading to build errors regarding multiple artifacts with the same name [1][2][3]. To resolve this, you have three primary approaches: 1. Disable the standard jar task: If you only need the shadowed (fat) JAR, you can disable the default jar task [1][2]. tasks.jar { enabled = false } 2. Assign a different classifier to the standard jar: You can give the standard JAR a unique classifier so it does not collide with the shadowed JAR [1][2]. tasks.jar { archiveClassifier.set("plain") } 3. Use a different classifier for shadowJar: If you prefer keeping the default behavior, simply use a non-empty classifier for shadowJar (e.g., "all", "fat", or "shadow") [4][5]. Additionally, note that if you change the output file name to match other tasks (like those provided by the application plugin, such as startScripts or distZip), Gradle may report "implicit dependency" validation errors [6][7]. You must explicitly declare dependencies between these tasks to ensure the shadowed JAR is built before the dependent tasks attempt to use it [6][7]: tasks.named("distZip") { dependsOn(tasks.shadowJar) } Setting archiveClassifier to null or an empty string can also sometimes cause issues with publication tasks if multiple artifacts are seen as identical [8]. It is generally recommended to use an explicit string (like "") if you intend to replace the primary JAR, while being mindful of the resulting collisions [1][2].
Citations:
🌐 Web query:
Gradle Project.files(Task...) task dependencies ordering overlapping outputs documentation Gradle 8.14💡 Result:
In Gradle 8.14, the Project.files(Object...) method creates a FileCollection that tracks both the files it contains and the tasks that produce them [1][2]. When a FileCollection containing task outputs is used as an input to another task, Gradle automatically establishes an implicit task dependency [1][3]. Task Dependencies and Ordering Gradle uses both explicit and implicit dependencies to order task execution [4]. 1. Implicit Dependencies: By using a Task or FileCollection (representing task outputs) as an input, Gradle infers that the consuming task requires the producing task to run first [1][3][4]. 2. Explicit Dependencies: You can manually define ordering using properties like dependsOn or mustRunAfter [4][5]. 3. Limitation: Simply using the copy method or referencing a directory as an input does not always create an automatic dependency. For reliable dependency management, it is recommended to use the formal Task input/output API (
@InputFiles,@OutputDirectory, etc.) or project-level file collections that link directly to tasks [6][3]. Overlapping Outputs Gradle detects when multiple tasks write to the same location (overlapping outputs) [7]. When this occurs: - Gradle may disable task output caching for the affected tasks to prevent incorrect cache entries [7]. - If Gradle cannot guarantee correct ordering, it may fail or prevent parallel execution of tasks targeting the same output directory [5][7]. - Official documentation strongly advises against having multiple tasks write to the same output directory [5]. Instead, you should configure tasks to use distinct output locations [5]. If shared files are necessary, use explicit task ordering (e.g., dependsOn) or ensure inputs and outputs are properly isolated [5]. For diagnostic purposes, running Gradle with the --info flag will provide details regarding why caching might be disabled or how tasks are ordered in the event of overlapping outputs [7].Citations:
🌐 Web query:
site:github.com/GradleUp/shadow "shadowJar.dependsOn(jar)" ShadowJar 8.3.9💡 Result:
In the context of the Gradle Shadow plugin (including version 8.3.9), the statement shadowJar.dependsOn(jar) is a manual task dependency configuration [1][2]. By default, the Shadow plugin is designed to automatically handle project dependencies declared in your build configuration [3]. The shadowJar task is typically configured to include the output of the main source set and its runtime dependencies [3]. You would generally use shadowJar.dependsOn(jar) (or a similar construction) only in specific, non-standard scenarios, such as: 1. Custom Task Dependencies: If you have created a custom task (e.g., generating extra resources, copying files, or building another specific JAR) that must complete before the shadowJar task runs [1][2][4]. 2. Multi-project Builds: In some complex multi-project setups, you may need to explicitly force a dependency on a shadowJar task from another subproject to ensure that the required artifacts are available and up-to-date [4]. 3. Resolving Build Validation Warnings: If Gradle detects an "implicit dependency" warning where one task consumes the output of another without an explicit dependency declaration, adding a dependsOn configuration is a standard way to satisfy Gradle's task graph validation [5][4]. It is important to note that the shadowJar task does not automatically add itself to the standard Gradle build task [6]. If your intention is for the shadow JAR to be built whenever you run./gradlew build, you should configure that dependency explicitly [6]: tasks.build.dependsOn tasks.shadowJar For modern versions of the Shadow plugin (including 8.3.9), ensure you are using the correct plugin ID (com.gradleup.shadow) and that your configuration follows the plugin's documented practices for custom tasks and multi-project builds [7].
Citations:
🌐 Web query:
site:gradleup.com/shadow 8.3.9 shadowJar jar dependsOn default task💡 Result:
The shadowJar task, provided by the Shadow Gradle plugin, is an extension of the standard Gradle Jar task [1]. Because it inherits from the base Jar task type, it possesses the same task dependency mechanisms as any other Gradle task [1]. In Gradle, you can manage task dependencies for the shadowJar task using the standard dependsOn method [2][3]. For example, if you need the shadowJar task to depend on a custom task or another lifecycle task, you can configure it in your build script as follows: tasks.shadowJar { dependsOn(tasks.named("someOtherTask")) } The shadowJar task also has its own specific internal configurations. By default, it is configured to merge all dependencies from the project's runtimeClasspath or runtime configuration into the final JAR [4][5]. While it operates on these dependencies, it does not require special configuration to trigger standard task dependencies; you can simply use the standard Gradle API [2][1]. Regarding version 8.3.9, which was released on August 5, 2025, the release notes indicate performance improvements related to Zip file writing [6]. There were no noted changes in how task dependencies are defined or how the shadowJar task interacts with default Gradle tasks in that specific version [6].
Citations:
Order
jarbeforeshadowJar.files(producers)makestestdepend on both tasks but does not order them. Where both tasks write the same archive,jarcan run aftershadowJarand leave tests with unshaded contents. Addtasks.shadowJar.dependsOn(tasks.jar)or configure distinct outputs.🤖 Prompt for AI Agents
Source: MCP tools