Skip to content

Commit b85c414

Browse files
Add repoName field to event classes, populate with sensible default (#123)
Useful for knowing where the tool is being used
1 parent 87c2b19 commit b85c414

File tree

9 files changed

+175
-0
lines changed

9 files changed

+175
-0
lines changed

core/src/main/kotlin/xyz/block/artifactswap/core/artifact_checker/models/ArtifactCheckerEvent.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package xyz.block.artifactswap.core.artifact_checker.models
22

33
import com.squareup.moshi.Json
44
import com.squareup.moshi.JsonClass
5+
import xyz.block.artifactswap.core.utils.RepoNameProvider
56

67
/** Result of artifact checker operation. */
78
enum class ArtifactCheckerResult(val exitCode: Int) {
@@ -46,6 +47,7 @@ data class ArtifactCheckerExecutionEvent(
4647
@Json(name = "ci_build_step_id") val buildStepId: String = "",
4748
@Json(name = "ci_build_job_id") val buildJobId: String = "",
4849
@Json(name = "ci_type") val ciType: String = "",
50+
@Json(name = "repo_name") val repoName: String = RepoNameProvider.default.repoName,
4951
)
5052

5153
/** Converts a service result to an execution event. */

core/src/main/kotlin/xyz/block/artifactswap/core/download/models/ArtifactDownloaderEvent.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package xyz.block.artifactswap.core.download.models
33
import com.squareup.moshi.Json
44
import com.squareup.moshi.JsonClass
55
import xyz.block.artifactswap.core.eventstream.EventstreamEvent
6+
import xyz.block.artifactswap.core.utils.RepoNameProvider
67

78
@JsonClass(generateAdapter = true)
89
data class ArtifactDownloaderEvent(
@@ -41,6 +42,7 @@ data class ArtifactDownloaderEvent(
4142
@Json(name = "base_build_job_id") val buildJobId: String = "",
4243
@Json(name = "base_ci_type") val ciType: String = "",
4344
@Json(name = "user_ldap") val userLdap: String = System.getProperty("user.name"),
45+
@Json(name = "repo_name") val repoName: String = RepoNameProvider.default.repoName,
4446
) {
4547

4648
fun toEventStreamEvent(): EventstreamEvent {

core/src/main/kotlin/xyz/block/artifactswap/core/hashing/models/HashingEvent.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.squareup.moshi.Json
44
import com.squareup.moshi.JsonClass
55
import kotlin.time.Duration
66
import xyz.block.artifactswap.core.eventstream.EventstreamEvent
7+
import xyz.block.artifactswap.core.utils.RepoNameProvider
78

89
/** Result of hashing a single project. */
910
data class ProjectHashingResult(
@@ -51,6 +52,7 @@ data class HashingExecutionEvent(
5152
@Json(name = "base_build_job_id") val buildJobId: String = "",
5253
@Json(name = "base_ci_type") val ciType: String = "",
5354
@Json(name = "user_ldap") val userLdap: String = System.getProperty("user.name"),
55+
@Json(name = "repo_name") val repoName: String = RepoNameProvider.default.repoName,
5456
) {
5557
fun toEventStreamEvent(): EventstreamEvent {
5658
return EventstreamEvent(

core/src/main/kotlin/xyz/block/artifactswap/core/publisher/models/BomPublishingEvent.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package xyz.block.artifactswap.core.publisher.models
33
import com.squareup.moshi.Json
44
import com.squareup.moshi.JsonClass
55
import xyz.block.artifactswap.core.eventstream.EventstreamEvent
6+
import xyz.block.artifactswap.core.utils.RepoNameProvider
67

78
/**
89
* Documents final task status.
@@ -58,6 +59,7 @@ data class BomPublishingEvent(
5859
@Json(name = "ci_build_step_id") val buildStepId: String,
5960
@Json(name = "ci_build_job_id") val buildJobId: String,
6061
@Json(name = "ci_type") val ciType: String,
62+
@Json(name = "repo_name") val repoName: String = RepoNameProvider.default.repoName,
6163
) {
6264
fun toEventStreamEvent(): EventstreamEvent {
6365
return EventstreamEvent(

core/src/main/kotlin/xyz/block/artifactswap/core/remover/models/ArtifactRemoverEvent.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import xyz.block.artifactswap.core.eventstream.EventstreamEvent
77
import xyz.block.artifactswap.core.repository.InstalledBom
88
import xyz.block.artifactswap.core.repository.InstalledProject
99
import xyz.block.artifactswap.core.repository.RepositoryStats
10+
import xyz.block.artifactswap.core.utils.RepoNameProvider
1011
import xyz.block.artifactswap.core.utils.inWholeMillisecondsIfFinite
1112

1213
enum class ArtifactRemoverEventResult(val exitCode: Int) {
@@ -132,6 +133,7 @@ data class ArtifactRemoverEvent(
132133
@Json(name = "delete_old_boms_duration_ms") val deleteOldBomsDurationMs: Long = -1,
133134
@Json(name = "total_duration_ms") val totalDurationMs: Long = -1,
134135
@Json(name = "user_ldap") val userLdap: String = System.getProperty("user.name"),
136+
@Json(name = "repo_name") val repoName: String = RepoNameProvider.default.repoName,
135137
) {
136138

137139
fun toEventStreamEvent(): EventstreamEvent {

core/src/main/kotlin/xyz/block/artifactswap/core/task_finder/models/TaskFinderEvent.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package xyz.block.artifactswap.core.task_finder.models
22

33
import com.squareup.moshi.Json
44
import com.squareup.moshi.JsonClass
5+
import xyz.block.artifactswap.core.utils.RepoNameProvider
56

67
/** Result of task finder operation. */
78
enum class TaskFinderResult(val exitCode: Int) {
@@ -46,6 +47,7 @@ data class TaskFinderExecutionEvent(
4647
@Json(name = "ci_build_step_id") val buildStepId: String = "",
4748
@Json(name = "ci_build_job_id") val buildJobId: String = "",
4849
@Json(name = "ci_type") val ciType: String = "",
50+
@Json(name = "repo_name") val repoName: String = RepoNameProvider.default.repoName,
4951
)
5052

5153
/** Converts a service result to an execution event. */

core/src/main/kotlin/xyz/block/artifactswap/core/task_runner/models/TaskRunnerEvent.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package xyz.block.artifactswap.core.task_runner.models
22

33
import com.squareup.moshi.Json
44
import com.squareup.moshi.JsonClass
5+
import xyz.block.artifactswap.core.utils.RepoNameProvider
56

67
/** Result of task runner operation. */
78
enum class TaskRunnerResult(val exitCode: Int) {
@@ -51,6 +52,7 @@ data class TaskRunnerExecutionEvent(
5152
@Json(name = "ci_build_step_id") val buildStepId: String = "",
5253
@Json(name = "ci_build_job_id") val buildJobId: String = "",
5354
@Json(name = "ci_type") val ciType: String = "",
55+
@Json(name = "repo_name") val repoName: String = RepoNameProvider.default.repoName,
5456
)
5557

5658
/** Converts a service result to an execution event. */
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package xyz.block.artifactswap.core.utils
2+
3+
import java.io.IOException
4+
import java.nio.file.Path
5+
import org.apache.logging.log4j.kotlin.logger
6+
import org.eclipse.jgit.storage.file.FileRepositoryBuilder
7+
8+
internal class RepoNameProvider(private val rootDir: Path) {
9+
10+
companion object {
11+
val default: RepoNameProvider by lazy { RepoNameProvider(Path.of("")) }
12+
}
13+
14+
val repoName: String by lazy {
15+
try {
16+
val repoRoot = findRepoRoot() ?: return@lazy ""
17+
val repoName =
18+
FileRepositoryBuilder().readEnvironment().findGitDir(repoRoot.toFile()).build().use { repo
19+
->
20+
val originUrl =
21+
repo.remoteNames
22+
.filter { it == "origin" }
23+
.map { repo.getConfig().getString("remote", it, "url") }
24+
.firstOrNull() ?: return@lazy ""
25+
originUrl.substringAfterLast("/").substringBeforeLast(".")
26+
}
27+
logger.debug("Repo name: $repoName")
28+
repoName
29+
} catch (e: IOException) {
30+
logger.warn("Failed to get repo name", e)
31+
""
32+
}
33+
}
34+
35+
/** Find location in current directory/parents that has a .git folder, if it exists */
36+
private fun findRepoRoot(): Path? {
37+
val currentDir = rootDir.toAbsolutePath()
38+
var dir = currentDir
39+
while (dir.parent != null) {
40+
if (dir.resolve(".git").toFile().exists()) {
41+
return dir
42+
}
43+
dir = dir.parent
44+
}
45+
return null
46+
}
47+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package xyz.block.artifactswap.core.utils
2+
3+
import java.nio.file.Path
4+
import kotlin.io.path.createDirectories
5+
import org.eclipse.jgit.api.Git
6+
import org.eclipse.jgit.transport.URIish
7+
import org.junit.jupiter.api.Assertions.*
8+
import org.junit.jupiter.api.Test
9+
import org.junit.jupiter.api.io.TempDir
10+
11+
class RepoNameProviderTest {
12+
13+
@TempDir lateinit var tempDir: Path
14+
15+
@Test
16+
fun `repo name is correct when root dir is git repo`() {
17+
val expectedRepoName = "test-repo"
18+
val repoRoot =
19+
tempDir.resolve(expectedRepoName).also { repoRoot ->
20+
Git.init().setDirectory(repoRoot.toFile()).call().use { git ->
21+
git
22+
.remoteAdd()
23+
.setName("origin")
24+
.setUri(URIish("https://example.com/$expectedRepoName.git"))
25+
.call()
26+
}
27+
}
28+
val repoNameProvider = RepoNameProvider(repoRoot)
29+
val actualRepoName = repoNameProvider.repoName
30+
assertEquals(expectedRepoName, actualRepoName)
31+
}
32+
33+
@Test
34+
fun `repo name is correct when root dir is subdir of a git repo`() {
35+
val expectedRepoName = "test-repo"
36+
val repoRoot =
37+
tempDir.resolve(expectedRepoName).also { repoRoot ->
38+
Git.init().setDirectory(repoRoot.toFile()).call().use { git ->
39+
git
40+
.remoteAdd()
41+
.setName("origin")
42+
.setUri(URIish("https://example.com/$expectedRepoName.git"))
43+
.call()
44+
}
45+
}
46+
val subDir = repoRoot.resolve("subdir").also { it.createDirectories() }
47+
val repoNameProvider = RepoNameProvider(subDir)
48+
val actualRepoName = repoNameProvider.repoName
49+
assertEquals(expectedRepoName, actualRepoName)
50+
}
51+
52+
@Test
53+
fun `repo name is empty when no git repo is found`() {
54+
val expectedRepoName = ""
55+
val nonRepoRoot = tempDir.resolve("non-git-repo-directory")
56+
val repoNameProvider = RepoNameProvider(nonRepoRoot)
57+
val actualRepoName = repoNameProvider.repoName
58+
assertEquals(expectedRepoName, actualRepoName)
59+
}
60+
61+
@Test
62+
fun `repo name is empty when repo has no remote named origin`() {
63+
val expectedRepoName = ""
64+
val repoRoot =
65+
tempDir.resolve(expectedRepoName).also { repoRoot ->
66+
Git.init().setDirectory(repoRoot.toFile()).call().use { git ->
67+
git
68+
.remoteAdd()
69+
.setName("nonOrigin")
70+
.setUri(URIish("https://example.com/$expectedRepoName.git"))
71+
.call()
72+
}
73+
}
74+
val repoNameProvider = RepoNameProvider(repoRoot)
75+
val actualRepoName = repoNameProvider.repoName
76+
assertEquals(expectedRepoName, actualRepoName)
77+
}
78+
79+
@Test
80+
fun `repo name is correct for standard GitHub HTTPS URL`() {
81+
val expectedRepoName = "artifact-swap"
82+
val repoRoot =
83+
tempDir.resolve("github-repo").also { repoRoot ->
84+
Git.init().setDirectory(repoRoot.toFile()).call().use { git ->
85+
git
86+
.remoteAdd()
87+
.setName("origin")
88+
.setUri(URIish("https://github.com/block/artifact-swap.git"))
89+
.call()
90+
}
91+
}
92+
val repoNameProvider = RepoNameProvider(repoRoot)
93+
val actualRepoName = repoNameProvider.repoName
94+
assertEquals(expectedRepoName, actualRepoName)
95+
}
96+
97+
@Test
98+
fun `repo name is correct for GitHub Enterprise SSH-style URL`() {
99+
val expectedRepoName = "artifact-swap"
100+
val repoRoot =
101+
tempDir.resolve("github-enterprise-repo").also { repoRoot ->
102+
Git.init().setDirectory(repoRoot.toFile()).call().use { git ->
103+
git
104+
.remoteAdd()
105+
.setName("origin")
106+
.setUri(URIish("org-123123123@github.com:block/artifact-swap.git"))
107+
.call()
108+
}
109+
}
110+
val repoNameProvider = RepoNameProvider(repoRoot)
111+
val actualRepoName = repoNameProvider.repoName
112+
assertEquals(expectedRepoName, actualRepoName)
113+
}
114+
}

0 commit comments

Comments
 (0)