Gradle-wrapper.jar not updated from 6.0.1 to 6.3

I have a project that is currently using Gradle 6.0.1. When running ./gradlew wrapper --gradle-version=6.3 --distribution-type=all, I see that gradle-wrapper.jar is not updated. Yet in another project, I see that the wrapper changed from 6.0.1 to 6.1.1 (though not from 6.1.1 to 6.3). But as the changes from 6.1.1 should be contained in 6.3, too, I would have expected the wrapper to do change when going from 6.0.1 straight to 6.3.

What’s wrong here?

Ah, looks like the wrapper task generates gradle-wrapper.jar (instead of e.g. downloading it from somewhere), so depending on e.g. the Java version, you might get (hash-wise) different gradle-wrapper.jar files even for the same Gradle version.

This is not quite right. While the wrapper task does use some “generator” classes, the exact gradle-wrapper.jar file is included in the Gradle distribution. The wrapper task copies the bytes from the classpath to the destination in the current project. The hash should always be identical and Gradle even provides a GitHub action to validate that the hash matches a released version so that someone can’t sneak a malicious version of gradle-wrapper.jar into a PR.

This would be expected on first run. The wrapper task is initially designed to install the wrapper for your current Gradle version, which if you’re starting from scratch, would be the version installed on your system.

When you perform an upgrade from an existing project using ./gradlew, things occur a bit differently. You still run the wrapper task, but the task executes with your current version (Gradle 6.0.1). The arguments only change the values that are written to gradle-wrapper.properties. The gradle-wrapper.jar file is still the one copied from the 6.0.1 distribution. The next build run using gradlew will download the new version distribution and use the new version (Gradle 6.3).

Therefore, if you’re doing an upgrade using ./gradlew, and want the wrapper files to be completely up-to-date, you’ll want to run the wrapper task with the version/type arguments twice in a row. The first run will update gradle-wrapper.properties. The second run will update the remaining files. Generally speaking though, it’s perfectly fine to run new versions of Gradle with ancient wrapper files unless you specifically have a problem with something that was addressed in the wrapper updates.

Hmm, “exact” does not seem to be quite right either. For example, the file at ~/.gradle/wrapper/dists/gradle-6.3-all/b4awcolw9l59x95tu1obfh9i8/gradle-6.3/lib/gradle-wrapper-6.3.jar is quite a bit smaller than the file in my project at gradle/wrapper/gradle-wrapper.jar even after running ./gradlew wrapper --gradle-version=6.3 --distribution-type=all twice. So I assume the latter is some kind of Fat-JAR version of the former?

That’s a good point, I should investigate how exactly the action works.

That use-case actually seems quite bogus to me. Starting from scratch to me means I have to Gradle installed at all in the system. In fact, that’s how I’ve always been working with Gradle: I have no global Gradle in PATH which is installed in the system, but only projects with committed Gradle wrappers.

Indeed. But frankly, this behavior seems quite dumb to me. In my case, I wanted to upgrade a project from using Gradle 6.0.1 to use Gradle 6.3. But the 6.0.1 distribution was not present in ~/.gradle/wrapper/dists yet. So when running ./gradlew wrapper --gradle-version=6.3 --distribution-type=all, first Gradle 6.0.1 is downloaded, even though it’s clear that I never want to use that version, just to use that version to update gradle-wrapper.properties.

At least for the case when the distribution initially specified in gradle-wrapper.properties is not present on the system, I would have expected the wrapper to be smarter and download the wanted distribution right away and update both gradle-wrapper.properties and gradle-wrapper.jar accordingly.

I don’t see that behavior being clearly documented, unfortunately, but it clearly should be. I’ll probably file an according PR.

You’re not referencing the correct JAR there. The classes in lib/gradle-wrapper-6.3.jar are on the classpath, but not that JAR itself. The lib/plugins/gradle-plugins-6.3.jar contains the gradle-wrapper.jar which is used by the wrapper task as a classpath resource to copy to the project folder.

Wow, yet another completely not obvious thing. Thanks for clarifying.

See https://github.com/gradle/gradle/pull/12671.

For the purposes of official documentation, it might be better to not use some of the casual comments in this discussion.

For example, it’s not that it doesn’t actually write files other than gradle-wrapper.properties, but that it writes the versions from the current version, not the updated version. They look untouched, but technically the bytes were still written.

Effectively, you could be getting an update every time you update versions, just the JAR would be updated to your n-1 version while the gradle-wrapper.properties is updated to n.

Thanks for the feedback, but please add any comments you might have directly to the diff in the PR to keep related things in a single place.