Skip to content

Commit

Permalink
Close #31
Browse files Browse the repository at this point in the history
  • Loading branch information
martinbonnin committed Jul 15, 2024
1 parent bab9717 commit 06c9461
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,29 @@ package com.gradleup.librarian.cli.command

import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.arguments.optional
import com.github.kinquirer.KInquirer
import com.github.kinquirer.components.promptConfirm
import com.gradleup.librarian.core.tooling.BumpMajor
import com.gradleup.librarian.core.tooling.DowngradeVersion
import com.gradleup.librarian.core.tooling.UseDefaultVersion
import com.gradleup.librarian.core.tooling.tagAndBump
import kotlin.system.exitProcess

internal class TagAndBump: CliktCommand() {
val versionToRelease by argument()
val versionToRelease by argument().optional()

override fun run() {
tagAndBump(versionToRelease)
tagAndBump(versionToRelease) {
val ret = when(it) {
is BumpMajor -> KInquirer.promptConfirm("Bump major version to '${it.tagVersion}' and bump? (current version is ${it.currentVersion})", true)
is DowngradeVersion -> KInquirer.promptConfirm("Downgrade version to '${it.tagVersion}' and bump? (current version is ${it.currentVersion})", true)
is UseDefaultVersion -> KInquirer.promptConfirm("Tag version '${it.expectedVersion}' and bump?", true)
}

if (!ret) {
exitProcess(1)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,94 @@ internal fun getNextSnapshot(version: String): String {
return getNextPatch(version) + "-SNAPSHOT"
}

/**
* Mostly used as a sanity check
*/
internal fun String.isValidVersion(): Boolean {
return Regex("[0-9]+\\.[0-9]+\\.[0-9]+.*").matches(this)
}
internal class PreRelease(
val name: String,
val version: Int,
) {

}

internal fun PreRelease?.compareTo(other: PreRelease?): Int {
return if (this == null && other == null) {
0
} else if (this == null) {
1
} else if (other == null) {
-1
} else {
// XXX: should we handle non-lexicographic order here?
val ret = name.compareTo(other.name)
if (ret != 0) {
return ret
}

return version.compareTo(other.version)
}
}

internal class Version(
val major: Int,
val minor: Int,
val patch: Int,
val preRelease: PreRelease?,
val isSnapshot: Boolean,
) {
operator fun compareTo(currentVersionParsed: Version): Int {
var ret = major.compareTo(currentVersionParsed.major)
if (ret != 0) return ret

ret = minor.compareTo(currentVersionParsed.minor)
if (ret != 0) return ret

ret = patch.compareTo(currentVersionParsed.patch)
if (ret != 0) return ret

ret = preRelease.compareTo(currentVersionParsed.preRelease)
if (ret != 0) return ret

ret = major.compareTo(currentVersionParsed.major)
if (ret != 0) return ret

return 0
}
}

internal fun String.toVersionOrNull(): Version? {
val regex1 = Regex("([0-9]+)\\.([0-9]+)\\.([0-9]+)(.*)")

val result1 = regex1.matchEntire(this) ?: return null

val major = result1.groupValues[1].toIntOrNull() ?: return null
val minor = result1.groupValues[2].toIntOrNull() ?: return null
val patch = result1.groupValues[3].toIntOrNull() ?: return null

var rem = result1.groupValues[4]
if (rem.isEmpty()) {
return Version(major, minor, patch, null, false)
}

var preRelease: PreRelease? = null

val snapshot = rem.endsWith("-SNAPSHOT")
if (snapshot) {
rem = rem.removeSuffix("-SNAPSHOT")
}
if (!rem.isEmpty()) {
if (!rem.startsWith("-")) {
return null
}
rem = rem.substring(1)
val regex2 = Regex("([a-zA-Z]+)\\.([0-9]+)")
val result2 = regex2.matchEntire(rem) ?: return null

val v = result2.groupValues[2].toIntOrNull() ?: return null
preRelease = PreRelease(result2.groupValues[1], v)
}
return Version(
major,
minor,
patch,
preRelease,
snapshot
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,54 @@ package com.gradleup.librarian.core.tooling
import java.io.File

fun tagAndBump(versionToRelease: String) {
return tagAndBump(versionToRelease) {
error("versionToRelease must not be null")
}
}

sealed interface Confirmation
class UseDefaultVersion(
val expectedVersion: String
): Confirmation

class DowngradeVersion(
val tagVersion: String,
val currentVersion: String
): Confirmation

class BumpMajor(
val tagVersion: String,
val currentVersion: String
): Confirmation

fun tagAndBump(versionToRelease: String?, confirm: (Confirmation) -> Unit) {
checkCwd()

check(versionToRelease.isValidVersion()) {
"Version must start with 'major.minor.patch' (found '$versionToRelease')"
var tagVersion = versionToRelease
val currentVersion = getCurrentVersion()
val currentVersionParsed = currentVersion.toVersionOrNull()
check(currentVersionParsed != null) {
"Cannot parse current version: '${currentVersion}'"
}
check(currentVersionParsed.isSnapshot) {
"Version '${currentVersion} is not a -SNAPSHOT, check your working directory"
}

val expectedVersion = currentVersion.removeSuffix("-SNAPSHOT")

check(getCurrentVersion().endsWith("-SNAPSHOT")) {
"Version '${getCurrentVersion()} is not a -SNAPSHOT, check your working directory"
if (tagVersion == null) {
confirm(UseDefaultVersion(expectedVersion))
tagVersion = expectedVersion
}

val tagVersionParsed = tagVersion.toVersionOrNull()
check(tagVersionParsed != null) {
"Version must start with 'major.minor.patch' (found '$tagVersion')"
}
if (tagVersionParsed < currentVersionParsed) {
confirm(DowngradeVersion(tagVersion, currentVersion))
} else if (tagVersionParsed.major > currentVersionParsed.major) {
confirm(BumpMajor(tagVersion, currentVersion))
}

check(runCommand("git", "status", "--porcelain").isEmpty()) {
Expand All @@ -22,14 +62,14 @@ fun tagAndBump(versionToRelease: String) {
"You must be on the main branch or a release branch to make a release"
}

val markdown = processChangelog(versionToRelease)
val markdown = processChangelog(tagVersion)

// 'De-snapshot' the version, open a PR, and merge it
val releaseBranchName = "tag-$versionToRelease"
val releaseBranchName = "tag-$tagVersion"
runCommand("git", "checkout", "-b", releaseBranchName)
setCurrentVersion(versionToRelease)
setVersionInDocs(versionToRelease)
runCommand("git", "commit", "-a", "-m", "release $versionToRelease")
setCurrentVersion(tagVersion)
setVersionInDocs(tagVersion)
runCommand("git", "commit", "-a", "-m", "release $tagVersion")
runCommand("git", "push", "origin", releaseBranchName)
runCommand("gh", "pr", "create", "--base", startBranch, "--fill")

Expand All @@ -39,17 +79,17 @@ fun tagAndBump(versionToRelease: String) {
// Tag the release, and push the tag
runCommand("git", "checkout", startBranch)
runCommand("git", "pull", "origin", startBranch)
val tagName = "v$versionToRelease"
val tagName = "v$tagVersion"
runCommand("git", "tag", tagName, "-m", markdown)

runCommand("git", "push", "origin", tagName)
println("Tag pushed.")

// Bump the version to the next snapshot
val bumpVersionBranchName = "bump-$versionToRelease"
val bumpVersionBranchName = "bump-$tagVersion"
runCommand("git", "checkout", "-b", bumpVersionBranchName)

val nextSnapshot = getNextSnapshot(versionToRelease)
val nextSnapshot = getNextSnapshot(tagVersion)
setCurrentVersion(nextSnapshot)
runCommand("git", "commit", "-a", "-m", "version is now $nextSnapshot")
runCommand("git", "push", "origin", bumpVersionBranchName)
Expand Down
9 changes: 5 additions & 4 deletions librarian-core/src/main/resources/gitignore
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
.kotlin
.fleet
.gradle

# Build outputs
build

# Idea
**/.idea/*
!**/.idea/codeStyles
!**/.idea/icon.png
!**/.idea/runConfigurations
!**/.idea/scopes
!**/.idea/dictionaries
*.iml

# Generated files
build
.kotlin

# Place where the Android SDK path is set
local.properties

Expand Down
44 changes: 44 additions & 0 deletions librarian-core/src/test/kotlin/SemVerTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import com.gradleup.librarian.core.tooling.toVersionOrNull
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull

class SemVerTest {
@Test
fun test() {
"1.2.3-alpha.0".toVersionOrNull().apply {
assertNotNull(this)
assertEquals(1, major)
assertEquals(2, minor)
assertEquals(3, patch)
assertEquals(false, isSnapshot)
assertEquals("alpha", preRelease?.name)
assertEquals(0, preRelease?.version)
}
"1.2.3".toVersionOrNull().apply {
assertNotNull(this)
assertEquals(1, major)
assertEquals(2, minor)
assertEquals(3, patch)
assertEquals(false, isSnapshot)
assertEquals(null, preRelease)
}
"1.2.3-SNAPSHOT".toVersionOrNull().apply {
assertNotNull(this)
assertEquals(1, major)
assertEquals(2, minor)
assertEquals(3, patch)
assertEquals(true, isSnapshot)
assertEquals(null, preRelease)
}
"1.2.3-alpha.0-SNAPSHOT".toVersionOrNull().apply {
assertNotNull(this)
assertEquals(1, major)
assertEquals(2, minor)
assertEquals(3, patch)
assertEquals(true, isSnapshot)
assertEquals("alpha", preRelease?.name)
assertEquals(0, preRelease?.version)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.maven.tasks.AbstractPublishToMaven
import org.gradle.api.tasks.TaskProvider
import org.gradle.jvm.tasks.Jar
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import java.util.Properties

internal const val librarianPublication = "librarianPublication"
Expand Down Expand Up @@ -154,8 +155,9 @@ fun Project.createMissingPublications(
when {
project.plugins.hasPlugin("org.jetbrains.kotlin.multiplatform") -> {
/**
* Kotlin MPP creates publications.
* It only misses the javadoc
* Kotlin MPP creates publications but doesn't add javadoc.
* Note: for Android, the caller needs to opt-in puoblication
* See https://kotlinlang.org/docs/multiplatform-publish-lib.html#publish-an-android-library
*/
publications.withType(MavenPublication::class.java).configureEach {
it.artifact(emptyJavadoc)
Expand Down

0 comments on commit 06c9461

Please sign in to comment.