feat: centralize version in internal/version package, fix updater for pre-release tags, show version in footer

This commit is contained in:
2026-04-08 21:10:07 +02:00
parent ca402eb88e
commit 1cf7f50bfb
6 changed files with 44 additions and 14 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ RUN go mod download
COPY . .
ARG VERSION=dev
RUN CGO_ENABLED=1 GOOS=linux go build -o keywarden -ldflags="-s -w -X main.Version=${VERSION}" ./cmd/keywarden/
RUN CGO_ENABLED=1 GOOS=linux go build -o keywarden -ldflags="-s -w -X git.techniverse.net/scriptos/keywarden/internal/version.Version=${VERSION}" ./cmd/keywarden/
# Stage 2: Runtime
FROM alpine:3.21
+4 -10
View File
@@ -25,17 +25,11 @@ import (
"git.techniverse.net/scriptos/keywarden/internal/security"
"git.techniverse.net/scriptos/keywarden/internal/servers"
"git.techniverse.net/scriptos/keywarden/internal/updater"
"git.techniverse.net/scriptos/keywarden/internal/version"
"git.techniverse.net/scriptos/keywarden/internal/worker"
"git.techniverse.net/scriptos/keywarden/web"
)
// Version is set at build time via -ldflags:
//
// go build -ldflags "-X main.Version=v1.0.0" ./cmd/keywarden/
//
// When building with Docker, pass --build-arg VERSION=v1.0.0
var Version = "dev"
func main() {
// Handle CLI subcommands before starting the server
if len(os.Args) > 1 {
@@ -55,7 +49,7 @@ func main() {
// Initialize structured logging
logging.Init(cfg.LogLevel)
logging.Info("🔑 Keywarden %s - Centralized SSH Key Management and Deployment", Version)
logging.Info("🔑 Keywarden %s - Centralized SSH Key Management and Deployment", version.Version)
logging.Info(" https://git.techniverse.net/scriptos/keywarden")
// Validate data paths relative paths inside a container bypass the
@@ -126,7 +120,7 @@ func main() {
}
// Initialize update checker
updaterSvc := updater.NewService(Version)
updaterSvc := updater.NewService(version.Version)
// Setup HTTP handlers
handler := handlers.New(authSvc, keysSvc, serversSvc, deploySvc, auditSvc, cronSvc, workerSvc, mailSvc, db, web.TemplateFS, web.StaticFS, cfg.DataDir, cfg.SecureCookies, cfg.BaseURL, updaterSvc)
@@ -293,7 +287,7 @@ func handleResetPassword(args []string) {
// printUsage displays available CLI subcommands
func printUsage() {
fmt.Printf("Keywarden %s - Centralized SSH Key Management and Deployment\n", Version)
fmt.Printf("Keywarden %s - Centralized SSH Key Management and Deployment\n", version.Version)
fmt.Println()
fmt.Println("Usage:")
fmt.Println(" keywarden Start the server")
+1 -1
View File
@@ -43,7 +43,7 @@ go mod download
CGO_ENABLED=1 go build -o keywarden ./cmd/keywarden/
# Build with version (optional, enables update checker)
CGO_ENABLED=1 go build -ldflags="-X 'main.Version=v1.0.0'" -o keywarden ./cmd/keywarden/
CGO_ENABLED=1 go build -ldflags="-X 'git.techniverse.net/scriptos/keywarden/internal/version.Version=v1.0.0'" -o keywarden ./cmd/keywarden/
# Run
./keywarden
+23 -1
View File
@@ -155,6 +155,8 @@ func (s *Service) check() {
// isNewer returns true if latest is a higher version than current.
// Both may optionally have a "v" prefix (e.g. "v1.2.3").
// Pre-release versions (e.g. "v1.0.0-alpha") are considered older than the
// same version without a suffix (e.g. "v1.0.0").
func isNewer(latest, current string) bool {
latestParts := parseVersion(latest)
currentParts := parseVersion(current)
@@ -174,12 +176,25 @@ func isNewer(latest, current string) bool {
return false
}
}
// Numeric parts are equal a stable release is newer than a pre-release
// of the same version (e.g. v0.3.0 > v0.3.0-alpha).
if hasPreRelease(current) && !hasPreRelease(latest) {
return true
}
return false
}
// parseVersion strips the "v" prefix and splits "1.2.3" into [1, 2, 3].
// parseVersion strips the "v" prefix and pre-release suffixes (e.g. "-alpha")
// then splits "1.2.3" into [1, 2, 3].
// A pre-release version is indicated by returning isPreRelease = true.
func parseVersion(v string) []int {
v = strings.TrimPrefix(v, "v")
// Strip pre-release suffix (e.g. "-alpha", "-beta.1", "-rc1")
if idx := strings.IndexByte(v, '-'); idx >= 0 {
v = v[:idx]
}
parts := strings.Split(v, ".")
nums := make([]int, 0, len(parts))
for _, p := range parts {
@@ -191,3 +206,10 @@ func parseVersion(v string) []int {
}
return nums
}
// hasPreRelease returns true when the version string contains a pre-release
// suffix (e.g. "-alpha", "-beta", "-rc1").
func hasPreRelease(v string) bool {
v = strings.TrimPrefix(v, "v")
return strings.ContainsRune(v, '-')
}
+14
View File
@@ -0,0 +1,14 @@
// Keywarden - Centralized SSH Key Management and Deployment
// Copyright (C) 2026 Patrick Asmus (scriptos)
// SPDX-License-Identifier: AGPL-3.0-or-later
package version
// Version is the current application version.
// This is the SINGLE SOURCE OF TRUTH for the version number.
// Update this value for each release.
//
// It can still be overridden at build time via:
//
// go build -ldflags "-X git.techniverse.net/scriptos/keywarden/internal/version.Version=v1.0.0"
var Version = "v0.3.0-alpha"
+1 -1
View File
@@ -793,7 +793,7 @@
<div class="container-xl">
<div class="row text-center align-items-center">
<div class="col-12">
<span class="text-secondary">&copy; 2026 Keywarden Centralized SSH Key Management and Deployment | AGPLv3</span>
<span class="text-secondary">&copy; 2026 Keywarden Centralized SSH Key Management and Deployment | AGPLv3 | {{appVersion}}{{if updateAvailable}} · <a href="{{releaseURL}}" target="_blank" rel="noopener noreferrer" class="text-warning" title="Update verfügbar"><i class="ti ti-download"></i> {{latestVersion}} verfügbar</a>{{end}}</span>
</div>
</div>
</div>