From 3bdf6665c233f7ea0e936ccc1253f47e2df147c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Mon, 27 Jul 2026 17:55:36 +0200 Subject: [PATCH] fix: make orchestrator -version never print empty output (#109) Plain `go build` left AppVersion/GitCommit unset (only build.sh ldflags filled them), so `-version` printed blank lines. Default to RELEASE_VERSION (marked devel when unset), skip empty GitCommit lines, align script/build ldflags with main.GitCommit, and add tests so defaultAppVersion stays in sync with RELEASE_VERSION. --- go/cmd/orchestrator/main.go | 35 ++++++++++++--- go/cmd/orchestrator/version_test.go | 67 +++++++++++++++++++++++++++++ script/build | 10 +++-- 3 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 go/cmd/orchestrator/version_test.go diff --git a/go/cmd/orchestrator/main.go b/go/cmd/orchestrator/main.go index 0347fee1..e392681d 100644 --- a/go/cmd/orchestrator/main.go +++ b/go/cmd/orchestrator/main.go @@ -30,8 +30,29 @@ import ( _ "github.com/mattn/go-sqlite3" ) +// AppVersion and GitCommit are normally injected via -ldflags by build.sh / script/build. +// When building with plain `go build` they are empty; defaultAppVersion (kept in sync with +// RELEASE_VERSION) is used so `orchestrator -version` is never blank (#109). var AppVersion, GitCommit string +// defaultAppVersion must match the contents of the repo-root RELEASE_VERSION file. +const defaultAppVersion = "4.30.0" + +func resolvedAppVersion() string { + if AppVersion != "" { + return AppVersion + } + return defaultAppVersion +} + +func versionOutput() string { + if AppVersion != "" { + return AppVersion + } + // Plain `go build` without -ldflags: still report the tree version, marked devel. + return defaultAppVersion + " (devel)" +} + // main is the application's entry point. It will either spawn a CLI or HTTP interfaces. func main() { configFile := flag.String("config", "", "config file name") @@ -95,15 +116,19 @@ func main() { log.SetPrintStackTrace(*stack) } if *config.RuntimeCLIFlags.Version { - fmt.Println(AppVersion) - fmt.Println(GitCommit) + fmt.Println(versionOutput()) + if GitCommit != "" { + fmt.Println(GitCommit) + } return } - startText := "starting orchestrator" - if AppVersion != "" { - startText += ", version: " + AppVersion + // Ensure runtime always has a non-empty version (API/status, backend deploy checks). + if AppVersion == "" { + AppVersion = resolvedAppVersion() } + + startText := "starting orchestrator, version: " + AppVersion if GitCommit != "" { startText += ", git commit: " + GitCommit } diff --git a/go/cmd/orchestrator/version_test.go b/go/cmd/orchestrator/version_test.go new file mode 100644 index 00000000..814a7263 --- /dev/null +++ b/go/cmd/orchestrator/version_test.go @@ -0,0 +1,67 @@ +/* + Copyright 2014 Outbrain Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package main + +import ( + "os" + "path/filepath" + "strings" + "testing" +) + +func TestDefaultAppVersionMatchesReleaseFile(t *testing.T) { + // Walk up from this test file's package dir to the repo root. + dir, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + var release string + for { + b, err := os.ReadFile(filepath.Join(dir, "RELEASE_VERSION")) + if err == nil { + release = strings.TrimSpace(string(b)) + break + } + parent := filepath.Dir(dir) + if parent == dir { + t.Fatal("RELEASE_VERSION not found") + } + dir = parent + } + if release != defaultAppVersion { + t.Fatalf("defaultAppVersion %q must match RELEASE_VERSION %q", defaultAppVersion, release) + } +} + +func TestVersionOutputNeverEmpty(t *testing.T) { + saved := AppVersion + defer func() { AppVersion = saved }() + + AppVersion = "" + out := versionOutput() + if strings.TrimSpace(out) == "" { + t.Fatal("versionOutput empty when AppVersion unset") + } + if !strings.Contains(out, defaultAppVersion) { + t.Fatalf("versionOutput %q missing defaultAppVersion", out) + } + + AppVersion = "9.9.9" + if versionOutput() != "9.9.9" { + t.Fatalf("versionOutput should prefer ldflags AppVersion, got %q", versionOutput()) + } +} diff --git a/script/build b/script/build index 2cf50b93..c9e94564 100755 --- a/script/build +++ b/script/build @@ -12,9 +12,13 @@ cd "$(dirname "$0")/.." mkdir -p bin bindir="$PWD"/bin -version=$(git rev-parse HEAD) -describe=$(git describe --tags --always --dirty) +commit=$(git rev-parse HEAD) +if [ -f RELEASE_VERSION ]; then + version=$(tr -d '[:space:]' < RELEASE_VERSION) +else + version=$(git describe --tags --always --dirty) +fi -go build -o "$bindir/orchestrator" -ldflags "-X main.AppVersion=${version} -X main.BuildDescribe=${describe}" ./go/cmd/orchestrator/main.go +go build -o "$bindir/orchestrator" -ldflags "-X main.AppVersion=${version} -X main.GitCommit=${commit}" ./go/cmd/orchestrator/main.go rsync -qa ./resources $bindir/