General question about Gradle wrapper vs no wrapper

I am used to drive projects with fixed versions of some tools for entire team and so far I was ( still I am) reluctant to work with wrappers like gradlew, mvnw …

For a team like 3-4 devs, for a several months period, it is easy to set up the given Gradle version (including local machines, VMs, images, build automation pipelines or any envs) and just use it from bash or pipeline scripts without the wrapper.

But some devs are crazy about wrappers.
I am not against wrapping - it is ok, let’s have this clean and fancy wrapper stub with gradle-wrapper.properties defined to the fixed version, but let’s do not use it in devOps duties.

I would prefer to run $gradle not $gradlew and just feel the coffee taste and the sand cracking in the gears.
I do not like when guys using gradlew complain on connectivity issues, caching, stopping, cleaning cache issues, “improving” the wrapper script to adapt it to caller script, parallel run etc etc.

It is hard to get to work with fixing the issues when you hear the answer “I don’t know the version, I am using wrapper …”

Would you share your experience and the devOps model regarding wrappers you use?

It is highly recommended to always use the wrapper in any project even the tiniest.
This way a build know the Gradle version it is compatible with and known working with properly and there can never arise problems due to differences in Gradle versions.

Even Maven-world has seen what good the Gradle wrapper does and replicated the approach with the Maven wrapper.

Of course, if you make sure some other way that the Gradle version is the expected one by only having internal projects where you control all runtime environments and all builds use the same version, that would be “fine” too.

But what if you end up 100 different builds (or just 10, doesn’t really matter) and you decide you want to use a newer Gradle version. You update the Gradle version in all runtime environments in a concerted action where at the same point in time you update the Gradle version in all runtime environment consistently. Already this is near impossible. But given you managed to do that, then instantly maybe a big amount of your projects do not build anymore as they were compatible with the old version, but are not compatible with the new version anymore. You then have big trouble and need to go through allll the projects immediately to fix up the builds and test whether everything is working as expected.

I mean, do whatever works best for you, but for me this scenario sounds very bad, and in my opinion any build that does not have the four wrapper files has a build bug.

I am used to drive projects with fixed versions of some tools for entire team

That might not be a too bad approach, but maybe you should do it in other ways. For example with some post-push Git hook that verifies if a project is pushed that the wrapper is configured with your current “fixed version”, so that if a project touched the next time anyway, it can and must be updated to that version. Or what I do at work is having a set of custom Gradle plugins and the very basic one that every project should have checks the Gradle version at runtime and enforces to be within a given major.minor version. This way one can at least use the latest patch version, but otherwise those plugins do not need to be compatible with multiple versions but can be tested with exactly the expected version. Then whenever a project is using a newer version of theses plugins, they also have to adapt to said new Gradle version enforced by that plugin version, which also allows a continuous migration to a newer version.

it is easy to set up the given Gradle version

With the Gradle wrapper it is even easier, because you do not need to set up any Gradle version anywhere, as the wrapper auto-provisions and manages the expected Gradle version. :slight_smile:

I am not against wrapping - it is ok, let’s have this clean and fancy wrapper stub with gradle-wrapper.properties defined to the fixed version, but let’s do not use it in devOps duties.

You are free to use an installed Gradle version as long as it is the version that is compatible with the build, usually meaning it is the version defined in the wrapper.
There is no real difference between using the wrapper or using an installed version that is the same version. It is just majorly easier to simply use the wrapper.

I would prefer to run $gradle not $gradlew and just feel the coffee taste and the sand cracking in the gears.

alias gradle=gradlew

:joy:

I do not like when guys using gradlew complain on connectivity issues, caching, stopping, cleaning cache issues,

I don’t know why they should. Whether you use the wrapper or an installed version is exactly the same as soon as the build starts, so stopping, cleaning, caching, network IO, all is exactly the same.

Of course with the one exception if something is going wrong while auto-provisioning the Gradle distribution defined in the wrapper if it is not already present on the machine running the build.
But those problems should usually be rather minimal and rare and imho the pros always outweigh this minimal additional “risk”.

“improving” the wrapper script to adapt it to caller script, parallel run etc etc.

This does not really sound like something that should be done.
But let’s put it that way, if something like that is necessary, you would also need such modifications in the installed Gradle version.
The only difference between using an installed version and the wrapper is, that the wrapper will download and unpack a Gradle version if necessary which is exactly what you would do manually when installing a Gradle version. After that, it is exactly the same.

It is hard to get to work with fixing the issues when you hear the answer “I don’t know the version, I am using wrapper …”

If you hear that, someone is probably just teasing you as he knows you don’t like the Wrapper.
Someone could as well say “I don’t know the version, I am just using gradle ...” not knowing or remembering what version was installed or which one of multiple is currently in the PATH or whether it is an alias and so on.

When using the wrapper you can simply look in the properties file which version is used.
Or you can always call Gradle with --version to quickly know the version that is used.
Or you can create a build --scan to read it from there.
Or you can everywhere put an init script that prints the Gradle version after every Gradle execution.
Or …

Would you share your experience and the devOps model regarding wrappers you use?

Always use the Gradle wrapper :slight_smile:

1 Like