add git extension
This commit is contained in:
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
## Extension
|
## Extension
|
||||||
|
|
||||||
|
### Extension Git
|
||||||
|
|
||||||
|
The GitExtension enhances versioning by dynamically appending the Git hash before "snapshot" in the version string. For example, 0.0.0-SNAPSHOT becomes 0.0.0.0a2b3c4d-SNAPSHOT, ensuring each build reflects its commit origin, prevents overwriting existing versions. This feature aids developers during development by providing clear version identification.
|
||||||
|
|
||||||
## Publish version catalog locally.
|
## Publish version catalog locally.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
|
|||||||
@@ -17,7 +17,11 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation(aa.jgit)
|
||||||
|
|
||||||
|
testImplementation(aa.junit.jupiter.params)
|
||||||
testImplementation(aa.kotlin.junit5)
|
testImplementation(aa.kotlin.junit5)
|
||||||
|
testImplementation(aa.mockk)
|
||||||
|
|
||||||
testRuntimeOnly(aa.junit.platform.launcher)
|
testRuntimeOnly(aa.junit.platform.launcher)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package ltd.lulz.plugin
|
package ltd.lulz.plugin
|
||||||
|
|
||||||
|
import ltd.lulz.plugin.extension.GitExtension
|
||||||
import org.gradle.api.Plugin
|
import org.gradle.api.Plugin
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
|
import ltd.lulz.plugin.extension.GitExtension.Companion.PLUGIN_NAME as GIT_PLUGIN_NAME
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
class CorePlugin : Plugin<Project> {
|
class CorePlugin : Plugin<Project> {
|
||||||
@@ -12,6 +14,11 @@ class CorePlugin : Plugin<Project> {
|
|||||||
override fun apply(
|
override fun apply(
|
||||||
project: Project,
|
project: Project,
|
||||||
) {
|
) {
|
||||||
TODO("Not yet implemented")
|
gitExtension(project)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun gitExtension(
|
||||||
|
project: Project,
|
||||||
|
): GitExtension = project.extensions
|
||||||
|
.create(GIT_PLUGIN_NAME, GitExtension::class.java, project)
|
||||||
}
|
}
|
||||||
|
|||||||
37
src/main/kotlin/ltd/lulz/plugin/extension/GitExtension.kt
Normal file
37
src/main/kotlin/ltd/lulz/plugin/extension/GitExtension.kt
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package ltd.lulz.plugin.extension
|
||||||
|
|
||||||
|
import org.eclipse.jgit.api.Git.open
|
||||||
|
import org.eclipse.jgit.lib.Constants.HEAD
|
||||||
|
import org.gradle.api.Project
|
||||||
|
|
||||||
|
abstract class GitExtension(private val project: Project) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PLUGIN_NAME = "git"
|
||||||
|
|
||||||
|
private const val HASH_LENGTH = 8
|
||||||
|
private const val SNAPSHOT = "-SNAPSHOT"
|
||||||
|
private const val UNAVAILABLE = "n/a"
|
||||||
|
private val PRIMARY_BRANCHES = setOf("master", "develop")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun version(): String = when {
|
||||||
|
isHead() || currentBranch() in PRIMARY_BRANCHES -> project.version.toString()
|
||||||
|
else -> makeVersion(project.version.toString(), currentShortHash())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun currentShortHash(): String = open(project.projectDir)
|
||||||
|
.use { it.repository.exactRef(HEAD)?.objectId?.name?.take(HASH_LENGTH) ?: UNAVAILABLE }
|
||||||
|
|
||||||
|
fun currentBranch(): String = open(project.projectDir)
|
||||||
|
.use { it.repository.branch ?: UNAVAILABLE }
|
||||||
|
|
||||||
|
fun isHead(): Boolean = open(project.projectDir)
|
||||||
|
.use { it.repository.exactRef(HEAD)?.target?.name == HEAD }
|
||||||
|
|
||||||
|
private fun makeVersion(version: String, shortHash: String): String = when {
|
||||||
|
shortHash == UNAVAILABLE -> version.also { println("Failed to get data from GIT") }
|
||||||
|
version.endsWith(SNAPSHOT) -> version.replace(SNAPSHOT, ".$shortHash$SNAPSHOT")
|
||||||
|
else -> version.also { println("Failed version missing suffix $SNAPSHOT") }
|
||||||
|
}
|
||||||
|
}
|
||||||
162
src/test/kotlin/ltd/lulz/plugin/extension/GitExtensionTest.kt
Normal file
162
src/test/kotlin/ltd/lulz/plugin/extension/GitExtensionTest.kt
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
package ltd.lulz.plugin.extension
|
||||||
|
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.justRun
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.mockkStatic
|
||||||
|
import io.mockk.unmockkStatic
|
||||||
|
import org.eclipse.jgit.api.Git
|
||||||
|
import org.eclipse.jgit.lib.ObjectId
|
||||||
|
import org.eclipse.jgit.lib.Ref
|
||||||
|
import org.eclipse.jgit.lib.Repository
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.testfixtures.ProjectBuilder
|
||||||
|
import org.junit.jupiter.api.AfterEach
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest
|
||||||
|
import org.junit.jupiter.params.provider.CsvSource
|
||||||
|
|
||||||
|
class GitExtensionTest {
|
||||||
|
companion object {
|
||||||
|
const val GIT_HASH_SHA_1 = "0a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t"
|
||||||
|
const val SHORT_GIT_HASH = "0a1b2c3d"
|
||||||
|
const val SNAPSHOT_HASH_VERSION = "0.0.0.0a1b2c3d-SNAPSHOT"
|
||||||
|
const val SNAPSHOT_VERSION = "0.0.0-SNAPSHOT"
|
||||||
|
const val VERSION = "0.0.0"
|
||||||
|
|
||||||
|
const val BRANCH_FEATURE = "feature/ABC-123"
|
||||||
|
const val BRANCH_MASTER = "master"
|
||||||
|
const val EXTENSION = "git"
|
||||||
|
const val PLUGIN_ID = "ltd.lulz.plugin.core-plugin"
|
||||||
|
const val REF_HEAD = "HEAD"
|
||||||
|
const val UNAVAILABLE = "n/a"
|
||||||
|
}
|
||||||
|
|
||||||
|
private val gitMock: Git = mockk()
|
||||||
|
private val refMock: Ref = mockk()
|
||||||
|
private val repositoryMock: Repository = mockk()
|
||||||
|
private val objectIdMock: ObjectId = mockk()
|
||||||
|
|
||||||
|
lateinit var name: String
|
||||||
|
lateinit var project: Project
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
fun buildUp() {
|
||||||
|
project = ProjectBuilder.builder().build()
|
||||||
|
project.version = SNAPSHOT_VERSION
|
||||||
|
project.pluginManager.apply(PLUGIN_ID)
|
||||||
|
mockkStatic(Git::class)
|
||||||
|
|
||||||
|
every { Git.open(any()) } returns gitMock
|
||||||
|
every { gitMock.repository } returns repositoryMock
|
||||||
|
every { repositoryMock.branch } returns null
|
||||||
|
every { repositoryMock.exactRef(any()) } returns refMock
|
||||||
|
every { refMock.target } returns refMock
|
||||||
|
every { refMock.name } returns null
|
||||||
|
every { refMock.objectId } returns objectIdMock
|
||||||
|
every { objectIdMock.name } returns null
|
||||||
|
|
||||||
|
justRun { gitMock.close() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
fun tearDown() {
|
||||||
|
unmockkStatic(Git::class)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(
|
||||||
|
"$REF_HEAD, true",
|
||||||
|
"$BRANCH_FEATURE, false",
|
||||||
|
)
|
||||||
|
fun `current ref is head`(ref: String, expected: Boolean) {
|
||||||
|
// given
|
||||||
|
every { refMock.name } returns ref
|
||||||
|
|
||||||
|
// when
|
||||||
|
val extension = project.extensions.getByName(EXTENSION) as GitExtension
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertEquals(expected, extension.isHead())
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(
|
||||||
|
", $UNAVAILABLE",
|
||||||
|
"$BRANCH_FEATURE, $BRANCH_FEATURE",
|
||||||
|
)
|
||||||
|
fun `get current branch`(branch: String?, expected: String) {
|
||||||
|
// given
|
||||||
|
every { repositoryMock.branch } returns branch
|
||||||
|
|
||||||
|
// when
|
||||||
|
val extension = project.extensions.getByName(EXTENSION) as GitExtension
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertEquals(expected, extension.currentBranch())
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(
|
||||||
|
", $UNAVAILABLE",
|
||||||
|
"$GIT_HASH_SHA_1, $SHORT_GIT_HASH",
|
||||||
|
)
|
||||||
|
fun `get current short hash`(hash: String?, expected: String) {
|
||||||
|
// given
|
||||||
|
every { objectIdMock.name } returns hash
|
||||||
|
|
||||||
|
// when
|
||||||
|
val extension = project.extensions.getByName(EXTENSION) as GitExtension
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertEquals(expected, extension.currentShortHash())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `get version - version without snapshot`() {
|
||||||
|
// given
|
||||||
|
project.version = VERSION
|
||||||
|
every { objectIdMock.name } returns GIT_HASH_SHA_1
|
||||||
|
|
||||||
|
// when
|
||||||
|
val extension = project.extensions.getByName(EXTENSION) as GitExtension
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertEquals(VERSION, extension.version())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `get version - short hash is blank`() {
|
||||||
|
// when
|
||||||
|
val extension = project.extensions.getByName(EXTENSION) as GitExtension
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertEquals(SNAPSHOT_VERSION, extension.version())
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(
|
||||||
|
", , $SNAPSHOT_HASH_VERSION",
|
||||||
|
", $REF_HEAD, $SNAPSHOT_VERSION",
|
||||||
|
"$BRANCH_MASTER, , $SNAPSHOT_VERSION",
|
||||||
|
"$BRANCH_MASTER, , $SNAPSHOT_VERSION",
|
||||||
|
"$BRANCH_FEATURE, , $SNAPSHOT_HASH_VERSION",
|
||||||
|
"$BRANCH_MASTER, $REF_HEAD, $SNAPSHOT_VERSION",
|
||||||
|
"$BRANCH_MASTER, $REF_HEAD, $SNAPSHOT_VERSION",
|
||||||
|
"$BRANCH_FEATURE, $REF_HEAD, $SNAPSHOT_VERSION",
|
||||||
|
)
|
||||||
|
fun `get version - different branches`(branch: String?, ref: String?, expected: String) {
|
||||||
|
// given
|
||||||
|
every { repositoryMock.branch } returns branch
|
||||||
|
every { objectIdMock.name } returns GIT_HASH_SHA_1
|
||||||
|
every { refMock.name } returns ref
|
||||||
|
|
||||||
|
// when
|
||||||
|
val extension = project.extensions.getByName(EXTENSION) as GitExtension
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertEquals(expected, extension.version())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user