Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adopt version catalogs and renovate #213

Closed
yschimke opened this issue Feb 17, 2022 · 19 comments
Closed

Adopt version catalogs and renovate #213

yschimke opened this issue Feb 17, 2022 · 19 comments

Comments

@yschimke
Copy link
Contributor

The huge number of samples means that updates to dependencies is a Sisyphean task

image

I would suggest adopting gradle version catalogs and automating dependency updates. I would be happy to contribute assuming there was prior agreement.

See https://www.whitesourcesoftware.com/free-developer-tools/renovate/

@yschimke
Copy link
Contributor Author

First step - adopt version catalogs #214

@yschimke
Copy link
Contributor Author

Update a project #215

Done with ./gradlew versionCatalogUpdate

And then removing the plugins.

@yschimke
Copy link
Contributor Author

@shumelchyk I suggest we share around the updates of the other projects as it's mostly automated.

@yschimke
Copy link
Contributor Author

After that we can try to merge the catalogs into a single file at the root, so updates are synchronized. And also setup renovate. Probably not worth doing that until projects are updated.

@shumelchyk
Copy link
Collaborator

@yschimke sounds good, I will update for the other projects

@LouisCAD
Copy link
Contributor

Have you considered trying refreshVersions for that dependencies updating problem?

@yschimke
Copy link
Contributor Author

I suggested adopting version catalogs and the ongoing update process.

A previous PR #214 did this, and used the little robots plugin to automate the updates one time. This plugin seems similar to the refreshVersions plugin except uses the literal versions in gradle version catalog instead of '_', assuming I understood the setup your are suggesting.

Ultimately getting renovate or similar to create PRs automatically, seems like the lowest effort way to keep up with releases, without any manual step.

I guess two questions

a) Are there specific advantages to refreshVersion over littlerobots VCU or renovate to update in future.
b) Can refreshVersion work with vanilla version catalogs?

I don't have a strong opinion on the final approach, so don't mind dev rel team decided to change the plan. But I was trying to deploy what looks like the emerging standard in gradle projects, and ensure it stays fresh in future.

@yschimke
Copy link
Contributor Author

Actually probably the first question - is whether gradle version catalogs are considered a good choice. And the choosing which method to update dependencies on top of it.

@LouisCAD
Copy link
Contributor

Version catalogs are better than putting dependencies and their versions in buildSrc because it avoids invalidating all build caches when you update a dependency.

However, version catalogs (alone) don't help updating… versions, they probably should have been called dependency catalogs instead. Using a bot like renovate or littlerobots VCU only partly tackles the issue, because it always pick the latest, unless some configuration is applied, but then you still lack the flexibility because you don't see all the available versions in context. Also, it can create some noise in the PRs, burying PRs from humans a bit.

Another remaining issue with version catalogs is duplicated "code" between projects. You have to copy or rewrite the catalog for you project, even for very popular libraries like the ones in AndroidX, and you can't share one without locking the used versions for the host projects.

refreshVersions tackles all those issues in the following way:

  1. It has built-in dependency notations for the Kotlin and the Android ecosystems, without locking the versions, and without touching buildSrc on dependencies update either.
  2. It finds all the available updates within a few seconds, not just the latest, all the newer versions, and puts them as comments, aligned in a way that allows updating with just a few keystrokes.
  3. It doesn't choose the version to upgrade to, instead, it purposefully helps you pick what you know is the right one (so you can decided whether you pick an alpha version or not for example)

Now, about whether Gradle's version catalogs are considered a good choice or not, I'd say they are helpful for multi-module projects, and when using refreshVersions, they are useful for the dependency notations that are not built-in, since using the version placeholder (_) there also works.
BTW, now that version catalogs matured, refreshVersions is in the process of adding a way to instantly migrate to version catalogs AND refreshVersions at the same time for existing projects that use only one of these, or none of these.

Can refreshVersion work with vanilla version catalogs?

Right now, it can't, but it's definitely doable since TOML supports comments, which is where refreshVersions puts the available versions. I believe it's best to have all the versions in the versions.properties file, and take advantage of the hand crafted built-in dependency notations (AndroidX.xxx, KotlinX.xxx, Firebase.xxx, etc), but since it's currently the second most upvoted feature request, it has a chance of getting prioritized soon.

I hope it wasn't too long 😅

@LouisCAD
Copy link
Contributor

There's a last thing I forgot to mention:
refreshVersions is optimized for readability.
It avoids showing redundant qualifiers and version keys, because it would get in the way of eye-scanning.

It means things like this (found in a version catalog in this repo):

org-jetbrains-kotlin-android = "org.jetbrains.kotlin.android:1.6.0"
org-jetbrains-kotlin-android-extensions = "org.jetbrains.kotlin.android.extensions:1.6.0"
org-jetbrains-kotlin-js = "org.jetbrains.kotlin.js:1.6.0"
org-jetbrains-kotlin-jvm = "org.jetbrains.kotlin.jvm:1.6.0"
org-jetbrains-kotlin-kapt = "org.jetbrains.kotlin.kapt:1.6.0"
org-jetbrains-kotlin-multiplatform = "org.jetbrains.kotlin.multiplatform:1.6.0"
org-jetbrains-kotlin-multiplatform-pm20 = "org.jetbrains.kotlin.multiplatform.pm20:1.6.0"
org-jetbrains-kotlin-native-cocoapods = "org.jetbrains.kotlin.native.cocoapods:1.6.0"
org-jetbrains-kotlin-native-performance = "org.jetbrains.kotlin.native.performance:1.6.0"
org-jetbrains-kotlin-platform-android = "org.jetbrains.kotlin.platform.android:1.6.0"
org-jetbrains-kotlin-platform-common = "org.jetbrains.kotlin.platform.common:1.6.0"
org-jetbrains-kotlin-platform-js = "org.jetbrains.kotlin.platform.js:1.6.0"
org-jetbrains-kotlin-platform-jvm = "org.jetbrains.kotlin.platform.jvm:1.6.0"
org-jetbrains-kotlin-plugin-parcelize = "org.jetbrains.kotlin.plugin.parcelize:1.6.0"
org-jetbrains-kotlin-plugin-scripting = "org.jetbrains.kotlin.plugin.scripting:1.6.0"

