Skip to content

Commit

Permalink
handle ci environments (#5)
Browse files Browse the repository at this point in the history
* handle ci environments

* make tests CI resilient

* remove debug mode on gradle runner test to avoid leaking ci environments into the test env
  • Loading branch information
MarvinSchramm authored May 27, 2023
1 parent 778dc0b commit 380f63b
Show file tree
Hide file tree
Showing 9 changed files with 348 additions and 11 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,21 @@ tasks.withType(GenerateGitPropertiesTask::class.java) {

> File (build.gradle.kts)
#### Behaviour on CI environments

As you may know, CI environments handle the git repository differently.
This plugin handles the branch resolution for

- Github Actions
- Gitlab CI
- Travis CI

If you are using a different CI service you can provide the branch name via the `branch-name` option

```bash
./gradlew generateGitProperties --branch-name=$CI_SPECIFIC_ENV
```

#### Available Properties

```properties
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ plugins {
}

group = "io.hndrs.gradle"
version = "1.0.0"
version = "1.0.0-local"

repositories {
mavenCentral()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ import org.gradle.api.provider.Property
import org.gradle.api.tasks.CacheableTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputDirectory
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.TaskExecutionException
import org.gradle.api.tasks.options.Option
import org.gradle.kotlin.dsl.property
import java.io.File
import javax.inject.Inject

Expand All @@ -44,6 +46,10 @@ abstract class GenerateGitPropertiesTask @Inject constructor(
val continueOnError: Property<Boolean> = objectFactory.property(Boolean::class.java)
.convention(false)

@get:Input
@get:Optional
@Option(option = "branch-name", description = "Provide branch name via cli")
val branchName: Property<String> = objectFactory.property(String::class)

/**
* Output file of this given task defaults to `/build/main/resources/git.properties`
Expand All @@ -56,7 +62,7 @@ abstract class GenerateGitPropertiesTask @Inject constructor(
runCatching {
val git = Git.open(dotGitDirectory.asFile.get())
val properties = GitPropertiesProviderChain.of(
GitBranchPropertiesProvider(git),
GitBranchPropertiesProvider(git, branchName.orNull),
GitConfigPropertiesProvider(git),
GitLogPropertiesProvider(git),
BuildHostPropertiesProvider(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,39 @@ package io.hndrs.gradle.plugin.git.properties.data
import org.eclipse.jgit.api.Git

class GitBranchPropertiesProvider(
private val git: Git
private val git: Git,
private val branchName: String?
) : GitPropertyProvider {

override fun get(): Map<String, Any?> {
return mapOf(GIT_BRANCH to git.repository.branch)
return branchName?.let {
mapOf(GIT_BRANCH to branchName)
} ?: resolveBranchName()?.let {
mapOf(GIT_BRANCH to it)
} ?: mapOf(GIT_BRANCH to git.repository.branch)
}

private fun resolveBranchName(): String? {
return CI_ENV_BRANCH_MAPPING.entries.firstNotNullOfOrNull {
if (EnvProvider.getEnv(it.key) != null) {
it.value.firstNotNullOfOrNull { EnvProvider.getEnv(it) }
} else null
}
}

/**
* Wrapper object for mocking
*/
object EnvProvider {
fun getEnv(name: String): String? = System.getenv(name)
}

companion object {
private const val GIT_BRANCH = "git.branch"
private val CI_ENV_BRANCH_MAPPING = mapOf(
"GITLAB_CI" to arrayOf("CI_COMMIT_REF_NAME"),
"CI" to arrayOf("GITHUB_HEAD_REF", "GITHUB_REF_NAME"),
"TRAVIS" to arrayOf("TRAVIS_BRANCH")
)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.hndrs.gradle.plugin.git.properties.data

import org.eclipse.jgit.api.Git
import java.net.URI

class GitConfigPropertiesProvider(
private val git: Git
Expand All @@ -13,11 +14,19 @@ class GitConfigPropertiesProvider(
mapOf(
GIT_BUILD_USER_EMAIL to it.getString("user", null, "email"),
GIT_BUILD_USER_NAME to it.getString("user", null, "name"),
GIT_REMOTE_ORIGIN_URL to it.getString("remote", "origin", "url")
GIT_REMOTE_ORIGIN_URL to it.getString("remote", "origin", "url")?.sanitise()
)
}
}

private fun String.sanitise(): String? {
return runCatching {
URI(this).userInfo?.let {
this.replace(it, "").replace("@", "")
}
}.getOrDefault(this)
}

companion object {
private const val GIT_REMOTE_ORIGIN_URL = "git.remote.origin.url"
private const val GIT_BUILD_USER_EMAIL = "git.build.user.email"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import java.io.File
class TestGitRepository(rootDir: File) {

private val git = Git.init().setDirectory(rootDir).call()

fun addCommit() =
git.commit()
.setAllowEmpty(true)
Expand All @@ -25,4 +25,6 @@ class TestGitRepository(rootDir: File) {
it.setString("user", null, "name", value)
it.save()
}

fun branch() = git.repository.branch
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,88 @@
package io.hndrs.gradle.plugin.git.properties.data

import io.hndrs.gradle.plugin.git.properties.data.GitBranchPropertiesProvider.EnvProvider
import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkObject
import org.eclipse.jgit.api.Git

class GitBranchPropertiesProviderTest : StringSpec({

val git = mockk<Git>() {
every { repository.branch } returns "main"
every { repository.branch } returns "git-main"
}

val underTest = GitBranchPropertiesProvider(git)
"resolves git branch via branch-name-option" {
val underTest = GitBranchPropertiesProvider(git, "main")
underTest.get() shouldBe mapOf(
"git.branch" to "main"
)
}

"resolves git branch via git" {
val underTest = GitBranchPropertiesProvider(git, null)
mockkObject(EnvProvider)
// to run tests on CI we need to make sure all return null
every { EnvProvider.getEnv(any()) } returns null
underTest.get() shouldBe mapOf(
"git.branch" to "main"
"git.branch" to "git-main"
)
}

"resolves git branch for github actions via env GITHUB_HEAD_REF" {
val underTest = GitBranchPropertiesProvider(git, null)
mockkObject(EnvProvider)

every { EnvProvider.getEnv("TRAVIS") } returns null
every { EnvProvider.getEnv("GITLAB_CI") } returns null
every { EnvProvider.getEnv("CI") } returns "true"
every { EnvProvider.getEnv("GITHUB_HEAD_REF") } returns "head-ref-main"

underTest.get() shouldBe mapOf(
"git.branch" to "head-ref-main"
)
}

"resolves git branch for github actions via env GITHUB_REF_NAME" {
val underTest = GitBranchPropertiesProvider(git, null)
mockkObject(EnvProvider)

every { EnvProvider.getEnv("TRAVIS") } returns null
every { EnvProvider.getEnv("GITLAB_CI") } returns null
every { EnvProvider.getEnv("CI") } returns "true"
every { EnvProvider.getEnv("GITHUB_HEAD_REF") } returns null
every { EnvProvider.getEnv("GITHUB_REF_NAME") } returns "ref-main"

underTest.get() shouldBe mapOf(
"git.branch" to "ref-main"
)
}

"resolves git branch for gitlab-ci via env CI_COMMIT_REF_NAME" {
val underTest = GitBranchPropertiesProvider(git, null)
mockkObject(EnvProvider)
every { EnvProvider.getEnv("TRAVIS") } returns null
every { EnvProvider.getEnv("CI") } returns null
every { EnvProvider.getEnv("GITLAB_CI") } returns "true"
every { EnvProvider.getEnv("CI_COMMIT_REF_NAME") } returns "gitlab-main"

underTest.get() shouldBe mapOf(
"git.branch" to "gitlab-main"
)
}

"resolves git branch for travis-ci via env TRAVIS_BRANCH" {
val underTest = GitBranchPropertiesProvider(git, null)
mockkObject(EnvProvider)
every { EnvProvider.getEnv("GITLAB_CI") } returns null
every { EnvProvider.getEnv("CI") } returns null
every { EnvProvider.getEnv("TRAVIS") } returns "true"
every { EnvProvider.getEnv("TRAVIS_BRANCH") } returns "travis-main"

underTest.get() shouldBe mapOf(
"git.branch" to "travis-main"
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class GitConfigPropertiesProviderTest : StringSpec({
every { repository.config } returns mockk(relaxed = true) {
every { getString("user", null, "email") } returns "[email protected]"
every { getString("user", null, "name") } returns "John Smith"
every { getString("remote", "origin", "url") } returns "git@github.com:hndrs/gradle-git-properties-plugin.git"
every { getString("remote", "origin", "url") } returns "https://name:password@github.com/hndrs/gradle-git-properties-plugin.git"
}
}

Expand All @@ -22,7 +22,7 @@ class GitConfigPropertiesProviderTest : StringSpec({
underTest.get() shouldBe mapOf(
"git.build.user.email" to "[email protected]",
"git.build.user.name" to "John Smith",
"git.remote.origin.url" to "git@github.com:hndrs/gradle-git-properties-plugin.git"
"git.remote.origin.url" to "https://github.com/hndrs/gradle-git-properties-plugin.git"
)
}

Expand Down
Loading

0 comments on commit 380f63b

Please sign in to comment.