feat(gitea): der Commit-Status verlinkt endlich die Artefaktseite — repo-bezogen
Der letzte offene Punkt der Sitzung D („Gitea status links use the repo-scoped URLs"). Beim Nachsehen war es kein Scoping-Problem, sondern ein fehlendes Feature: `server.publicBaseUrl` ist als „used for all links posted to Gitea" dokumentiert, der Executor postete aber `targetUrl = null` — es gab überhaupt keinen Link. Jetzt zeigt der Status auf die Artefaktseite des Builds, also auf die Logs, um die es geht. Ohne `publicBaseUrl` bleibt er null: ein relativer Link in einem Gitea-Status wäre schlimmer als keiner, er löste gegen die Forge auf. Die Präfix-Regel wohnt jetzt an einer Stelle (`RepoLinks`), weil drei dasselbe damit tun: die Seiten, die API-Antworten und diese Ziel-URLs — und eine dreimal ausgeschriebene Regel driftet. Die Slice-Tests binden die echte Komponente per @Import ein, statt die Regel im Test nachzubauen. Ein neuer Test (mit publicBaseUrl trägt der Status die Artefaktseite; die vorhandenen Tests halten fest, dass ohne sie weiterhin null gepostet wird). 499 Tests grün, ktlint sauber. Plan und Architektur-Skill nachgezogen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
91e1dd47a3
commit
80a14a7467
@@ -7,11 +7,14 @@ import de.hoennig.werkator.build.ProcessBuildRunner
|
||||
import de.hoennig.werkator.config.ConfigLoader
|
||||
import de.hoennig.werkator.gitea.GiteaClient
|
||||
import de.hoennig.werkator.repo.RepoContext
|
||||
import de.hoennig.werkator.repo.RepoLinks
|
||||
import de.hoennig.werkator.repo.RepoRegistry
|
||||
import io.kotest.assertions.nondeterministic.eventually
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.nulls.shouldNotBeNull
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.string.shouldContain
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import org.springframework.context.ApplicationEventPublisher
|
||||
import java.nio.file.Files
|
||||
@@ -42,6 +45,7 @@ class BuildExecutorArtifactIntegrationTest : FunSpec() {
|
||||
val executor =
|
||||
BuildExecutor(
|
||||
configLoader = ConfigLoader(),
|
||||
repoLinks = RepoLinks(mockk<RepoRegistry>().also { every { it.all() } returns listOf(repo) }),
|
||||
giteaClient = mockk<GiteaClient>(relaxed = true),
|
||||
buildRunner = ProcessBuildRunner(),
|
||||
workspaces = BranchWorkspaces { _, _, _ -> workspace },
|
||||
|
||||
@@ -3,6 +3,8 @@ package de.hoennig.werkator.build
|
||||
import de.hoennig.werkator.config.ConfigLoader
|
||||
import de.hoennig.werkator.gitea.GiteaClient
|
||||
import de.hoennig.werkator.repo.RepoContext
|
||||
import de.hoennig.werkator.repo.RepoLinks
|
||||
import de.hoennig.werkator.repo.RepoRegistry
|
||||
import io.kotest.assertions.nondeterministic.eventually
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.booleans.shouldBeFalse
|
||||
@@ -53,6 +55,7 @@ class BuildExecutorTest : FunSpec() {
|
||||
val executor =
|
||||
BuildExecutor(
|
||||
configLoader = ConfigLoader(),
|
||||
repoLinks = RepoLinks(mockk<RepoRegistry>().also { every { it.all() } returns listOf(repo) }),
|
||||
giteaClient = giteaClient,
|
||||
buildRunner = buildRunner,
|
||||
workspaces = workspaces,
|
||||
@@ -138,6 +141,35 @@ class BuildExecutorTest : FunSpec() {
|
||||
verify { h.artifactStore.persist(match { it.status == BuildStatus.SUCCESS }, build.stagingDir, h.workingDir) }
|
||||
}
|
||||
|
||||
test("the commit status carries the artifact page when a public base URL is configured") {
|
||||
val h =
|
||||
Harness(
|
||||
"""
|
||||
server:
|
||||
publicBaseUrl: https://ci.example.org/
|
||||
branches:
|
||||
default:
|
||||
buildCommand: "true"
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
val build = h.executor.startBuild(h.repo, "main", "abc123")
|
||||
|
||||
awaitStatus(h, "main", BuildStatus.SUCCESS)
|
||||
awaitIdle(h)
|
||||
// one served repository: the installation's existing URLs, no repository segment
|
||||
verify {
|
||||
h.giteaClient.publishStatus(
|
||||
"abc123",
|
||||
BuildStatus.SUCCESS,
|
||||
any(),
|
||||
"https://ci.example.org/builds/" + build.artifactKey,
|
||||
h.workingDir,
|
||||
any(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
test("build commands run in the workspace prepared for the branch") {
|
||||
val h = harness(buildCommand = "pwd", workspaceSubdir = "branch-workspace")
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import de.hoennig.werkator.build.BuildStatus
|
||||
import de.hoennig.werkator.build.RunningBuild
|
||||
import de.hoennig.werkator.git.GitService
|
||||
import de.hoennig.werkator.repo.RepoContext
|
||||
import de.hoennig.werkator.repo.RepoLinks
|
||||
import de.hoennig.werkator.repo.RepoRegistry
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.mockk.clearMocks
|
||||
@@ -17,6 +18,7 @@ import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest
|
||||
import org.springframework.context.annotation.Import
|
||||
import org.springframework.test.web.servlet.MockMvc
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
|
||||
@@ -29,6 +31,7 @@ import java.time.Duration
|
||||
import java.time.Instant
|
||||
|
||||
@WebMvcTest(BuildsApiController::class, properties = ["spring.main.web-application-type=servlet"])
|
||||
@Import(RepoLinks::class)
|
||||
class BuildsApiControllerTest : FunSpec() {
|
||||
private val tempDir: Path = Files.createTempDirectory("werkator-server-test")
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import de.hoennig.werkator.config.WerkatorConfig
|
||||
import de.hoennig.werkator.git.GitService
|
||||
import de.hoennig.werkator.metrics.SystemMetricsCollector
|
||||
import de.hoennig.werkator.repo.RepoContext
|
||||
import de.hoennig.werkator.repo.RepoLinks
|
||||
import de.hoennig.werkator.repo.RepoRegistry
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.mockk.clearMocks
|
||||
@@ -18,6 +19,7 @@ import io.mockk.every
|
||||
import org.hamcrest.Matchers.containsString
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest
|
||||
import org.springframework.context.annotation.Import
|
||||
import org.springframework.test.web.servlet.MockMvc
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
|
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content
|
||||
@@ -37,6 +39,7 @@ import java.time.Instant
|
||||
controllers = [UiController::class, ArtifactFileController::class],
|
||||
properties = ["spring.main.web-application-type=servlet"],
|
||||
)
|
||||
@Import(RepoLinks::class)
|
||||
class PermanentBranchRoutesTest : FunSpec() {
|
||||
@Autowired
|
||||
lateinit var mockMvc: MockMvc
|
||||
|
||||
@@ -18,6 +18,7 @@ import de.hoennig.werkator.metrics.MetricAggregate
|
||||
import de.hoennig.werkator.metrics.SystemMetrics
|
||||
import de.hoennig.werkator.metrics.SystemMetricsCollector
|
||||
import de.hoennig.werkator.repo.RepoContext
|
||||
import de.hoennig.werkator.repo.RepoLinks
|
||||
import de.hoennig.werkator.repo.RepoRegistry
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
@@ -30,6 +31,7 @@ import org.hamcrest.Matchers.containsString
|
||||
import org.hamcrest.Matchers.not
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest
|
||||
import org.springframework.context.annotation.Import
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.test.web.servlet.MockMvc
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
|
||||
@@ -44,6 +46,7 @@ import java.time.Duration
|
||||
import java.time.Instant
|
||||
|
||||
@WebMvcTest(UiController::class, properties = ["spring.main.web-application-type=servlet"])
|
||||
@Import(RepoLinks::class)
|
||||
class UiControllerTest : FunSpec() {
|
||||
private val tempDir: Path = Files.createTempDirectory("werkator-ui-test")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user