Renovate: update version numbers in Gradle properties

Created on 5 Nov 2018  Â·  19Comments  Â·  Source: renovatebot/renovate

What Renovate type are you using?
Renovate CLI, version 13.121.0
Gradle, version 4.10.2

Describe the bug
Version variable replacement only takes affect on variables in build.gradle.
Variables from gradle.properties are ignored.

Did you see anything helpful in debug logs?
Nothing unexpected in the logs.

To Reproduce
Configure renovate with

{
  "extends": [
    "config:base"
  ],
  "gradle": {
    "enabled": true
  },
  "renovateFork": true
}

Include a build.gradle and a gradle.properties.
Leverage a property as a dependency variable build.gradle file.

E.G. https://github.com/ChristianMurphy/uPortal/tree/example/issue

Expected behavior
Matcher should find and update variable in gradle.properties

Additional context

https://github.com/renovatebot/renovate/blob/dc05ea1de783dcbd85832081821d45c04007eddb/lib/manager/gradle/build-gradle.js#L64-L78

It appears that when a version is found in build.gradle, only the current file is scanned for replacement.

priority-3-normal feature

All 19 comments

Thanks @ChristianMurphy. I am marking this as a feature at least until @corecanarias has had a chance to triage it. I see you mention build.gradle, settings.gradle and gradle.properties. Is the last one the only one with a problem updating?

The issue is between build.gradle and gradle.properties.
Updated description to remove settings.gradle.

Yes, this use case is a bit tricky. How the current solution works, it look up for a dependency definition in a file and try to find a version in the same file to replace it with the newer version.

Not sure how I would approach this problem generalizing for any project. I would say that initially we could build something specifically for this specific use case only. Meaning if we find a gradle.properties file in a repo we always try to substitute version variables in this files as well. Does this makes sense?

Any other ideas on how to solve this case?

Does the tool we use find these updates, or is it fooled too?

From the gradle docs:

Setting up a consistent environment for your build is as simple as placing these settings into a gradle.properties file. The configuration is applied in following order (if an option is configured in multiple locations _the last one wins_):

  • gradle.properties in project root directory.
  • gradle.properties in GRADLE_USER_HOME directory.
  • system properties, e.g. when -Dgradle.user.home is set on the command line

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

Automatically changing a file in user home folder seems unsafe.
Commandline properties can't be changed, because they aren't saved.
But it could make sense to check the current file, then check the _gradle.properties_ in the root of the project.

I don’t know gradle but it seems to make sense to me that we also update any gradle.properties file that’s found next to the build.gradle. The problem is that we are “outsourcing” the lookups to a gradle tool so if it’s fooled by gradle.properties then we can’t do anything without a full rewrite.

The current tool does report updates to versions listed in gradle.properties.

There are two parts in this problem:

  • Identifying all the dependencies and the updates for a given project. For this, we use a gradle plugin and that takes into consideration any gradle.properties or any other configuration that gradle requires. Because the plugin uses the gradle API this always should work as expected. (For uPortal this is working as expected)
  • Given a specific dependency with a new version from the previous step, now we need to find the right file to update the version. This is something we are doing inside renovate without the help of gradle. Currently we assume that the version is specified in the same file where the definition of the dependency is. But if the versions are externalized into a different file, our implementation won't be able to update that file.
    Using gradle.properties might be a common pattern, but it could be literally anything, because gradle allows you to do whatever you want with the versions.

I think that supporting gradle.properties the way uPortal is using it would require some important refactoring, but it could be doable. But not sure how much value this will provide. Probably it would be simpler to move the versions inside the build.gradle? I know this is a particular decision of every developer for every project. But if the dependencies are managed by renovate, it's something to consider?

I think all the changes required to support this will be contained into this function: https://github.com/renovatebot/renovate/blob/master/lib/manager/gradle/index.js#L77

This is the one that receives a dependency with the new version and needs to update the file

This is an example of how the uPortal project could change the versions: https://github.com/corecanarias/uPortal/pull/3/files

I think it's the most common way to support global variables in gradle multi-projects

  • Still pending to test if with only this change renovate will change the versions.

Probably it would be simpler to move the versions inside the build.gradle?

It would be simplier from the parsing perspective.
But brings some risk, uPortal and CAS adopted the properties to keep dependencies in sync across sub projects during hand done edits.
Even with renovate, some hand edits will still probably be needed, given maven's rather loose versioning rules (#2759 will help a lot, there will still be a few edge cases that need to be handled manually).

This is an example of how the uPortal project could change the versions: https://github.com/corecanarias/uPortal/pull/3/files
I think it's the most common way to support global variables in gradle multi-projects

Interesting :thinking:
Does the renovate currently handle updating the top level _build.gradle_ env variables, if the dependency is only used in a sub-project _build.gradle_?

Yep, you're right. moving the versions to the build.gradle is essentially the same problem: The dependency and the version has to be defined in the same file.

This is something that can be encounter in many multi-project configs.

@rarkins Do you know about any other package manager that has the same issue? Having the dependency in one file and the version in other? If that's the case, I could try to copy the solution there.

@corecanarias none that I recall. So far they all follow the same type of approach with dependencyName=version.

What if we add some manual step like this?

  1. Look for the matching dependency name in build.gradle
  2. If the "value" in build.gradle is actually a variable name, then look for the variable name in a root gradle.properties
  3. If found in gradle.properties then update it to the new version

But please confirm: in this case the gradle.properties variables are used not only in the root build.gradle but also within nested build.gradle files too, right?

in this case the gradle.properties variables are used not only in the root build.gradle but also within nested build.gradle files too, right?

Correct,
That, or, they can also be declared at the top level, but are used only in nested build.gradle files.

I'm working on a change to support this, I expect I can make it work without many changes... Give me a bit more time to get something I can show and we can discuss if we want to continue that path or look for other solutions. I haven't spent much time on it, really...

@rarkins Ok, I've got something: https://github.com/renovatebot/renovate/pull/2779/files I did two passes to collect the variables first, and then look for them in all the files. So if someone is using a different file, we will look in them as well.

@ChristianMurphy This is what happened when I run it in uPortal: https://github.com/corecanarias/uPortal/pulls

:tada: This issue has been resolved in version 13.131.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

Is there something that I'm missing? I've added Renovate to my repo, but it is updating my build.gradle file with dependency changes rather than updating my gradle.properties. Yet, it knows what version it is upgrading from...

https://github.com/Wagan8r/essentials-kit/pull/37

Based on this thread, that is not the expected behavior. Has something changed in the last year?

@Wagan8r that looks like undesirable behaviour. Please raise a new issue so we can track its fix properly

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ZauberNerd picture ZauberNerd  Â·  4Comments

hutson picture hutson  Â·  3Comments

jycouet picture jycouet  Â·  4Comments

jgarec picture jgarec  Â·  3Comments

ikatyang picture ikatyang  Â·  4Comments