Get replaced by that:

version.kotlin=1.6.0

@yschimke
Copy link
Contributor Author

I really like that refreshVersions plugin, particularly the built in dependency catalog.

    implementation libs.jackson.databind
    implementation libs.jackson.crypto
    implementation KotlinX.coroutines.core
    testImplementation Kotlin.test.common

I am a bit concerned about the samples using 3rd party plugins, version catalogs are a standard part of Gradle now, so I must believe that Android Studio will start to support them nicely with inbuilt upgrade prompts and the like.

That said, I'll leave it to the Wear DevRel team to decide, I have no strong view on which way to go and at this point the dependencies are cleaned up and it's a choice of which mechanism to update them over time.

Nice to see that Wear compose, tiles, and so on are already supported https://github.com/jmfayard/refreshVersions/blob/16f3b1c5f03a9f3de2c4186bc32e0c6c68bd7039/plugins/dependencies/src/main/kotlin/dependencies/AndroidX.kt#L2727

@shumelchyk
Copy link
Collaborator

@LouisCAD Thank you for such a precise explanation!
To echo what @yschimke mentioned above in near term we want to adapt a fully automated and avoid any manual steps due to limited team bandwidth.
Nevertheless, we have an internal council who regularly evaluates/approves the best available options, so we may reconsider the approach in future.

@LouisCAD
Copy link
Contributor

Reducing the amount of needed developer time is what refreshVersions is all about, and even though it might seem more manual than a bot sending PRs, I found that I would actually spend less time upgrading dependencies. I would tend to think you'd have a similar experience in the sample projects in this repo.

I forgot to mention earlier that there's also a way to make a bot that runs refreshVersions, commits the changes and sends a PR, here's an example.

BTW, I'm seeing that the WatchFaceKotlin sample is still using Kotlin 1.6.0, even though Kotlin 1.6.10 has been released a while ago. Is there a special rule that prevents the upgrade with the mechanism that you currently have?

@yschimke
Copy link
Contributor Author

@LouisCAD I think that is updated by Kseniia here https://github.com/android/wear-os-samples/pull/217/files#diff-4ecef8049661bdaba55564eb4fa0d1a371bf0863cd0397d1b48f2d10be61de6c

@shumelchyk
Copy link
Collaborator

@LouisCAD RefreshVersions seems to be a very nice tool, but anyway it may require additional reviews/approvals before integrating it (that's usually evaluated for all Android samples, not per project).

I forgot to mention earlier that there's also a way to make a bot that runs refreshVersions, commits the changes and sends a PR, here's an example.

With this automation example it seems that bot creates a PR with inline comments about available dependencies updates as opposed to actual dependencies update. I can understand your point about manual process paying off at the end, that's why we may reconsider the fully automated approach in longer-term.

Is there a special rule that prevents the upgrade with the mechanism that you currently have?

No rules afaik, it should land within #217

@yschimke
Copy link
Contributor Author

PR to merge version catalogs. #220

It can land but I hopefully see some PR of gradle deps. https://app.renovatebot.com/dashboard#github/yschimke/wear-os-samples/584928192 The logs suggest it is working, but we upgraded everything.

So far it just flagged a github action yschimke#2

@yschimke
Copy link
Contributor Author

Bingo yschimke#3

@yschimke
Copy link
Contributor Author

Since that landed, I'll try to get the bot installed. And fall back to running it as a local action otherwise.

But it appears to work nicely.

@yschimke
Copy link
Contributor Author

yschimke commented Apr 8, 2022

For now I'm using ~/.gradle/init.d/add-versions.gradle

initscript {
  repositories {
     gradlePluginPortal()
  }

  dependencies {
    classpath 'com.github.ben-manes:gradle-versions-plugin:+'
    classpath 'nl.littlerobots.vcu:plugin:+'
  }
}

rootProject {
  apply plugin: com.github.benmanes.gradle.versions.VersionsPlugin
  apply plugin: nl.littlerobots.vcu.plugin.VersionCatalogUpdatePlugin

  tasks.named("dependencyUpdates").configure {
      rejectVersionIf {
              (it.candidate.version == "1.6.20") ||
          (it.candidate.version ==~ /.*-alpha.*/ && !(it.currentVersion ==~ /.*-alpha.*/)) ||
                  (it.candidate.version ==~ /.*-beta.*/ && !(it.currentVersion ==~ /.*-(beta|alpha).*/)) ||
                  (it.candidate.version ==~ /.*1.6.20-M.*/) || (it.candidate.version ==~ /.*1.6.20-RC.*/)
      }
  }

  versionCatalogUpdate {
      keep {
        keepUnusedVersions = true
      }
  }
}

@yschimke yschimke closed this as completed Jun 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants