axion-release-plugin icon indicating copy to clipboard operation
axion-release-plugin copied to clipboard

Please adopt to allow better Gradle Kotlin DSL usage

Open Zordid opened this issue 2 years ago • 8 comments

Please make your plugin more Kotlin DSL friendly. Using Groovy Closures is not the preferred way to make anything happen in Gradle - use Action<T> instead of closures to allow better usage of other languages. See here: https://docs.gradle.org/current/userguide/kotlin_dsl.html#groovy_closures_from_kotlin

I am having troubles setting the version creator closure with using Kotlin DSL.

Zordid avatar Apr 01 '22 05:04 Zordid

hi @Zordid

could you share some examples? What does bother you now and maybe a suggestion how would you like it to be? :)

bgalek avatar Apr 07 '22 20:04 bgalek

Hey @bgalek ! Thanks for replying. From my perspective (having moved to Gradle from Maven and directly using the Gradle Kotlin DSL), it is often somewhat frustrating to adopt existing plugins' examples from Groovy DSL to Kotlin DSL. So, I am not proficient enough to explain anything from the Groovy perspective. That being said: if I need to adopt a given example, like your cool plugin's setup, but it is given only in Groovy, I totally depend on understanding what the context is and what to do to make it work in Kotlin DSL. The link I sent in my first comment shows how the Gradle people basically state:

Gradle plugins written in any language should prefer the type Action<T> type in place of closures. Groovy closures and Kotlin lambdas are automatically mapped to arguments of that type.

Setting the versionCreator for example needs a conversion from a Groovy Closure to a Kotlin lambda like this:

versionCreator = KotlinClosure2({ versionFromTag: String, position: pl.allegro.tech.build.axion.release.domain.scm.ScmPosition ->
    .... code here ....
}

Or even worse to allow easier usage of the pre-fileUpdate I have written this helper function:

/**
 * Helper function for Kotlin -> Groovy used by Release Plugin's Pre-Fileupdate Action
 */
fun HooksConfig.preFileUpdate(
    file: String,
    pattern: (String, pl.allegro.tech.build.axion.release.domain.hooks.HookContext) -> String,
    replacement: (String, pl.allegro.tech.build.axion.release.domain.hooks.HookContext) -> String,
) {
    pre(
        "fileUpdate", mapOf(
            "file" to file,
            "pattern" to KotlinClosure2(pattern),
            "replacement" to KotlinClosure2(replacement)
        )
    )
}

So, it would be really cool if you could revise your config to not rely on Groovy closures, but more on Action<T>? And, if possible, write some documentation on how to use the plugin with Kotlin Gradle DSL?

Thanks!

Zordid avatar Apr 12 '22 14:04 Zordid

I am having this error also using the Kotlin DSL

  Line 17:     tag {
                   ^ Type mismatch: inferred type is () -> Unit but Closure<(raw) Any!>! was expected

  Line 18:         prefix = "config-server"
                   ^ Unresolved reference: prefix

Jordantan1999 avatar Apr 15 '22 09:04 Jordantan1999

happy to contribute code to this, if someone can flip me the contributor deets.

cloudshiftchris avatar May 20 '22 23:05 cloudshiftchris

Examples of what is working so far (what isn't visible is all the configuration closures -> Actions, these ones are transformation functions).

def "should not fail build when Kotlin DSL used to configure Axion"() {
        given:
        new FileTreeBuilder(temporaryFolder).file("build.gradle.kts",
            """
        import pl.allegro.tech.build.axion.release.domain.*
        import pl.allegro.tech.build.axion.release.domain.properties.*

        plugins {
            id("pl.allegro.tech.build.axion-release")
        }

        scmVersion {
            localOnly = true
            useHighestVersion = true
            tag {
                prefix = "release"
                versionSeparator = "/"

                // configure via function calls
                setDeserializer({ a,b,c -> "d" })
                setSerializer( { a,b -> "c" })

                // assignment via Kotlin property extension
//                tagNameSerializer = { a,b -> "c" }
//                tagNameDeserializer = { a,b,c -> "d" }

                // assignment to existing variables
                serialize = TagProperties.Serializer({a,b -> "c"})
                deserialize = TagProperties.Deserializer({a,b,c -> "d"})
            }
            repository {
                type = "git"
            }
            checks {
                setAheadOfRemote(false)
                setSnapshotDependencies(true)
            }
            nextVersion {
                // function calls
                setDeserializer( { a,b,c -> "d" })
                setSerializer( {a,b -> "c"})

                // assignment via Kotlin property extension
//                versionSerializer = {a,b -> "c"}
//                versionDeserializer = {a,b,c -> "d" }
            }
            hooks {
                pre({println("here")})
                pre("commit") {
                  println("here")
                }

                post({println("here")})
                post("commit") {
                  println("here")
                }

                preRelease {
                    push()
                    commit { releaseVersion, position -> "New commit message for version \$releaseVersion" }
                    custom { context -> println("\$context")}
                    fileUpdate {
                        file("README.md") // repeat for additional files
                        pattern = {previousVersion,context -> "version: \$previousVersion"}
                        replacement = {currentVersion,context -> "version: \$currentVersion"}
                    }
                }

                postRelease {
                    push()
                    commit { releaseVersion, position -> "New commit message for version \$releaseVersion" }
                    custom { context -> println("\$context")}
                    fileUpdate {
                        file("README.md") // repeat for additional files
                        pattern = {previousVersion,context -> "version: \$previousVersion"}
                        replacement = {currentVersion,context -> "version: \$currentVersion"}

                    }
                }
            }
            monorepos {
            }

            versionCreator = VersionProperties.Creator({a,b -> "c"})
            versionCreator({a,b -> "c"})

            snapshotCreator = VersionProperties.Creator({a,b -> "c"})
            snapshotCreator({a,b -> "c"})

            versionIncrementer = VersionProperties.Incrementer({a -> null})
            versionIncrementer({a -> null})
        }

        project.version = scmVersion.version
        """)

        when:
        def result = GradleRunner.create()
            .withProjectDir(temporaryFolder)
            .withPluginClasspath()
            .withArguments('currentVersion', '--stacktrace')
            .build()

        then:
        result.task(":currentVersion").outcome == TaskOutcome.SUCCESS
    }

cloudshiftchris avatar May 21 '22 17:05 cloudshiftchris

@cloudshiftchris fork repository and submit a PR, I'll be happy to review ;) Cool initiative! :)

bgalek avatar May 23 '22 06:05 bgalek

I was waiting for this one!

bric3 avatar May 31 '22 22:05 bric3

👋🏻 Good day, mates. I make the following utilities based on Solidity & Rust with powerful frontend demonstration. 💻Dapps(Swap, Staking, Referral, Farm, Pool, Presale, Reflection, DAO ...) 💻NFT marketplaces (Opensea, Rarible, Metaplex) 💻Backend software Do you have some issues?

UrsaarDev avatar Jul 27 '22 11:07 UrsaarDev

1.14.0 release has better kotlin support now ;)

bgalek avatar Aug 03 '22 12:08 bgalek