add git extension
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
|
||||
## 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.
|
||||
|
||||
```shell
|
||||
|
||||
@@ -17,7 +17,11 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(aa.jgit)
|
||||
|
||||
testImplementation(aa.junit.jupiter.params)
|
||||
testImplementation(aa.kotlin.junit5)
|
||||
testImplementation(aa.mockk)
|
||||
|
||||
testRuntimeOnly(aa.junit.platform.launcher)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package ltd.lulz.plugin
|
||||
|
||||
import ltd.lulz.plugin.extension.GitExtension
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import ltd.lulz.plugin.extension.GitExtension.Companion.PLUGIN_NAME as GIT_PLUGIN_NAME
|
||||
|
||||
@Suppress("unused")
|
||||
class CorePlugin : Plugin<Project> {
|
||||
@@ -12,6 +14,11 @@ class CorePlugin : Plugin<Project> {
|
||||
override fun apply(
|
||||
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