From 363bf8933dc866641eecfd27e3a61f07aec806af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Fri, 24 Apr 2026 15:50:53 +0200 Subject: [PATCH] fix(abg): Only consider refs with exactly three parts --- .../workflows/shared/internal/GithubApi.kt | 3 + .../shared/internal/model/GithubApiTest.kt | 107 ++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/shared-internal/src/main/kotlin/io/github/typesafegithub/workflows/shared/internal/GithubApi.kt b/shared-internal/src/main/kotlin/io/github/typesafegithub/workflows/shared/internal/GithubApi.kt index 54a3eadc7a..0c6a00b53f 100644 --- a/shared-internal/src/main/kotlin/io/github/typesafegithub/workflows/shared/internal/GithubApi.kt +++ b/shared-internal/src/main/kotlin/io/github/typesafegithub/workflows/shared/internal/GithubApi.kt @@ -25,6 +25,8 @@ import java.time.ZonedDateTime private val logger = logger { } +private const val MAX_REF_PARTS = 3 + suspend fun fetchAvailableVersions( owner: String, name: String, @@ -38,6 +40,7 @@ suspend fun fetchAvailableVersions( apiTagsUrl(githubEndpoint = githubEndpoint, owner = owner, name = name), apiBranchesUrl(githubEndpoint = githubEndpoint, owner = owner, name = name), ).flatMap { url -> fetchGithubRefs(url, githubAuthToken, httpClient).bind() } + .filter { it.ref.split('/', limit = MAX_REF_PARTS + 1).size == MAX_REF_PARTS } .versions(githubAuthToken, meterRegistry = meterRegistry) } } diff --git a/shared-internal/src/test/kotlin/io/github/typesafegithub/workflows/shared/internal/model/GithubApiTest.kt b/shared-internal/src/test/kotlin/io/github/typesafegithub/workflows/shared/internal/model/GithubApiTest.kt index eeaa8309b0..74a387cc6b 100644 --- a/shared-internal/src/test/kotlin/io/github/typesafegithub/workflows/shared/internal/model/GithubApiTest.kt +++ b/shared-internal/src/test/kotlin/io/github/typesafegithub/workflows/shared/internal/model/GithubApiTest.kt @@ -109,6 +109,113 @@ class GithubApiTest : Version("v2"), ).right() } + test("branches scoped branches and tags starting with v") { + // Given + val tagsResponse = + """ + [ + { + "ref":"refs/tags/v1.0.0", + "node_id":"MDM6UmVmMTk3ODE0NjI5OnJlZnMvdGFncy92MQ==", + "url":"https://api.github.com/repos/some-owner/some-name/git/refs/tags/v1", + "object": { + "sha":"544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9", + "type":"tag", + "url":"https://api.github.com/repos/actions/some-name/git/tags/544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9" + } + }, + { + "ref":"refs/tags/v1.0.1", + "node_id":"MDM6UmVmMTk3ODE0NjI5OnJlZnMvdGFncy92MQ==", + "url":"https://api.github.com/repos/some-owner/some-name/git/refs/tags/v1.0.1", + "object": { + "sha":"af513c7a016048ae468971c52ed77d9562c7c819", + "type":"tag", + "url":"https://api.github.com/repos/actions/some-name/git/tags/af513c7a016048ae468971c52ed77d9562c7c819" + } + }, + { + "ref":"refs/tags/virtual/tag", + "node_id":"MDM6UmVmMTk3ODE0NjI5OnJlZnMvdGFncy92MQ==", + "url":"https://api.github.com/repos/some-owner/some-name/git/refs/tags/virtual/tag", + "object": { + "sha":"af513c7a016048ae468971c52ed77d9562c7c819", + "type":"tag", + "url":"https://api.github.com/repos/actions/some-name/git/tags/af513c7a016048ae468971c52ed77d9562c7c819" + } + } + ] + """.trimIndent() + val headsResponse = + """ + [ + { + "ref":"refs/heads/v1", + "node_id":"MDM6UmVmMTk3ODE0NjI5OnJlZnMvaGVhZHMvdm1qb3NlcGgvc2lsZW50LXJldi1wYXJzZQ==", + "url":"https://api.github.com/repos/some-owner/some-name/git/refs/heads/v1", + "object": { + "sha":"af5130cb8882054eda385840657dcbd1e19ab8f4", + "type":"commit", + "url":"https://api.github.com/repos/some-owner/some-name/git/commits/af5130cb8882054eda385840657dcbd1e19ab8f4" + } + }, + { + "ref":"refs/heads/v2", + "node_id":"MDM6UmVmMTk3ODE0NjI5OnJlZnMvaGVhZHMvdm1qb3NlcGgvdG9vbGtpdC13aW5kb3dzLWV4ZWM=", + "url":"https://api.github.com/repos/some-owner/some-name/git/refs/heads/v2", + "object": { + "sha":"c22ccee38a13e34cb01a103c324adb1db665821e", + "type":"commit", + "url":"https://api.github.com/repos/some-owner/some-name/git/commits/c22ccee38a13e34cb01a103c324adb1db665821e" + } + }, + { + "ref":"refs/heads/virtual/branch", + "node_id":"MDM6UmVmMTk3ODE0NjI5OnJlZnMvaGVhZHMvdm1qb3NlcGgvdG9vbGtpdC13aW5kb3dzLWV4ZWM=", + "url":"https://api.github.com/repos/some-owner/some-name/git/refs/heads/virtual/branch", + "object": { + "sha":"c22ccee38a13e34cb01a103c324adb1db665821e", + "type":"commit", + "url":"https://api.github.com/repos/some-owner/some-name/git/commits/c22ccee38a13e34cb01a103c324adb1db665821e" + } + } + ] + """.trimIndent() + mockServer + .`when`(request().withPath("/repos/$owner/$name/git/matching-refs/tags/v")) + .respond( + response() + .withStatusCode(200) + .withHeader("Content-Type", "application/json") + .withBody(tagsResponse), + ) + mockServer + .`when`(request().withPath("/repos/$owner/$name/git/matching-refs/heads/v")) + .respond( + response() + .withStatusCode(200) + .withHeader("Content-Type", "application/json") + .withBody(headsResponse), + ) + + // When + val versionsOrError = + fetchAvailableVersions( + owner = owner, + name = name, + githubAuthToken = "token", + githubEndpoint = "http://localhost:${mockServer.port}", + ) + + // Then + versionsOrError shouldBe + listOf( + Version("v1.0.0"), + Version("v1.0.1"), + Version("v1"), + Version("v2"), + ).right() + } test("error occurs when fetching branches and tags") { // Given