From 17e837b1960657672faa667f4b5a6f20c8fee7ab Mon Sep 17 00:00:00 2001 From: Rongsong Shen Date: Thu, 20 Aug 2026 13:47:03 +0000 Subject: [PATCH] feat(build-time-versioning): apiserver -version flag and startup log Declares GitCommit/BuildTime package vars (default "unknown", target of task 4.1's -ldflags -X injection), a -version flag checked before utils.PromptForTopDir()/InitLogger() (zero filesystem side effects), and extends the existing "Initialize Logger done!" startup log line with zap.String structured fields carrying both values, per design.md's explicit mandate. Live-verified end to end: -version output and the startup log's first line are byte-identical, with a real commit id (matching git rev-parse --short HEAD plus dirty suffix) and UTC timestamp -- the first full round-trip proof in this spec (earlier Go tasks could only verify via linked build-info metadata, since no consuming vars existed yet). Task 4.4/13 of build-time-versioning. Co-Authored-By: Claude Sonnet 5 --- .kiro/specs/build-time-versioning/tasks.md | 9 ++++---- src/frontend/apiserver/cmd/main.go | 26 +++++++++++++++++++++- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/.kiro/specs/build-time-versioning/tasks.md b/.kiro/specs/build-time-versioning/tasks.md index 76d66219..4227b703 100644 --- a/.kiro/specs/build-time-versioning/tasks.md +++ b/.kiro/specs/build-time-versioning/tasks.md @@ -73,11 +73,10 @@ - _Boundary: Makefile_ - _Depends: 4.1_ -- [ ] 4.4 (P) apiserver: version flag, vars, and startup log - - Declare `GitCommit`/`BuildTime` package vars (default `unknown`) in `src/frontend/apiserver/cmd/main.go` - - Add a `-version` flag, checked before `utils.InitLogger()`, that prints both values and exits with no logging side effects - - Extend the existing `logger.Info("********** Initialize Logger done!")` call site to also log both values - - Observable: `xce_apiserver -version` prints both values and exits without starting the server; the startup log's first lines include the identical two values +- [x] 4.4 (P) apiserver: version flag, vars, and startup log + - `GitCommit`/`BuildTime` package vars (default `unknown`); `-version` flag checked before `utils.PromptForTopDir`/`utils.InitLogger()`, zero filesystem side effects (live-verified: no logs dir created) + - Startup log extended via `zap.String("gitCommit", ...)`/`zap.String("buildTime", ...)` structured fields on the existing `"Initialize Logger done!"` line, per design.md's explicit mandate + - Observable confirmed live (independently re-verified by review, full round trip): `-version` and the startup log's first line are byte-identical (`45c9b026-dirty`, matching `git rev-parse --short HEAD` + dirty suffix, and a real UTC timestamp) - _Requirements: 1.1, 1.2, 2.1, 2.2, 3.1, 3.2_ - _Boundary: apiserver/cmd/main.go_ - _Depends: 4.1_ diff --git a/src/frontend/apiserver/cmd/main.go b/src/frontend/apiserver/cmd/main.go index 65b53196..0e8c847e 100644 --- a/src/frontend/apiserver/cmd/main.go +++ b/src/frontend/apiserver/cmd/main.go @@ -21,12 +21,26 @@ import ( "go.uber.org/zap" ) +// GitCommit and BuildTime are injected at link time via +// `-ldflags "-X main.GitCommit=... -X main.BuildTime=..."` (see +// src/tools/go_build and src/frontend/Makefile's build-server target). The +// "unknown" defaults matter: a bare `go build`/`go run` that bypasses that +// ldflags injection must still report "unknown" rather than an empty +// string, matching this feature's unknown-fallback requirement (see +// xce_version_field() in src/lib/utils.c for the equivalent C-side +// convention). +var ( + GitCommit = "unknown" + BuildTime = "unknown" +) + func main() { gin.SetMode(gin.ReleaseMode) gin.DefaultWriter = io.Discard gin.DefaultErrorWriter = io.Discard topDir := flag.String("d", "", "Top directory (default: current directory)") + versionFlag := flag.Bool("version", false, "Print version information and exit") flag.Usage = func() { fmt.Fprintln(os.Stderr, ` Usage: apiserver -d @@ -35,12 +49,22 @@ func main() { } flag.Parse() + // Checked before utils.InitLogger() runs so -version has no logging + // side effects: it must only print and exit, matching controller's/ + // scheduler's/worker's own --version contract (Requirement 2.1). + if *versionFlag { + fmt.Printf("xce-apiserver %s built %s\n", GitCommit, BuildTime) + return + } + utils.Global_TopDir = utils.PromptForTopDir(topDir) if err := utils.InitLogger(); err != nil { os.Exit(1) } - logger.Info("********** Initialize Logger done!") + logger.Info("********** Initialize Logger done!", + zap.String("gitCommit", GitCommit), + zap.String("buildTime", BuildTime)) if err := utils.InitConf(); err != nil { logger.Error("Failed to initialize configuration files", zap.Error(err))