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

[Question] Increment build number using Conventional Commits messages

Open lopesdasilva opened this issue 5 years ago • 5 comments

Hi,

Thanks for the hard work on this plugin.

I'm currently trying to implement this plugin on our mono repo multi project. However one of our requirements is to increment the builds using commit messages, following the conventional commits (https://www.conventionalcommits.org/en/v1.0.0/) is this something that your plugin can support in any way?

Thanks

lopesdasilva avatar Mar 26 '20 16:03 lopesdasilva

The easiest "hack" I could think of would be to write a Gradle task that analyzes the HEAD commit of the checked out workspace. If it would find the information that it should create a release, this could trigger the createRelease or release Gradle task as a finalizer or dependOn dependency to your custom task. This would be a hack because this check would have to run during configuration time, for each Gradle invocation.

If done on task execution time, one would have to do some trickery, like trying to disable the finalized task when the result is negative. Something like (untested)

task maybeRelease {
     def releaseTask = tasks.findByName("release")
     finalizedBy releaseTask
     doLast {
         // check the SCM
         releaseTask.enabled = true / false
     }
}

realdadfish avatar Mar 26 '20 22:03 realdadfish

Hi @realdadfish, thanks for your answer. That gave me an idea.

after reading the documentation I created the following:

plugin configuration: scmVersion { tag { prefix = 'b2x' versionSeparator = '@' } monorepos { projectDirs = project.subprojects.collect({ p -> p.name }) } branchVersionIncrementer = [ "master": { c -> shouldIncrement(c) } ] }

`Object shouldIncrement(Object c) {

println("Current Version: $c.currentVersion")
def lastCommitMessage = getLastCommit().trim();

println("Last commit was -> $lastCommitMessage")

def conventionalCommitsPattern = "^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\\([a-z ]+\\))?: [\\w ]+"

if (lastCommitMessage =~ conventionalCommitsPattern) {
    println("The last commit was a valid commit message.\nInferring the new version.")

    def major = "BREAKING CHANGE"
    def minor = "^(feat)(\\([a-z ]+\\))?: [\\w ]+"
    def patch = "^(fix)(\\([a-z ]+\\))?: [\\w ]+"

    if (lastCommitMessage =~ major) {
        println("Inferred a new MAJOR version.")
        return c.currentVersion.incrementMajorVersion()
    } else if (lastCommitMessage =~ minor) {
        println("Inferred a new MINOR version.")
        return c.currentVersion.incrementMinorVersion()
    } else if (lastCommitMessage =~ patch) {
        println("Inferred a new PATCH version.")
        return c.currentVersion.incrementPatchVersion()
    }

}
println("No new version needed.")
return c.currentVersion

}

private String getLastCommit() { return runCommands("git", "log", "master", "--format=%B", "-n", "1") }

private String runCommands(String... commands) { def process = new ProcessBuilder(commands).redirectErrorStream(true).start() process.waitFor() def result = '' process.inputStream.eachLine { result += it + '\n' } def errorResult = process.exitValue() == 0 if (!errorResult) { throw new IllegalStateException(result) } return result }`

This is creating the correct version on the Gradle output. However I'm seeing 2 different issues now.

  1. I can't remove the -SNAPSHOT even when I'm on master branch. 👎
  2. I'm getting this strange error when I do ./gradlew release

pl.allegro.tech.build.axion.release.ReleaseFailedException (no error message)

lopesdasilva avatar Apr 01 '20 09:04 lopesdasilva

Don't know about the second issue, but the first issue can be solved by using the tools at hand:

val versionConfig = project.extensions.getByType(VersionConfig::class.java)
val context = GradleAwareContext.create(project, versionConfig)
val versionService = context.versionService()
val currentVersion = versionService.getVersion(context.rules()).toString()

currentVersion will then be the version without -SNAPSHOT applied to it.

realdadfish avatar Apr 01 '20 10:04 realdadfish

Where should this code go?

lopesdasilva avatar Apr 02 '20 13:04 lopesdasilva

I've wrote a custom Gradle plugin that internally applies the axion plugin and has custom tasks. You can put this into a doLast {} block of your current task (convert to Groovy, of course).

realdadfish avatar Apr 02 '20 15:04 realdadfish