Open Wrywulf opened 3 years ago
This is tricky.
The cannot be serialized
error is probably due to the Extensions (WrapperExtension
) being dynamic object in gradle which can't be serialized.
If you try to get the value of wrapperExtension.myfilter.get()
before overrideVersionName
, you'll get Cannot query the value of extension 'wrapper' property 'myFilter' because it has no value available.
as the values won't be available before the project is evaluated.
The only workaround I can think of right now is:
class WrapperPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withType<AppPlugin> {
val wrapperExtension = project.extensions.create("wrapper", WrapperExtension::class.java)
project.plugins.apply(AppVersioningPlugin::class.java)
val extension = project.extensions.getByType(AppVersioningExtension::class.java)
val myFilter = AtomicReference<String>(null)
project.afterEvaluate {
myFilter.set(wrapperExtension.myFilter.get())
}
extension.overrideVersionName { gitTag, providerFactory, variantInfo ->
myFilter.get()
}
}
}
}
I could change the plugin to add tagFilter
to the overrideVersionCode|Name
lambda parameters (maybe wrap them in a Metadata
object), but it feels weird to just add tagFilter
and not the others.
The other option is to add a val metadata = objects.property<Any>().convention(null)
extension which is passed into the overrrideVersionCode|Name
lambda by the plugin. But I'm not sure if being able to customize the versionCode/name from the extension of another plugin is a common use case.
Thanks for the input.
It seems even the
project.afterEvaluate {
myFilter.set(wrapperExtension.myFilter.get())
}
cannot be done (it triggers Cannot query the value of extension 'wrapper' property 'myFilter' because it has no value available
)
I've sort of paused the idea for now.
I understand that this is probably a niche use case so it makes sense to not pollute the API with these specific requirements.
However, I think it the metadata
idea could make sense at some point. Perhaps as an optionally implemented "overloaded" lambda with this extra parameter. It would definitely lift the current constraints and make it flexible for use cases similar to mine (hydrating the lambda with external data).
cannot be done (it triggers Cannot query the value of extension 'wrapper' property 'myFilter' because it has no value available) I've sort of paused the idea for now.
Hmm, I was able to do get this to work locally. How are you defining your WrapperExtension
?
This is how I defined it:
open class WrapperExtension internal constructor(objects: ObjectFactory) {
val myFilter = objects.property<String>().convention(null)
}
This is how my extension is defined:
open class WrapperExtension @Inject constructor(objectFactory: ObjectFactory) {
val myFilter: Property<String> = objectFactory.property(String::class)
}
perhaps the convention
is the reason?
That doesn't seem to make a difference. Unless you're not actually setting myFilter
in your custom plugin configuration?
Here are all the changes I have locally:
In buildSrc/build.gradle.kts
:
dependencies {
...
implementation("io.github.reactivecircus.appversioning:app-versioning-gradle-plugin:0.8.1")
}
gradlePlugin {
plugins {
register("wrapper") {
id = "wrapper-plugin"
implementationClass = "io.github.reactivecircus.streamlined.WrapperPlugin"
}
}
}
In my buildSrc/WrapperPlugin.kt
:
package io.github.reactivecircus.streamlined
import com.android.build.gradle.internal.plugins.AppPlugin
import io.github.reactivecircus.appversioning.AppVersioningExtension
import io.github.reactivecircus.appversioning.AppVersioningPlugin
import java.util.concurrent.atomic.AtomicReference
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.model.ObjectFactory
import org.gradle.kotlin.dsl.property
import org.gradle.kotlin.dsl.withType
class WrapperPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.withType<AppPlugin> {
val wrapperExtension = project.extensions.create("wrapper", WrapperExtension::class.java)
project.plugins.apply(AppVersioningPlugin::class.java)
val extension = project.extensions.getByType(AppVersioningExtension::class.java)
val myFilter = AtomicReference<String>(null)
project.afterEvaluate {
myFilter.set(wrapperExtension.myFilter.get())
}
extension.overrideVersionName { gitTag, providerFactory, variantInfo ->
myFilter.get()
}
}
}
}
open class WrapperExtension internal constructor(objects: ObjectFactory) {
val myFilter = objects.property<String>().convention(null)
}
Finally in the app/build.gradle.kts
:
plugins {
`wrapper-plugin`
id("com.android.application")
kotlin("android")
...
}
wrapper {
myFilter.set("0-9]*.[0-9]*.[0-9]*")
}
...
Running ./gradlew generateAppVersionInfoForDebug
produces:
> Task :app:generateAppVersionInfoForDebug
Generated app version code: 300.
Generated app version name: "0-9]*.[0-9]*.[0-9]*".
Thanks a lot for looking into this. I'll try to replicate what you did and figure out why it fails on my side.
I guess this is more of a question.. How would it be possible to customize the versionName/versionCode using data not provided as input to the lambda (GitTag, ProviderFactory, VariantInfo)?
Context: I'm building an opinionated wrapper plugin around
app-versioning
and would like to declare my own plugin extension that app projects populate. Those extension properties would be used in theoverrideVersionName
lambda to calculate the version name.If I try to use my custom extension property in the
overrideVersionName
lambda like this:I get the error:
Property 'kotlinVersionNameCustomizer' with value '(io.github.reactivecircus.appversioning.GitTag, org.gradle.api.provider.ProviderFactory, io.github.reactivecircus.appversioning.VariantInfo) -> kotlin.String' cannot be serialized
Am I missing something obvious here?
Basically, I guess I would like "myFilter" to be a part of the input to the
GenerateAppVersionInfo
task.