From eb49387c97400dbe8d3ce3798192372bdd086b08 Mon Sep 17 00:00:00 2001 From: mhoennig Date: Mon, 10 Aug 2026 16:55:11 +0200 Subject: [PATCH] Redirect legacy page names to the new routes (v0.9.4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The retired legacy instance now blanket-redirects its old host to the new one, so pre-rewrite deep links like /index.html or /branches.html arrive here — they answer 301 to the new routes instead of 404; about/license had no successor pages and land on the start page. Co-Authored-By: Claude Fable 5 --- build.gradle.kts | 2 +- .../hoennig/gittally/server/UiController.kt | 23 +++++++++++++++++++ .../gittally/server/UiControllerTest.kt | 16 +++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 14524ee..a88b126 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,7 +11,7 @@ plugins { group = "de.hoennig" // bump at least the patch version for every deployment, so the UI footer // (BuildProperties) and --version identify what is actually running -version = "0.9.3" +version = "0.9.4" java { toolchain { diff --git a/src/main/kotlin/de/hoennig/gittally/server/UiController.kt b/src/main/kotlin/de/hoennig/gittally/server/UiController.kt index 934f2d3..731b879 100644 --- a/src/main/kotlin/de/hoennig/gittally/server/UiController.kt +++ b/src/main/kotlin/de/hoennig/gittally/server/UiController.kt @@ -7,6 +7,7 @@ import de.hoennig.gittally.build.BuildResultRepository import de.hoennig.gittally.build.BuildStatus import de.hoennig.gittally.config.ConfigLoader import de.hoennig.gittally.metrics.SystemMetricsCollector +import jakarta.servlet.http.HttpServletRequest import org.springframework.beans.factory.ObjectProvider import org.springframework.boot.info.BuildProperties import org.springframework.http.HttpStatus @@ -15,6 +16,7 @@ import org.springframework.ui.Model import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.server.ResponseStatusException +import org.springframework.web.servlet.view.RedirectView import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths @@ -41,6 +43,16 @@ class UiController( ) { var workingDir: Path = Paths.get(".") + /** + * Permanent redirects for the legacy script's static page names, so bookmarks + * and links from before the rewrite (e.g. via the old host's redirect) keep working. + */ + @GetMapping("/index.html", "/branches.html", "/history.html", "/system.html", "/about.html", "/license.html") + fun legacyPageName(request: HttpServletRequest): RedirectView = + RedirectView(LEGACY_PAGE_TARGETS.getValue(request.requestURI)).apply { + setStatusCode(HttpStatus.MOVED_PERMANENTLY) + } + @GetMapping("/") fun latest(model: Model): String { val links = baseModel(model, view = "latest", pageTitle = "Latest Builds") @@ -256,5 +268,16 @@ class UiController( companion object { private val FAILURES_COUNTER = Regex("""id="failures">\s*
(\d+)""") + + /** Legacy page name → new route; about/license had no successor pages and land on the start page. */ + private val LEGACY_PAGE_TARGETS = + mapOf( + "/index.html" to "/", + "/branches.html" to "/branches", + "/history.html" to "/history", + "/system.html" to "/system", + "/about.html" to "/", + "/license.html" to "/", + ) } } diff --git a/src/test/kotlin/de/hoennig/gittally/server/UiControllerTest.kt b/src/test/kotlin/de/hoennig/gittally/server/UiControllerTest.kt index 6c68404..cc90f9b 100644 --- a/src/test/kotlin/de/hoennig/gittally/server/UiControllerTest.kt +++ b/src/test/kotlin/de/hoennig/gittally/server/UiControllerTest.kt @@ -28,6 +28,7 @@ import org.springframework.http.HttpStatus 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 +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.header import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status import org.springframework.web.server.ResponseStatusException import java.nio.file.Files @@ -270,6 +271,21 @@ class UiControllerTest : FunSpec() { Regex(""" failed""").findAll(page).count() shouldBe 1 } + test("legacy page names redirect permanently to the new routes") { + mockMvc + .perform(get("/index.html")) + .andExpect(status().isMovedPermanently) + .andExpect(header().string("Location", "/")) + mockMvc + .perform(get("/branches.html")) + .andExpect(status().isMovedPermanently) + .andExpect(header().string("Location", "/branches")) + mockMvc + .perform(get("/history.html")) + .andExpect(status().isMovedPermanently) + .andExpect(header().string("Location", "/history")) + } + test("artifact index of a pruned build explains the missing artifacts") { every { repository.history() } returns listOf(successResult) every { artifactStore.artifactDir("main-abc123-key") } returns null