Add a release-notes page linked from the footer version (v0.9.6)
Reconstructed from the commit history since the first production deployment; the initial entry is the 0.9.0 port of the legacy bash script to Kotlin/Spring Boot. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
d2b39c56d3
commit
428d1a06cb
+1
-1
@@ -11,7 +11,7 @@ plugins {
|
|||||||
group = "de.hoennig"
|
group = "de.hoennig"
|
||||||
// bump at least the patch version for every deployment, so the UI footer
|
// bump at least the patch version for every deployment, so the UI footer
|
||||||
// (BuildProperties) and --version identify what is actually running
|
// (BuildProperties) and --version identify what is actually running
|
||||||
version = "0.9.5"
|
version = "0.9.6"
|
||||||
|
|
||||||
java {
|
java {
|
||||||
toolchain {
|
toolchain {
|
||||||
|
|||||||
@@ -109,6 +109,13 @@ class UiController(
|
|||||||
return "current"
|
return "current"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Hand-maintained release notes (templates/releases.html); linked from the version in the footer. */
|
||||||
|
@GetMapping("/releases")
|
||||||
|
fun releases(model: Model): String {
|
||||||
|
baseModel(model, view = "releases", pageTitle = "Release Notes")
|
||||||
|
return "releases"
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/system")
|
@GetMapping("/system")
|
||||||
fun system(model: Model): String {
|
fun system(model: Model): String {
|
||||||
baseModel(model, view = "system", pageTitle = "System Metrics")
|
baseModel(model, view = "system", pageTitle = "System Metrics")
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer th:fragment="footer" class="site-footer">
|
<footer th:fragment="footer" class="site-footer">
|
||||||
<strong><em th:text="'GitTally v' + ${version}">GitTally</em></strong>
|
<strong><a href="/releases" title="Release notes"><em th:text="'GitTally v' + ${version}">GitTally</em></a></strong>
|
||||||
— © <a href="https://michael.hoennig.de" target="_blank" rel="noopener noreferrer">Michael Hönnig</a>, 2026
|
— © <a href="https://michael.hoennig.de" target="_blank" rel="noopener noreferrer">Michael Hönnig</a>, 2026
|
||||||
<th:block th:unless="${#strings.isEmpty(impressumUrl)}">
|
<th:block th:unless="${#strings.isEmpty(impressumUrl)}">
|
||||||
— <a th:href="${impressumUrl}" target="_blank" rel="noopener noreferrer">Impressum (Legal Disclosure)</a>
|
— <a th:href="${impressumUrl}" target="_blank" rel="noopener noreferrer">Impressum (Legal Disclosure)</a>
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org" lang="en">
|
||||||
|
<head th:replace="~{fragments :: head(${pageTitle})}"></head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
<h1 th:replace="~{fragments :: header(${pageTitle})}"></h1>
|
||||||
|
<div th:replace="~{fragments :: nav(${view})}"></div>
|
||||||
|
<div class="panel release-notes">
|
||||||
|
|
||||||
|
<h2>v0.9.6 <span class="muted">— 2026-08-10</span></h2>
|
||||||
|
<ul>
|
||||||
|
<li>This release-notes page, linked from the version in the footer.</li>
|
||||||
|
<li>Mobile: the live indicator collapses to a colored state dot so it no longer squeezes the menu.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>v0.9.5 <span class="muted">— 2026-08-10</span></h2>
|
||||||
|
<ul>
|
||||||
|
<li>Builds killed by a server shutdown (e.g. a deployment restart) are recorded as
|
||||||
|
<span class="status status-interrupted">interrupted</span> instead of
|
||||||
|
<span class="status status-failed">failed</span>, publish a <em>pending</em> Gitea status,
|
||||||
|
and are re-enqueued when the server starts again.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>v0.9.4 <span class="muted">— 2026-08-10</span></h2>
|
||||||
|
<ul>
|
||||||
|
<li>The legacy page names (<code>/index.html</code>, <code>/branches.html</code>, …) answer with
|
||||||
|
permanent redirects to the new routes, so pre-rewrite bookmarks and the redirect from the
|
||||||
|
old host keep working.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>v0.9.3 <span class="muted">— 2026-08-10</span></h2>
|
||||||
|
<ul>
|
||||||
|
<li>The artifact page shows a <span class="status status-failed">n failed</span> badge behind
|
||||||
|
links to test reports that contain failures.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>v0.9.2 <span class="muted">— 2026-08-10</span></h2>
|
||||||
|
<ul>
|
||||||
|
<li>Cancelling a build also terminates its auxiliary phases (Docker image build, Gradle cache
|
||||||
|
volume preparation), so the next queued build starts immediately.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>v0.9.1 <span class="muted">— 2026-08-10</span></h2>
|
||||||
|
<ul>
|
||||||
|
<li>Durations no longer flicker while live-updating.</li>
|
||||||
|
<li>While a build is running or pending, the artifact link shows an hourglass (logs only,
|
||||||
|
so far) instead of the report icon.</li>
|
||||||
|
<li>Pending builds show their queue wait time in italics; running and finished builds show
|
||||||
|
the pure build time without the wait.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>v0.9.0 <span class="muted">— 2026-08-10</span></h2>
|
||||||
|
<p>Port of the legacy <em>gitTally</em> bash script to Kotlin/Spring Boot — the first production
|
||||||
|
deployment of the rewrite.</p>
|
||||||
|
<ul>
|
||||||
|
<li>Dual-mode application: CLI (<code>init</code>, <code>status</code>, <code>build</code>,
|
||||||
|
<code>retry</code>, <code>config:print</code>) and HTTP server with this web UI and a JSON API.</li>
|
||||||
|
<li>Declarative YAML configuration: committed <code>.gittally.yml</code> plus machine-specific
|
||||||
|
overrides and secrets under <code>.git/gittally/</code>.</li>
|
||||||
|
<li>Builds run detached in git worktrees — the primary checkout is never used for builds.</li>
|
||||||
|
<li>Docker build containers with automatic image rebuilds and a per-repository Gradle cache volume;
|
||||||
|
works under rootless Docker daemons; git metadata is available read-only inside the container.</li>
|
||||||
|
<li>Branch watcher with auto-builds (nightly slots), a pull-request gate, and pruning of results,
|
||||||
|
artifacts, and stale worktrees.</li>
|
||||||
|
<li>Commit statuses reported to Gitea; artifact store with per-branch retention and permanent
|
||||||
|
latest-green links; system metrics page.</li>
|
||||||
|
<li>Managed nginx/TLS container (Let's Encrypt) for hosts without a reverse proxy;
|
||||||
|
<code>init --systemd</code> generates the service unit.</li>
|
||||||
|
<li>Self-contained runtime bundle (jlink-trimmed JRE + jar) for hosts without a Java runtime.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<footer th:replace="~{fragments :: footer}"></footer>
|
||||||
|
<script src="/gittally.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -286,6 +286,17 @@ class UiControllerTest : FunSpec() {
|
|||||||
.andExpect(header().string("Location", "/history"))
|
.andExpect(header().string("Location", "/history"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("release notes page renders the version history and the footer links to it") {
|
||||||
|
mockMvc
|
||||||
|
.perform(get("/releases"))
|
||||||
|
.andExpect(status().isOk)
|
||||||
|
.andExpect(content().string(containsString("Release Notes")))
|
||||||
|
.andExpect(content().string(containsString("v0.9.0")))
|
||||||
|
.andExpect(content().string(containsString("Kotlin/Spring Boot")))
|
||||||
|
// the footer version (rendered on every page) is the link to this page
|
||||||
|
.andExpect(content().string(containsString("""href="/releases"""")))
|
||||||
|
}
|
||||||
|
|
||||||
test("artifact index of a pruned build explains the missing artifacts") {
|
test("artifact index of a pruned build explains the missing artifacts") {
|
||||||
every { repository.history() } returns listOf(successResult)
|
every { repository.history() } returns listOf(successResult)
|
||||||
every { artifactStore.artifactDir("main-abc123-key") } returns null
|
every { artifactStore.artifactDir("main-abc123-key") } returns null
|
||||||
|
|||||||
Reference in New Issue
Block a user