// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

[[gradle_wrapper]]
= The Gradle Wrapper

The recommended way to execute any Gradle build is with the help of the Gradle Wrapper (in short just “Wrapper”). The Wrapper is a script that invokes a declared version of Gradle, downloading it beforehand if necessary. As a result, developers can get up and running with a Gradle project quickly without having to follow manual installation processes saving your company time and money.

.The Wrapper workflow
image::wrapper-workflow.png[]

**In a nutshell you gain the following benefits:**

- Standardizes a project on a given Gradle version, leading to more reliable and robust builds.
- Provisioning a new Gradle version to different users and execution environment (e.g. IDEs or Continuous Integration servers) is as simple as changing the Wrapper definition.

**So how does it work? For a user there are typically three different workflows:**

- You set up a new Gradle project and want to <<#sec:adding_wrapper,add the Wrapper>> to it.
- You want to <<#sec:using_wrapper,run a project with the Wrapper>> that already provides it.
- You want to <<#sec:upgrading_wrapper,upgrade the Wrapper>> to a new version of Gradle.

The following sections explain each of these use cases in more detail.

[[sec:adding_wrapper]]
== Adding the Gradle Wrapper

Generating the Wrapper files requires an installed version of the Gradle runtime on your machine as described in <<installation.adoc#installation,Installation>>. Thankfully, generating the initial Wrapper files is a one-time process.

Every vanilla Gradle build comes with a built-in task called `wrapper`. You’ll be able to find the task listed under the group "Build Setup tasks" when <<command_line_interface.adoc#sec:listing_tasks,listing the tasks>>. Executing the `wrapper` task generates the necessary Wrapper files in the project directory.

.Running the Wrapper task
----
$ gradle wrapper
include::{snippetsPath}/wrapper/simple/tests/wrapperCommandLine.out[]
----

[NOTE]
====
To make the Wrapper files available to other developers and execution environments you’ll need to check them into version control. All Wrapper files including the JAR file are very small in size. Adding the JAR file to version control is expected. Some organizations do not allow projects to submit binary files to version control. At the moment there are no alternative options to the approach.
====

The generated Wrapper properties file, `gradle/wrapper/gradle-wrapper.properties`, stores the information about the Gradle distribution.

* The server hosting the Gradle distribution.
* The type of Gradle distribution. By default that’s the `-bin` distribution containing only the runtime but no sample code and documentation.
* The Gradle version used for executing the build. By default the `wrapper` task picks the exact same Gradle version that was used to generate the Wrapper files.


.Example: The generated distribution URL
[source,properties,subs=+attributes]
.`gradle/wrapper/gradle-wrapper.properties`
----
distributionUrl=https\://services.gradle.org/distributions/gradle-{gradleVersion}-bin.zip
----

All of those aspects are configurable at the time of generating the Wrapper files with the help of the following command line options.

`--gradle-version`::
The Gradle version used for downloading and executing the Wrapper.

`--distribution-type`::
The Gradle distribution type used for the Wrapper. Available options are `bin` and `all`. The default value is `bin`.

`--gradle-distribution-url`::
The full URL pointing to Gradle distribution ZIP file. Using this option makes `--gradle-version` and `--distribution-type` obsolete as the URL already contains this information. This option is extremely valuable if you want to host the Gradle distribution inside your company’s network.

`--gradle-distribution-sha256-sum`::
The SHA256 hash sum used for <<#sec:verification,verifying the downloaded Gradle distribution>>.

Let’s assume the following use case to illustrate the use of the command line options. You would like to generate the Wrapper with version {gradleVersion} and use the `-all` distribution to enable your IDE to enable code-completion and being able to navigate to the Gradle source code. Those requirements are captured by the following command line execution:

.Providing options to Wrapper task
[listing,subs=+attributes]
----
$ gradle wrapper --gradle-version {gradleVersion} --distribution-type all
include::{snippetsPath}/wrapper/simple/tests/wrapperCommandLine.out[]
----

As a result you can find the desired information in the Wrapper properties file.

[source,properties,subs=+attributes]
.Example: The generated distribution URL
----
distributionUrl=https\://services.gradle.org/distributions/gradle-{gradleVersion}-all.zip
----

Let’s have a look at the following project layout to illustrate the expected Wrapper files:

