Precedence of gradle.properties?

According to:
https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties

…If an option is configured in multiple locations, the first one found in any of these locations wins:

  • command line, as set using the -P / --project-prop environment options.
  • gradle.properties in GRADLE_USER_HOME directory.
  • gradle.properties in project root directory.
  • gradle.properties in Gradle installation directory.

So if I have:

~/.gradle/gradle.properties
myProp="orange"

~/myProject/.gradle.properties
myProp="banana"

I will still get orange when I run my build (unless I override it in my build.gradle file). To me that makes no sense.

Compare with:
http://git-scm.com/docs/git-config#FILES

The files are read in the order given above, with last value found taking precedence over values read earlier. When multiple values are taken then all values of a key from all files will be used.

I assume gradle team have a good reason why not to follow the same convention as e.g. git above?

And is it possible to change it to something similar as git?

The difference to Git is, that the repo-specific .git/config and the user-specific ~/.gitconfig are both not versioned by maintained locally by and for that single user, so it makes sense to declare defaults user-specific and make user-specific overrides.

In Gradle, the project-specific <project>/gradle.properties is usually checked into version control and defines the defaults for the project, with the option to override them for each user in their ~/.gradle/gradle.properties.

What you really would want is a <project>/gradle-local.properties that you can have in the project directory but ignored for VCS and that has higher precedence than <project>/gradle.properties, but lower precedence than ~/.gradle/gradle.properties.

I don’t think that you can change the default precedence order and even if you could, you would confuse everyone that is used to the normal Gradle precedence rules.

Actually you can read all files you want in the order you want and then set the properties to the values according to your precedence rules, but I really wouldn’t recommend that.
If you really want to do that, you can have a look at how GitHub - stevesaliman/gradle-properties-plugin: Gradle plugin to simplify loading project properties from external environment specific files does it.
But there is at least no real configuration-cache safe way to do it (yet).

The use case is a CI/build server setup where the agents have ~/.gradle/gradle.properties with common properties for all projects. So it needs to go to VCS.

But for some projects I need to be able to override those properties as part of build migrations without affecting all the other projects. A pretty standard use case I suppose and also going from system wide → project seems like a natural way of ordering this.

I guess I can simply have a pre-step that deletes ~/.gradle/gradle.properties so it uses the one in the project. Just seems strange that its designed to work like this.

Again, it is not strange.
The one checked in defines the defaults.
The one in the Gradle user home overwrites the defaults for the current user.
What is missing is another file in the project that is not checked in and has higher precedence.
Unfortunately Gradle guys are not really willing to do it, but you might also raise your voice in the according issue: Add official local.properties support · Issue #12283 · gradle/gradle · GitHub

1 Like

Use -P$key=$val from the command line. It is the answer, especially declarative in CI pipelines YAML ))