Closed yschimke closed 2 years ago
First step - adopt version catalogs https://github.com/android/wear-os-samples/pull/214
Update a project https://github.com/android/wear-os-samples/pull/215
Done with ./gradlew versionCatalogUpdate
And then removing the plugins.
@shumelchyk I suggest we share around the updates of the other projects as it's mostly automated.
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.
@yschimke sounds good, I will update for the other projects
Have you considered trying refreshVersions for that dependencies updating problem?
I suggested adopting version catalogs and the ongoing update process.
A previous PR https://github.com/android/wear-os-samples/pull/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.
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.
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:
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 😅
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): https://github.com/android/wear-os-samples/blob/f375a8bf34a7e5251798a4b3800ca007deef239f/WatchFaceKotlin/gradle/libs.versions.toml#L70-L84
Get replaced by that:
version.kotlin=1.6.0
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
@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.
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?
@LouisCAD I think that is updated by Kseniia here https://github.com/android/wear-os-samples/pull/217/files#diff-4ecef8049661bdaba55564eb4fa0d1a371bf0863cd0397d1b48f2d10be61de6c
@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 https://github.com/android/wear-os-samples/pull/217
PR to merge version catalogs. https://github.com/android/wear-os-samples/pull/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 https://github.com/yschimke/wear-os-samples/pull/2
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.
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
}
}
}
The huge number of samples means that updates to dependencies is a Sisyphean task
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/