====
[.multi-language-sample]
=====
[source,groovy]
----
.
├── a-subproject
│   └── build.gradle
├── settings.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat
----
=====
[.multi-language-sample]
=====
[source,kotlin]
----
.
├── a-subproject
│   └── build.gradle.kts
├── settings.gradle.kts
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat
----
=====
====

A Gradle project typically provides a `settings.gradle(.kts)` file and one `build.gradle(.kts)` file for each subproject.
The Wrapper files live alongside in the `gradle` directory and the root directory of the project.
The following list explains their purpose.

`gradle-wrapper.jar`::
The Wrapper JAR file containing code for downloading the Gradle distribution.

`gradle-wrapper.properties`::
A properties file responsible for configuring the Wrapper runtime behavior e.g. the Gradle version compatible with this version. Note that more generic settings, like <<build_environment.adoc#sec:accessing_the_web_via_a_proxy,configuring the Wrapper to use a proxy>>, need to go into a <<build_environment.adoc#sec:gradle_configuration_properties,different file>>.

`gradlew`, `gradlew.bat`::
A shell script and a Windows batch script for executing the build with the Wrapper.

You can go ahead and <<#sec:using_wrapper,execute the build with the Wrapper>> without having to install the Gradle runtime. If the project you are working on does not contain those Wrapper files then you’ll need to <<#sec:adding_wrapper,generate them>>.

[[sec:using_wrapper]]
== Using the Gradle Wrapper

It is recommended to always execute a build with the Wrapper to ensure a reliable, controlled and standardized execution of the build. Using the Wrapper looks almost exactly like running the build with a Gradle installation. Depending on the operating system you either run `gradlew` or `gradlew.bat` instead of the `gradle` command. The following console output demonstrate the use of the Wrapper on a Windows machine for a Java-based project.

.Executing the build with the Wrapper batch file
----
$ gradlew.bat build
include::{snippetsPath}/wrapper/simple/tests/wrapperBatchFileExecution.out[]
----

In case the Gradle distribution is not available on the machine, the Wrapper will download it and store in the local file system. Any subsequent build invocation is going to reuse the existing local distribution as long as the distribution URL in the Gradle properties doesn't change.

[NOTE]
====
The Wrapper shell script and batch file reside in the root directory of a single or multi-project Gradle build. You will need to reference the correct path to those files in case you want to execute the build from a subproject directory e.g. `../../gradlew tasks`.
====

[[sec:upgrading_wrapper]]
== Upgrading the Gradle Wrapper

Projects will typically want to keep up with the times and upgrade their Gradle version to benefit from new features and improvements. One way to upgrade the Gradle version is manually change the `distributionUrl` property in the Wrapper's `gradle-wrapper.properties` file. The better and recommended option is to run the `wrapper` task and provide the target Gradle version as described in <<#sec:adding_wrapper,Adding the Gradle Wrapper>>. Using the `wrapper` task ensures that any optimizations made to the Wrapper shell script or batch file with that specific Gradle version are applied to the project. As usual, you should commit the changes to the Wrapper files to version control.

Note that running the wrapper task once will update `gradle-wrapper.properties` only, but leave the wrapper itself in `gradle-wrapper.jar` untouched. This is usually fine as new versions of Gradle can be run even with ancient wrapper files. If you nevertheless want *all* the wrapper files to be completely up-to-date, you'll need to run the `wrapper` task a second time.

Use the Gradle `wrapper` task to generate the wrapper, specifying a version. The default is the current version. Once you have upgraded the wrapper, you can check that it's the version you expect by executing `./gradlew --version`.

.Example: Upgrading the Wrapper version
[listing,subs=+attributes]
----
$ ./gradlew wrapper --gradle-version {gradleVersion}
include::{snippetsPath}/wrapper/simple/tests/wrapperGradleVersionUpgrade.out[]
----

[[customizing_wrapper]]
== Customizing the Gradle Wrapper

Most users of Gradle are happy with the default runtime behavior of the Wrapper. However, organizational policies, security constraints or personal preferences might require you to dive deeper into customizing the Wrapper. Thankfully, the built-in `wrapper` task exposes numerous options to bend the runtime behavior to your needs. Most configuration options are exposed by the underlying task type link:{groovyDslPath}/org.gradle.api.tasks.wrapper.Wrapper.html[Wrapper].

Let’s assume you grew tired of defining the `-all` distribution type on the command line every time you upgrade the Wrapper. You can save yourself some keyboard strokes by re-configuring the `wrapper` task.

