Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- name: Build Site
run: |
# Don't cache it to track updates.
pip install mkdocs-material mdx_truly_sane_lists
pip install mkdocs-material mdx_truly_sane_lists mkdocs-callouts
mkdocs build
- uses: actions/upload-pages-artifact@v5
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/links.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
- name: Mkdocs build validation
run: |
# Don't cache it to track updates.
pip install mkdocs-material mdx_truly_sane_lists
pip install mkdocs-material mdx_truly_sane_lists mkdocs-callouts
mkdocs build --strict
- uses: umbrelladocs/action-linkspector@v1
with:
Expand Down
84 changes: 38 additions & 46 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,22 +85,21 @@

## [9.5.0](https://github.com/GradleUp/shadow/releases/tag/9.5.0) - 2026-07-06

!!! note

With the introduction of `DuplicatesStrategy` checking for transformers, you may see warnings like:

```
'META-INF/...kotlin_module' is matched by com.github.jengelman.gradle.plugins.shadow.transformers.KotlinModuleMetadataTransformer but its DuplicatesStrategy is EXCLUDE — duplicates may be silently dropped before the transformer processes them.
```

If you do not need Kotlin module metadata remapping, you can disable it:

```
tasks.shadowJar {
@Suppress("DEPRECATION") // This flag will be disabled and removed in the next major version of Shadow.
enableKotlinModuleRemapping = false
}
```
> [!NOTE]
> With the introduction of `DuplicatesStrategy` checking for transformers, you may see warnings like:
>
> ```
> 'META-INF/...kotlin_module' is matched by com.github.jengelman.gradle.plugins.shadow.transformers.KotlinModuleMetadataTransformer but its DuplicatesStrategy is EXCLUDE — duplicates may be silently dropped before the transformer processes them.
> ```
>
> If you do not need Kotlin module metadata remapping, you can disable it:
>
> ```
> tasks.shadowJar {
> @Suppress("DEPRECATION") // This flag will be disabled and removed in the next major version of Shadow.
> enableKotlinModuleRemapping = false
> }
> ```

### Added

Expand Down Expand Up @@ -342,14 +341,12 @@

## [9.0.1](https://github.com/GradleUp/shadow/releases/tag/9.0.1) - 2025-08-09

!!! note

If you are upgrading from 8.x versions, please read 9.0.0 release notes first.

!!! tip
> [!NOTE]
> If you are upgrading from 8.x versions, please read 9.0.0 release notes first.

You can diff the shadowed JARs when upgrading from 8.x to 9.x by using [Diffuse](https://github.com/JakeWharton/diffuse).
If there are any things missing in the changelog or the doc site, please report them to us.
> [!TIP]
> You can diff the shadowed JARs when upgrading from 8.x to 9.x by using [Diffuse](https://github.com/JakeWharton/diffuse).
> If there are any things missing in the changelog or the doc site, please report them to us.

### Changed

Expand All @@ -367,23 +364,20 @@

## [9.0.0](https://github.com/GradleUp/shadow/releases/tag/9.0.0) - 2025-08-07

!!! warning
> [!WARNING]
> This release is a major update from the 8.x series. The plugin has been fully rewritten in Kotlin, bringing
> significant improvements to maintainability, performance, and future extensibility. It introduces many new features,
> enhancements, and bug fixes, and includes several breaking changes. Please review the changelog carefully and consult
> the [new doc site](https://gradleup.com/shadow/) before upgrading.
>
> *If you really don't want to upgrade, you can still use the 8.3.x, which is also Gradle 9 compatible. But no additional features or crucial bug fixes will be included in the 8.x line.*

This release is a major update from the 8.x series. The plugin has been fully rewritten in Kotlin, bringing
significant improvements to maintainability, performance, and future extensibility. It introduces many new features,
enhancements, and bug fixes, and includes several breaking changes. Please review the changelog carefully and consult
the [new doc site](https://gradleup.com/shadow/) before upgrading.
> [!TIP]
> You can diff the shadowed JARs when upgrading from 8.x to 9.x by using [Diffuse](https://github.com/JakeWharton/diffuse).
> If there are any things missing in the changelog or the doc site, please report them to us.

*If you really don't want to upgrade, you can still use the 8.3.x, which is also Gradle 9 compatible. But no additional features or crucial bug fixes will be included in the 8.x line.*

!!! tip

You can diff the shadowed JARs when upgrading from 8.x to 9.x by using [Diffuse](https://github.com/JakeWharton/diffuse).
If there are any things missing in the changelog or the doc site, please report them to us.

!!! note

Release notes for 9.0.0 beta and rc versions are available on [GitHub Releases](https://github.com/GradleUp/shadow/releases).
> [!NOTE]
> Release notes for 9.0.0 beta and rc versions are available on [GitHub Releases](https://github.com/GradleUp/shadow/releases).

### Added

Expand Down Expand Up @@ -567,10 +561,9 @@ See more details about the fixed `DuplicatesStrategy` behaviors at [Handling Dup

## [8.3.11](https://github.com/GradleUp/shadow/releases/tag/8.3.11) - 2026-05-28

!!! warning

Only Gradle 9 support is being backported to this version. No additional features or crucial bug fixes will be
included in the 8.x line. Please migrate to Shadow 9 as soon as possible.
> [!WARNING]
> Only Gradle 9 support is being backported to this version. No additional features or crucial bug fixes will be
> included in the 8.x line. Please migrate to Shadow 9 as soon as possible.

### Changed

Expand Down Expand Up @@ -700,10 +693,9 @@ See more details about the fixed `DuplicatesStrategy` behaviors at [Handling Dup

## [8.1.1](https://github.com/GradleUp/shadow/releases/tag/8.1.1) - 2023-03-20

!!! note

As of this version, the GitHub repository has migrated to the `main` branch as the default branch for
releases.
> [!NOTE]
> As of this version, the GitHub repository has migrated to the `main` branch as the default branch for
> releases.

### What's Changed

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Shadow uses [Android Lint](https://developer.android.com/studio/write/lint) to c
Shadow's user guide is built using [MkDocs Material](https://squidfunk.github.io/mkdocs-material/). You can build and
preview the documentation website locally:

- **Install MkDocs dependencies**: `pip install mkdocs-material mdx_truly_sane_lists`
- **Install MkDocs dependencies**: `pip install mkdocs-material mdx_truly_sane_lists mkdocs-callouts`
- **Preview documentation locally**: `mkdocs serve` (then navigate to `http://127.0.0.1:8000/`)
- **Build the static site**: `mkdocs build`

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ with R8/ProGuard. The Gradle counterpart to Maven Shade Plugin.
[![CI](https://github.com/GradleUp/shadow/actions/workflows/build.yml/badge.svg?branch=main&event=push)](https://github.com/GradleUp/shadow/actions/workflows/build.yml?query=branch:main+event:push)
[![License](https://img.shields.io/github/license/GradleUp/shadow.svg)](LICENSE)

> [!NOTE]\
> [!NOTE]
> Previously this plugin was developed by [@johnrengelman](https://github.com/johnrengelman) and published under the
> ID [`com.github.johnrengelman.shadow`][johnrengelman's] before maintenance was transferred to the
> [GradleUp organization](https://github.com/GradleUp) to ensure future development, see
Expand Down
19 changes: 10 additions & 9 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
A Gradle plugin for creating fat/uber JARs, transforming files, relocating packages, and optimizing applications with
R8/ProGuard. The Gradle counterpart to Maven Shade Plugin.

!!! warning "Plugin ID Change"

Previously this plugin was developed by [@johnrengelman][johnrengelman] and published under the ID
[`com.github.johnrengelman.shadow`][johnrengelman's] before maintenance was transferred to the
[GradleUp organization][GradleUp] to ensure future development, see [#908].

If you are still using the old plugin ID in your build script, we recommend to switch to the new plugin ID
[`com.gradleup.shadow`][gradleup's] and update to the latest version to receive all the latest bug fixes and
improvements.
> [!WARNING]
> **Plugin ID Change**
>
> Previously this plugin was developed by [@johnrengelman][johnrengelman] and published under the ID
> [`com.github.johnrengelman.shadow`][johnrengelman's] before maintenance was transferred to the
> [GradleUp organization][GradleUp] to ensure future development, see [#908].
>
> If you are still using the old plugin ID in your build script, we recommend to switch to the new plugin ID
> [`com.gradleup.shadow`][gradleup's] and update to the latest version to receive all the latest bug fixes and
> improvements.

| Shadow Version | Min Gradle Version | Min Java Version | Plugin ID |
|----------------|--------------------|------------------|------------------------------------------------------|
Expand Down
1 change: 0 additions & 1 deletion docs/changes/README.md

This file was deleted.

1 change: 1 addition & 0 deletions docs/changes/README.md
7 changes: 3 additions & 4 deletions docs/configuration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,9 @@ Inspecting the `META-INF/MANIFEST.MF` entry in the JAR file will reveal the foll
Class-Path: junit-3.8.2.jar
```

!!! important

When deploying a shadowed JAR as an execution JAR, any non-bundled runtime dependencies **must** be deployed in the
location specified in the `Class-Path` entry in the manifest.
> [!IMPORTANT]
> When deploying a shadowed JAR as an execution JAR, any non-bundled runtime dependencies **must** be deployed in the
> location specified in the `Class-Path` entry in the manifest.

## Configuring the JAR Manifest

Expand Down
37 changes: 18 additions & 19 deletions docs/configuration/dependencies/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,16 @@ The above code sample would configure the [`ShadowJar`][ShadowJar] task to merge
`compileClasspath` configuration. This means any dependency declared in the `runtimeOnly` configuration would be **not**
be included in the final JAR.

!!! warning "Required Configuration"

Note the literal use of [`project.configurations`][Project.configurations] when setting the
[`configurations`][ShadowJar.configurations] attribute of a [`ShadowJar`][ShadowJar] task.

This is **required**. It may be tempting to specify `configurations = [configurations.compileClasspath]` but
this will not have the intended effect, as `configurations.compile` will try to delegate to the
[`configurations`][ShadowJar.configurations] property of the [`ShadowJar`][ShadowJar] task instead of the
`project`.
> [!WARNING]
> **Required Configuration**
>
> Note the literal use of [`project.configurations`][Project.configurations] when setting the
> [`configurations`][ShadowJar.configurations] attribute of a [`ShadowJar`][ShadowJar] task.
>
> This is **required**. It may be tempting to specify `configurations = [configurations.compileClasspath]` but
> this will not have the intended effect, as `configurations.compile` will try to delegate to the
> [`configurations`][ShadowJar.configurations] property of the [`ShadowJar`][ShadowJar] task instead of the
> `project`.

## Embedding Local Jar Files into Your Shadowed JAR

Expand Down Expand Up @@ -205,11 +206,10 @@ Individual dependencies can be filtered from the final JAR by using the `depende
[`ShadowJar`][ShadowJar] task. Dependency filtering does **not** apply to transitive dependencies. That is, excluding a
dependency does not exclude any of its dependencies from the final JAR.

!!! note

Excluding a dependency via `dependencies { exclude(...) }` removes it entirely from the shadow JAR. If you instead
want the dependency to be bundled into the shadow JAR but prevented from having its unused classes stripped during
minimization, see [`minimize { exclude(...) }`][minimizing].
> [!NOTE]
> Excluding a dependency via `dependencies { exclude(...) }` removes it entirely from the shadow JAR. If you instead
> want the dependency to be bundled into the shadow JAR but prevented from having its unused classes stripped during
> minimization, see [`minimize { exclude(...) }`][minimizing].

The `dependency` blocks provides a number of methods for resolving dependencies using the notations familiar from
Gradle's [`project.configurations`][Project.configurations] block.
Expand Down Expand Up @@ -270,11 +270,10 @@ Gradle's [`project.configurations`][Project.configurations] block.
}
```

!!! note

While not being able to filter entire transitive dependency graphs might seem like an oversight, it is necessary
because it would not be possible to intelligently determine the build author's intended results when there is a
common dependency between two 1st level dependencies when one is excluded and the other is not.
> [!NOTE]
> While not being able to filter entire transitive dependency graphs might seem like an oversight, it is necessary
> because it would not be possible to intelligently determine the build author's intended results when there is a
> common dependency between two 1st level dependencies when one is excluded and the other is not.

### Using Regex Patterns to Filter Dependencies

Expand Down
73 changes: 39 additions & 34 deletions docs/configuration/merging/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@ Maven Shade implementation. A [`ResourceTransformer`][ResourceTransformer] is in
being written to the final output JAR. This allows a [`ResourceTransformer`][ResourceTransformer] to determine if it
should process a particular entry and apply any modifications before writing the stream to the output.

!!! important "Guaranteed Processing Order"

[`ResourceTransformer`][ResourceTransformer] follows a guaranteed processing order:

1. **Project files first**: All files in projects are processed before any dependency files.
2. **Dependency files second**: Files from configurations (runtime dependencies) or added via
[`ShadowJar.from`][ShadowJar.from] are processed after project files.

This ordering is crucial when merging configuration files where you want to preserve project-specific values while
merging in additional data from dependencies.
> [!IMPORTANT]
> **Guaranteed Processing Order**
>
> [`ResourceTransformer`][ResourceTransformer] follows a guaranteed processing order:
>
> 1. **Project files first**: All files in projects are processed before any dependency files.
> 2. **Dependency files second**: Files from configurations (runtime dependencies) or added via
> [`ShadowJar.from`][ShadowJar.from] are processed after project files.
>
> This ordering is crucial when merging configuration files where you want to preserve project-specific values while
> merging in additional data from dependencies.

## Handling Duplicates Strategy

Expand Down Expand Up @@ -59,13 +60,14 @@ Different strategies will lead to different results for `foo/bar` files in the J
exception like `Entry .* is a duplicate but no duplicate handling strategy has been set`.
- `WARN`: **Warn** about duplicates in the build log; this behaves exactly as `INCLUDE` otherwise.

!!! note "Precedence of DuplicatesStrategy"

The `duplicatesStrategy` evaluation takes precedence over transforming and relocating.
Because `ShadowJar` is a subclass of Gradle's `AbstractCopyTask`, duplicate filtering configured via
`duplicatesStrategy` is performed at Gradle's `CopySpec` processing layer **before** entries are passed to Shadow's
internal [`ResourceTransformer`][ResourceTransformer] engine.
See the [ShadowJar Execution Flow][shadowjar-execution-flow] for the complete lifecycle diagram.
> [!NOTE]
> **Precedence of DuplicatesStrategy**
>
> The `duplicatesStrategy` evaluation takes precedence over transforming and relocating.
> Because `ShadowJar` is a subclass of Gradle's `AbstractCopyTask`, duplicate filtering configured via
> `duplicatesStrategy` is performed at Gradle's `CopySpec` processing layer **before** entries are passed to Shadow's
> internal [`ResourceTransformer`][ResourceTransformer] engine.
> See the [ShadowJar Execution Flow][shadowjar-execution-flow] for the complete lifecycle diagram.

If you mix the usages of `duplicatesStrategy = DuplicatesStrategy.EXCLUDE` and
[`ResourceTransformer`][ResourceTransformer] like below:
Expand Down Expand Up @@ -120,10 +122,11 @@ Alternatively, you can follow these steps:
[`filesMatching`][Jar.filesMatching], [`filesNotMatching`][Jar.filesNotMatching], or [`eachFile`][Jar.eachFile]
functions to set their `duplicatesStrategy` to `INCLUDE` or `WARN`.

!!! warning "Build Cache Impact"

Functions inherited from [`CopySpec`][CopySpec], such as [`filesMatching`][Jar.filesMatching],
[`filesNotMatching`][Jar.filesNotMatching], [`eachFile`][Jar.eachFile], or others, disable the output caching.
> [!WARNING]
> **Build Cache Impact**
>
> Functions inherited from [`CopySpec`][CopySpec], such as [`filesMatching`][Jar.filesMatching],
> [`filesNotMatching`][Jar.filesNotMatching], [`eachFile`][Jar.eachFile], or others, disable the output caching.

Optional steps:

Expand Down Expand Up @@ -358,14 +361,15 @@ the [`ServiceFileTransformer`][ServiceFileTransformer]:
}
```

!!! note "Groovy Extension Modules"

Groovy Extension Module descriptor files (located at
`META-INF/services/org.codehaus.groovy.runtime.ExtensionModule`) are ignored by the
[`ServiceFileTransformer`][ServiceFileTransformer].
This is due to these files having a different syntax than standard service descriptor files.
Use the [`mergeGroovyExtensionModules()`][mergeGroovyExtensionModules] method to merge these files if your
dependencies contain them.
> [!NOTE]
> **Groovy Extension Modules**
>
> Groovy Extension Module descriptor files (located at
> `META-INF/services/org.codehaus.groovy.runtime.ExtensionModule`) are ignored by the
> [`ServiceFileTransformer`][ServiceFileTransformer].
> This is due to these files having a different syntax than standard service descriptor files.
> Use the [`mergeGroovyExtensionModules()`][mergeGroovyExtensionModules] method to merge these files if your
> dependencies contain them.

### Configuring the Location of Service Descriptor Files

Expand Down Expand Up @@ -877,11 +881,12 @@ If certain duplicate resources at the same path legitimately have different cont
or `pom.xml` files from different dependency versions), you can exclude those paths from being checked using
`exclude(...)`:

!!! warning "Do Not Combine with PreserveFirstFoundResourceTransformer"

Do not combine [`PreserveFirstFoundResourceTransformer`][PreserveFirstFoundResourceTransformer] with
[`DeduplicatingResourceTransformer`][DeduplicatingResourceTransformer], as they handle duplicates differently and
combining them leads to redundant or unexpected behavior.
> [!WARNING]
> **Do Not Combine with PreserveFirstFoundResourceTransformer**
>
> Do not combine [`PreserveFirstFoundResourceTransformer`][PreserveFirstFoundResourceTransformer] with
> [`DeduplicatingResourceTransformer`][DeduplicatingResourceTransformer], as they handle duplicates differently and
> combining them leads to redundant or unexpected behavior.

=== ":material-language-kotlin: build.gradle.kts"

Expand Down
Loading