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

Consider migration from Groovy Closure to Gradle Action API to be Kotlin DSL frendly

Open vladimirfx opened this issue 5 years ago • 11 comments

As now all plugin configuration callbacks is Goovy Closure. It would be nice refactor it to Action. Currently Kotlin DSL configuration is ugly because of use Kotlin to Groovy Closure adapters: ` scmVersion { ignoreUncommittedChanges = false useHighestVersion = true

tag(closureOf<TagNameSerializationConfig> {
    prefix = project.name
})

versionIncrementer("incrementMinor")

branchVersionIncrementer = mapOf<String?, KotlinClosure1<VersionIncrementerContext, Version>>(
        "release/.+" to KotlinClosure1({
            val branch = scmPosition.branch
            val matcher = "release/(\\d+)\\.(\\d+)".toRegex().matchEntire(branch)
            if (matcher == null) {
                throw IllegalArgumentException("Unsupported release branch naming: $branch")
            } else {
                val major = matcher.groupValues[1].toInt()
                val minor = matcher.groupValues[2].toInt()
                if (currentVersion.majorVersion != major || currentVersion.minorVersion != minor) {
                    Version.forIntegers(major, minor)
                } else {
                    currentVersion.incrementPatchVersion()
                }
            }
        }),
        "hotfix/.+" to KotlinClosure1({
            val branch = scmPosition.branch
            val matcher = "hotfix/(\\d+)\\.(\\d+)\\.(\\d+)".toRegex().matchEntire(branch)
            if (matcher == null) {
                throw IllegalArgumentException("Unsupported hotfix branch naming: $branch")
            } else {
                Version.forIntegers(matcher.groupValues[1].toInt(),
                        matcher.groupValues[2].toInt(),
                        matcher.groupValues[3].toInt())
            }
        })
)

branchVersionCreator = mapOf(
        "(?:feature/.+|bugfix/.+)" to KotlinClosure2<String, ScmPosition, String>({ versionFromTag, position ->
            "$versionFromTag-issue${position.branch.split("/")[1]}"
        })
)

} ` In most cases migration would be trivial and not break API. And thank you for great plugin!

vladimirfx avatar Mar 25 '19 04:03 vladimirfx

I know this plugin falls behind current standards in writing Gradle plugins. I have a separate branch in which I slowly move to Java from Groovy. Next step would be to write e2e tests with Kotlin DSL and then start swiitching to new Gradle APIs. However there is no estimated date for this, depends on the amount of free time :)

adamdubiel avatar Mar 25 '19 12:03 adamdubiel

Great plugin guys, we're using it for a project for one of the world's biggest retailers. Would be indeed great to have this feature as we are 100% Gradle Kotlin DSL.

kboom avatar Dec 20 '19 07:12 kboom

Perhaps it would be better to split this plugin into two, one that determines version, and one that does release. That way, each can be migrated to Kotlin without having to do a big-bang migration for the whole. Also, my guess is, lot of companies have their internal release process, and just use this plugin for versioning; I know we do.

asarkar avatar Oct 22 '20 01:10 asarkar

@kboom I'm also looking for Kotlin DSL usage. Would you be willing to post some code snippets without divulging proprietary code?

asarkar avatar Oct 22 '20 01:10 asarkar

@kboom I'm also looking for Kotlin DSL usage. Would you be willing to post some code snippets without divulging proprietary code?

In this issue description presented working example of Kotlin DSL usage. Feel free to ask your questions, if any.

vladimirfx avatar Oct 22 '20 08:10 vladimirfx

@vladimirfx I'm looking for the following:

  1. If on a release/.* branch, find the last tag matching release/.* and add the commit distance with the patch version. commit distance is the number of commits between the latest commit and the tag found.
  2. Otherwise, find the last tag with prefix not release/.* (empty prefix), and append -SNAPSHOT to it, regardless of any commits made after the tag or not.

I tried but couldn't find a way to implement the above using this plugin.

asarkar avatar Oct 22 '20 11:10 asarkar

@vladimirfx I'm looking for the following:

  1. If on a release/.* branch, find the last tag matching release/.* and add the commit distance with the patch version. commit distance is the number of commits between the latest commit and the tag found.
  2. Otherwise, find the last tag with prefix not release/.* (empty prefix), and append -SNAPSHOT to it, regardless of any commits made after the tag or not.

I tried but couldn't find a way to implement the above using this plugin.

Your questions not about Kotlin DSL. But I try to answer it.

  1. There is no API to count commits and it is reasonable because this distance may vary depending on path you go between commits.
  2. Version decoration usually based on current commit (and dirty state) AFTER base version number is calculated.

So seems your requirements is not covered by this plugin.

vladimirfx avatar Oct 22 '20 14:10 vladimirfx

this distance may vary depending on path you go between commits.

It's basically

git log 375a1..58b20 --pretty=oneline | wc -l

asarkar avatar Oct 22 '20 22:10 asarkar

I had to do

scmVersion {
  versionCreator("versionWithBranch")
  tag (closureOf<pl.allegro.tech.build.axion.release.domain.TagNameSerializationConfig> {
    prefix = "my-prefix"
  })
}

gabrieljones avatar Dec 11 '20 19:12 gabrieljones

This is definitely annoying when using Kotlin DSL.

Here are other tricks to work with the anonymous groovy closures.

scmVersion {
    nextVersion(closureOf<pl.allegro.tech.build.axion.release.domain.NextVersionConfig> {
        suffix = "eap"
        separator = "-"
    })

    snapshotCreator = KotlinClosure2<String, pl.allegro.tech.build.axion.release.domain.scm.ScmPosition, String>(
        { version, position ->
            position.shortRevision
        },
        this,
        this
    )

    checks(closureOf<pl.allegro.tech.build.axion.release.domain.ChecksConfig> {
        isUncommittedChanges = false 
    })
}

FYI closureOf creates a org.gradle.kotlin.dsl.KotlinClosure1, but for 2 and 3 arg variants you will have to use org.gradle.kotlin.dsl.KotlinClosure2 and [org.gradle.kotlin.dsl.KotlinClosure3] classes directly. If the closure shouldn't return anything (ie void), just use Unit as the last parameter type.

For those that are searching the types needed in the closureOf or for the anonymous closures, you can start the code of the scmVersion. Some are types are usually *Config in java sources and groovy sources, some are anonymous closure like for the snapshotCreator.

bric3 avatar Dec 03 '21 09:12 bric3

This is addressed in #449

cloudshiftchris avatar May 31 '22 21:05 cloudshiftchris