.Customizing the Wrapper task
====
include::sample[dir="snippets/wrapper/customized-task/groovy",files="build.gradle[tags=customized-wrapper-task]"]
include::sample[dir="snippets/wrapper/customized-task/kotlin",files="build.gradle.kts[tags=customized-wrapper-task]"]
====

With the configuration in place running `./gradlew wrapper --gradle-version {gradleVersion}` is enough to produce a `distributionUrl` value in the Wrapper properties file that will request the `-all` distribution.

[listing,subs=+attributes]
.The generated distribution URL
----
distributionUrl=https\://services.gradle.org/distributions/gradle-{gradleVersion}-all.zip
----

Check out the API documentation for more detail descriptions of the available configuration options. You can also find various samples for configuring the Wrapper in the Gradle distribution.

[[sec:authenticated_download]]
=== Authenticated Gradle distribution download

The Gradle `Wrapper` can download Gradle distributions from servers using HTTP Basic Authentication. This enables you to host the Gradle distribution on a private protected server. You can specify a username and password in two different ways depending on your use case: as system properties or directly embedded in the `distributionUrl`. Credentials in system properties take precedence over the ones embedded in `distributionUrl`.

[TIP]
.Security Warning
====
HTTP Basic Authentication should only be used with `HTTPS` URLs and not plain `HTTP` ones. With Basic Authentication, the user credentials are sent in clear text.
====

Using system properties can be done in the `.gradle/gradle.properties` file in the user's home directory, or by other means, see <<build_environment.adoc#sec:gradle_configuration_properties,Gradle Configuration Properties>>.

[source,properties]
.Specifying the HTTP Basic Authentication credentials using system properties
----
systemProp.gradle.wrapperUser=username
systemProp.gradle.wrapperPassword=password
----

Embedding credentials in the `distributionUrl` in the `gradle/wrapper/gradle-wrapper.properties` file also works. Please note that this file is to be committed into your source control system. Shared credentials embedded in `distributionUrl` should only be used in a controlled environment.

[listing]
.Specifying the HTTP Basic Authentication credentials in `distributionUrl`
----
distributionUrl=https://username:password@somehost/path/to/gradle-distribution.zip
----

This can be used in conjunction with a proxy, authenticated or not. See <<build_environment.adoc#sec:accessing_the_web_via_a_proxy,Accessing the web via a proxy>> for more information on how to configure the `Wrapper` to use a proxy.

[[sec:verification]]
=== Verification of downloaded Gradle distributions

The Gradle Wrapper allows for verification of the downloaded Gradle distribution via SHA-256 hash sum comparison. This increases security against targeted attacks by preventing a man-in-the-middle attacker from tampering with the downloaded Gradle distribution.

To enable this feature, download the `.sha256` file associated with the Gradle distribution you want to verify.

==== Downloading the SHA-256 file

You can download the `.sha256` file from the link:https://services.gradle.org/distributions/[stable releases] or link:https://services.gradle.org/distributions-snapshots/[release candidate and nightly releases]. The format of the file is a single line of text that is the SHA-256 hash of the corresponding zip file.

You can also reference the link:https://gradle.org/release-checksums/[list of Gradle distribution checksums].

==== Configuring checksum verification

Add the downloaded hash sum to `gradle-wrapper.properties` using the `distributionSha256Sum` property or use `--gradle-distribution-sha256-sum` on the command-line.

[source,properties]
.Configuring SHA-256 checksum verification
----
distributionSha256Sum=371cb9fbebbe9880d147f59bab36d61eee122854ef8c9ee1ecf12b82368bcf10
----

Gradle will report a build failure in case the configured checksum does not match the checksum found on the server for hosting the distribution. Checksum Verification is only performed if the configured Wrapper distribution hasn't been downloaded yet.

[[wrapper_checksum_verification]]
== Verifying the integrity of the Gradle Wrapper JAR

The Wrapper JAR is a binary file that will be executed on the computers of developers and build servers.
As with all such files, you should be sure that it's trustworthy before executing it.
Since the Wrapper JAR is usually checked into a project's version control system, there is the potential for a malicious actor to replace the original JAR with a modified one by submitting a pull request that seemingly only upgrades the Gradle version.

To verify the integrity of the Wrapper JAR, Gradle has created a link:https://github.com/marketplace/actions/gradle-wrapper-validation[GitHub Action] that automatically checks Wrapper JARs in pull requests against a list of known good checksums.
Gradle also publishes the link:https://gradle.org/release-checksums/[checksums of all releases] (except for version 3.3 to 4.0.2, which did not generate reproducible JARs), so you can manually verify the integrity of the Wrapper JAR.

=== Automatically verifying the Gradle Wrapper JAR on GitHub

The link:https://github.com/marketplace/actions/gradle-wrapper-validation[GitHub Action] is released separately from Gradle, so please check its documentation for how to apply it to your project.

=== Manually verifying the Gradle Wrapper JAR
You can manually verify the checksum of the Wrapper JAR to ensure that it has not been tampered with by running the following commands on one of the major operating systems:

[source,bash,subs=+attributes]
.Manually verifying the checksum of the Wrapper JAR on Linux
----
$ cd gradle/wrapper
$ curl --location --output gradle-wrapper.jar.sha256 \
       https://services.gradle.org/distributions/gradle-{gradleVersion}-wrapper.jar.sha256
$ echo "  gradle-wrapper.jar" >> gradle-wrapper.jar.sha256
$ sha256sum --check gradle-wrapper.jar.sha256
gradle-wrapper.jar: OK
----

[source,bash,subs=+attributes]
.Manually verifying the checksum of the Wrapper JAR on macOS
----
$ cd gradle/wrapper
$ curl --location --output gradle-wrapper.jar.sha256 \
       https://services.gradle.org/distributions/gradle-{gradleVersion}-wrapper.jar.sha256
$ echo "  gradle-wrapper.jar" >> gradle-wrapper.jar.sha256
$ shasum --check gradle-wrapper.jar.sha256
gradle-wrapper.jar: OK
----

[source,powershell,subs=+attributes]
.Manually verifying the checksum of the Wrapper JAR on Windows (using PowerShell)
----
> $expected = Invoke-RestMethod -Uri https://services.gradle.org/distributions/gradle-{gradleVersion}-wrapper.jar.sha256
> $actual = (Get-FileHash gradle\wrapper\gradle-wrapper.jar -Algorithm SHA256).Hash.ToLower()
> @{$true = 'OK: Checksum match'; $false = "ERROR: Checksum mismatch!`nExpected: $expected`nActual:   $actual"}[$actual -eq $expected]
OK: Checksum match
----

=== Troubleshooting a checksum mismatch

If the checksum does not match the one you expected, chances are the `wrapper` task wasn't executed with the upgraded Gradle distribution.
Thus, you should first check whether the actual checksum matches the one of a different Gradle version.
Here are the commands you can run on the major operating systems to generate the actual checksum of the Wrapper JAR:

[source,bash,subs=+attributes]
.Generating the actual checksum of the Wrapper JAR on Linux
----
$ sha256sum gradle/wrapper/gradle-wrapper.jar
d81e0f23ade952b35e55333dd5f1821585e887c6d24305aeea2fbc8dad564b95  gradle/wrapper/gradle-wrapper.jar
----

[source,bash,subs=+attributes]
.Generating the actual checksum of the Wrapper JAR on macOS
----
$ shasum --algorithm=256 gradle/wrapper/gradle-wrapper.jar
d81e0f23ade952b35e55333dd5f1821585e887c6d24305aeea2fbc8dad564b95  gradle/wrapper/gradle-wrapper.jar
----

[source,powershell,subs=+attributes]
.Generating the actual checksum of the Wrapper JAR on Windows (using PowerShell)
----
> (Get-FileHash gradle\wrapper\gradle-wrapper.jar -Algorithm SHA256).Hash.ToLower()
d81e0f23ade952b35e55333dd5f1821585e887c6d24305aeea2fbc8dad564b95
----

Once you know the actual checksum, check whether it's listed on https://gradle.org/release-checksums/.
If it is listed, you have verified the integrity of the Wrapper JAR.
If the version of Gradle that generated the Wrapper JAR doesn't match the version in `gradle/wrapper/gradle-wrapper.properties`, it's safe to run the `wrapper` task again to update the Wrapper JAR.

If the checksum is not listed on the page, the Wrapper JAR might be from a milestone, release candidate, or nightly build or may have been generated by Gradle 3.3 to 4.0.2.
You should try to find out how it was generated but treat it as untrustworthy until proven otherwise.
If you think the Wrapper JAR was compromised, please let the Gradle team know by sending an email to mailto:security@gradle.com[security@gradle.com].
