Merged in feature/log-version (pull request #185)
inject and print version at startup for all services * inject and print version * coverage
This commit is contained in:
+2
-1
@@ -33,13 +33,14 @@ ENV CC=musl-gcc
|
||||
|
||||
ARG GIT_VERSION=dev
|
||||
ARG GIT_COMMIT=unknown
|
||||
ARG BUILD_TIME=unknown
|
||||
|
||||
RUN go build \
|
||||
-mod vendor \
|
||||
-tags musl \
|
||||
-trimpath \
|
||||
-installsuffix cgo \
|
||||
-ldflags "-s -w -linkmode external -extldflags '-static -Wl,--as-needed -Wl,--gc-sections -Wl,-O1' -X main.version=${GIT_VERSION} -X main.gitCommit=${GIT_COMMIT}" \
|
||||
-ldflags "-s -w -linkmode external -extldflags '-static -Wl,--as-needed -Wl,--gc-sections -Wl,-O1' -X queryorchestration/internal/serviceconfig/build.version=${GIT_VERSION} -X queryorchestration/internal/serviceconfig/build.gitCommit=${GIT_COMMIT} -X queryorchestration/internal/serviceconfig/build.buildTime=${BUILD_TIME}" \
|
||||
-o bin/ ./cmd/...
|
||||
|
||||
FROM scratch AS final
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
clientsyncrunner "queryorchestration/api/clientSyncRunner"
|
||||
clientsync "queryorchestration/internal/client/sync"
|
||||
"queryorchestration/internal/server/runner"
|
||||
"queryorchestration/internal/serviceconfig/build"
|
||||
"queryorchestration/internal/serviceconfig/queue/documentsync"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
@@ -24,6 +25,9 @@ type ClientSyncConfig struct {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Print version information before any environment checks
|
||||
build.PrintVersionInfo("clientSyncRunner")
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
cfg := &ClientSyncConfig{}
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
doccleanrunner "queryorchestration/api/docCleanRunner"
|
||||
documentclean "queryorchestration/internal/document/clean"
|
||||
"queryorchestration/internal/server/runner"
|
||||
"queryorchestration/internal/serviceconfig/build"
|
||||
"queryorchestration/internal/serviceconfig/objectstore"
|
||||
"queryorchestration/internal/serviceconfig/queue/documenttext"
|
||||
|
||||
@@ -28,6 +29,9 @@ type DocCleanConfig struct {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Print version information before any environment checks
|
||||
build.PrintVersionInfo("docCleanRunner")
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
cfg := &DocCleanConfig{}
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
docinitrunner "queryorchestration/api/docInitRunner"
|
||||
documentinit "queryorchestration/internal/document/init"
|
||||
"queryorchestration/internal/server/runner"
|
||||
"queryorchestration/internal/serviceconfig/build"
|
||||
documentsyncc "queryorchestration/internal/serviceconfig/queue/documentsync"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
@@ -34,6 +35,9 @@ type DocInitConfig struct {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Print version information before any environment checks
|
||||
build.PrintVersionInfo("docInitRunner")
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
cfg := &DocInitConfig{}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"queryorchestration/internal/document"
|
||||
documentsync "queryorchestration/internal/document/sync"
|
||||
"queryorchestration/internal/server/runner"
|
||||
"queryorchestration/internal/serviceconfig/build"
|
||||
documentcleanc "queryorchestration/internal/serviceconfig/queue/documentclean"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
@@ -30,6 +31,9 @@ type DocSyncConfig struct {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Print version information before any environment checks
|
||||
build.PrintVersionInfo("docSyncRunner")
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
cfg := &DocSyncConfig{}
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
doctextrunner "queryorchestration/api/docTextRunner"
|
||||
documenttext "queryorchestration/internal/document/text"
|
||||
"queryorchestration/internal/server/runner"
|
||||
"queryorchestration/internal/serviceconfig/build"
|
||||
"queryorchestration/internal/serviceconfig/objectstore"
|
||||
"queryorchestration/internal/serviceconfig/queue/querysync"
|
||||
"queryorchestration/internal/serviceconfig/textract"
|
||||
@@ -30,6 +31,9 @@ type DocTextConfig struct {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Print version information before any environment checks
|
||||
build.PrintVersionInfo("docTextRunner")
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
cfg := &DocTextConfig{}
|
||||
|
||||
@@ -5,9 +5,14 @@ import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"queryorchestration/internal/serviceconfig/build"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Print version information before any environment checks
|
||||
build.PrintVersionInfo("healthcheck")
|
||||
|
||||
err := check()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
"queryorchestration/internal/query/result"
|
||||
"queryorchestration/internal/server/api"
|
||||
"queryorchestration/internal/serviceconfig"
|
||||
"queryorchestration/internal/serviceconfig/build"
|
||||
"queryorchestration/internal/serviceconfig/objectstore"
|
||||
"queryorchestration/internal/serviceconfig/queue/clientsync"
|
||||
"queryorchestration/internal/serviceconfig/queue/queryversionsync"
|
||||
@@ -57,6 +58,9 @@ type QueryAPIConfig struct {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Print version information before any environment checks
|
||||
build.PrintVersionInfo("queryAPI")
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
cfg := &QueryAPIConfig{}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
resultset "queryorchestration/internal/query/result/set"
|
||||
resultsync "queryorchestration/internal/query/result/sync"
|
||||
"queryorchestration/internal/server/runner"
|
||||
"queryorchestration/internal/serviceconfig/build"
|
||||
queryc "queryorchestration/internal/serviceconfig/queue/query"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
@@ -29,6 +30,9 @@ type QueryConfig struct {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Print version information before any environment checks
|
||||
build.PrintVersionInfo("queryRunner")
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
cfg := &QueryConfig{}
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
resultsync "queryorchestration/internal/query/result/sync"
|
||||
querysync "queryorchestration/internal/query/sync"
|
||||
"queryorchestration/internal/server/runner"
|
||||
"queryorchestration/internal/serviceconfig/build"
|
||||
queryc "queryorchestration/internal/serviceconfig/queue/query"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
@@ -35,6 +36,9 @@ type QuerySyncConfig struct {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Print version information before any environment checks
|
||||
build.PrintVersionInfo("querySyncRunner")
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
cfg := &QuerySyncConfig{}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
queryversionsyncrunner "queryorchestration/api/queryVersionSyncRunner"
|
||||
queryversionsync "queryorchestration/internal/query/versionsync"
|
||||
"queryorchestration/internal/server/runner"
|
||||
"queryorchestration/internal/serviceconfig/build"
|
||||
"queryorchestration/internal/serviceconfig/queue/clientsync"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
@@ -24,6 +25,9 @@ type QueryVersionSyncConfig struct {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Print version information before any environment checks
|
||||
build.PrintVersionInfo("queryVersionSyncRunner")
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
cfg := &QueryVersionSyncConfig{}
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
storeeventrunner "queryorchestration/api/storeEventRunner"
|
||||
documentstore "queryorchestration/internal/document/store"
|
||||
"queryorchestration/internal/server/runner"
|
||||
"queryorchestration/internal/serviceconfig/build"
|
||||
"queryorchestration/internal/serviceconfig/queue/documentinit"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
@@ -26,6 +27,9 @@ type StoreEventConfig struct {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Print version information before any environment checks
|
||||
build.PrintVersionInfo("storeEventRunner")
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
cfg := &StoreEventConfig{}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"queryorchestration/internal/serviceconfig"
|
||||
"queryorchestration/internal/serviceconfig/aws"
|
||||
"queryorchestration/internal/serviceconfig/build"
|
||||
"queryorchestration/internal/serviceconfig/objectstore"
|
||||
"queryorchestration/internal/serviceconfig/queue/querysync"
|
||||
"queryorchestration/internal/serviceconfig/textract"
|
||||
@@ -27,6 +28,9 @@ type Config struct {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Print version information before any environment checks
|
||||
build.PrintVersionInfo("textExtractor")
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
directory := "files/"
|
||||
|
||||
@@ -45,7 +45,10 @@ func New(ctx context.Context, cfg Config) (func() error, error) {
|
||||
|
||||
version := build.GetVersion()
|
||||
if cfg.GetLogger() != nil {
|
||||
cfg.GetLogger().Info("Starting", "version", version)
|
||||
cfg.GetLogger().Info("Starting",
|
||||
"version", version,
|
||||
"buildTime", build.GetBuildTime(),
|
||||
"commit", build.GetGitCommit())
|
||||
}
|
||||
|
||||
err := database.RunMigrations(ctx, cfg)
|
||||
|
||||
@@ -2,6 +2,7 @@ package build
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -11,6 +12,13 @@ const (
|
||||
SystemName = "doczy"
|
||||
)
|
||||
|
||||
// These variables will be set via ldflags during build
|
||||
var (
|
||||
version = "(devel)"
|
||||
gitCommit = "unknown"
|
||||
buildTime = "unknown"
|
||||
)
|
||||
|
||||
func IsValidUnixVersion(v int64) error {
|
||||
currentVersion := GetVersionUnixTimestamp()
|
||||
|
||||
@@ -60,8 +68,9 @@ func GetVersionUnixTimestamp() int64 {
|
||||
return GetVersionTimestamp().UnixMilli()
|
||||
}
|
||||
|
||||
// GetVersion returns the version of the application in the Golang build info format.
|
||||
// This is a raw format and will change depending on the build environment and the git tags.
|
||||
// GetVersion returns the version of the application.
|
||||
// It first checks if a version was set via ldflags during build.
|
||||
// If not set via ldflags, it falls back to the Golang build info format.
|
||||
// When building from a commit with an associated Git tag (e.g., v1.2.3),
|
||||
//
|
||||
// the runtime version uses the tag name without a timestamp.
|
||||
@@ -72,9 +81,44 @@ func GetVersionUnixTimestamp() int64 {
|
||||
//
|
||||
// An example of a version v0.0.2-0.20250310175756-a91372dc0602+dirty.
|
||||
func GetVersion() string {
|
||||
// Check if version was set via ldflags
|
||||
if version != "" && version != "(devel)" {
|
||||
return version
|
||||
}
|
||||
|
||||
// Fall back to debug.ReadBuildInfo
|
||||
info, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
return "unknown"
|
||||
}
|
||||
return info.Main.Version
|
||||
}
|
||||
|
||||
// GetGitCommit returns the git commit hash set during build.
|
||||
// Returns "unknown" if not set via ldflags.
|
||||
func GetGitCommit() string {
|
||||
return gitCommit
|
||||
}
|
||||
|
||||
// GetBuildTime returns the build time set during build.
|
||||
// Returns "unknown" if not set via ldflags.
|
||||
func GetBuildTime() string {
|
||||
return buildTime
|
||||
}
|
||||
|
||||
// PrintVersionInfo prints version information to stderr.
|
||||
// This should be called at the very beginning of main() before any environment checks.
|
||||
// It prints to stderr to ensure output even if stdout is redirected or logging isn't initialized.
|
||||
// Format: Starting <service> version=<version> buildTime=<buildTime> commit=<commit>
|
||||
func PrintVersionInfo(serviceName string) {
|
||||
// If version already contains timestamp and commit (format: YYYYMMDD.HHMMSS-commit),
|
||||
// just use that. Otherwise, construct from parts.
|
||||
if version != "(devel)" && version != "" {
|
||||
fmt.Fprintf(os.Stderr, "Starting %s version=%s buildTime=%s commit=%s\n",
|
||||
serviceName, version, buildTime, gitCommit)
|
||||
} else {
|
||||
// Fallback format when not built via Docker
|
||||
fmt.Fprintf(os.Stderr, "Starting %s version=%s commit=%s\n",
|
||||
serviceName, GetVersion(), GetGitCommit())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -129,3 +132,125 @@ func TestGetVersion(t *testing.T) {
|
||||
t.Errorf("Version not consistent between calls: '%s' != '%s'", version, version2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetGitCommit(t *testing.T) {
|
||||
// Test that GetGitCommit returns a non-empty string
|
||||
commit := GetGitCommit()
|
||||
if commit == "" {
|
||||
t.Error("Git commit should not be empty")
|
||||
}
|
||||
|
||||
// In test environment, it should return the default value
|
||||
if commit != "unknown" && commit != gitCommit {
|
||||
t.Errorf("Unexpected commit value: %s", commit)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetBuildTime(t *testing.T) {
|
||||
// Test that GetBuildTime returns a non-empty string
|
||||
bt := GetBuildTime()
|
||||
if bt == "" {
|
||||
t.Error("Build time should not be empty")
|
||||
}
|
||||
|
||||
// In test environment, it should return the default value
|
||||
if bt != "unknown" && bt != buildTime {
|
||||
t.Errorf("Unexpected build time value: %s", bt)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrintVersionInfo(t *testing.T) {
|
||||
// Save original stderr
|
||||
oldStderr := os.Stderr
|
||||
defer func() { os.Stderr = oldStderr }()
|
||||
|
||||
// Create a pipe to capture stderr
|
||||
r, w, _ := os.Pipe()
|
||||
os.Stderr = w
|
||||
|
||||
// Test 1: PrintVersionInfo with default values (devel)
|
||||
t.Run("with devel version", func(t *testing.T) {
|
||||
// Save original values
|
||||
originalVersion := version
|
||||
originalCommit := gitCommit
|
||||
originalBuildTime := buildTime
|
||||
|
||||
// Set test values
|
||||
version = "(devel)"
|
||||
gitCommit = "testcommit"
|
||||
buildTime = "testtime"
|
||||
|
||||
// Call PrintVersionInfo
|
||||
PrintVersionInfo("testService")
|
||||
|
||||
// Close writer and read output
|
||||
w.Close()
|
||||
var buf bytes.Buffer
|
||||
_, err := buf.ReadFrom(r)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read from pipe: %v", err)
|
||||
}
|
||||
output := buf.String()
|
||||
|
||||
// Check output contains expected parts
|
||||
if !strings.Contains(output, "Starting testService") {
|
||||
t.Errorf("Output should contain service name, got: %s", output)
|
||||
}
|
||||
if !strings.Contains(output, "version=") {
|
||||
t.Errorf("Output should contain version, got: %s", output)
|
||||
}
|
||||
|
||||
// Restore original values
|
||||
version = originalVersion
|
||||
gitCommit = originalCommit
|
||||
buildTime = originalBuildTime
|
||||
})
|
||||
|
||||
// Create new pipe for second test
|
||||
r2, w2, _ := os.Pipe()
|
||||
os.Stderr = w2
|
||||
|
||||
// Test 2: PrintVersionInfo with custom values
|
||||
t.Run("with custom version", func(t *testing.T) {
|
||||
// Save original values
|
||||
originalVersion := version
|
||||
originalCommit := gitCommit
|
||||
originalBuildTime := buildTime
|
||||
|
||||
// Set test values
|
||||
version = "20231201.123456-abc123"
|
||||
gitCommit = "abc123def456"
|
||||
buildTime = "2023-12-01T12:34:56Z"
|
||||
|
||||
// Call PrintVersionInfo
|
||||
PrintVersionInfo("customService")
|
||||
|
||||
// Close writer and read output
|
||||
w2.Close()
|
||||
var buf bytes.Buffer
|
||||
_, err := buf.ReadFrom(r2)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read from pipe: %v", err)
|
||||
}
|
||||
output := buf.String()
|
||||
|
||||
// Check output contains all expected parts
|
||||
if !strings.Contains(output, "Starting customService") {
|
||||
t.Errorf("Output should contain service name, got: %s", output)
|
||||
}
|
||||
if !strings.Contains(output, "version=20231201.123456-abc123") {
|
||||
t.Errorf("Output should contain version, got: %s", output)
|
||||
}
|
||||
if !strings.Contains(output, "buildTime=2023-12-01T12:34:56Z") {
|
||||
t.Errorf("Output should contain build time, got: %s", output)
|
||||
}
|
||||
if !strings.Contains(output, "commit=abc123def456") {
|
||||
t.Errorf("Output should contain commit, got: %s", output)
|
||||
}
|
||||
|
||||
// Restore original values
|
||||
version = originalVersion
|
||||
gitCommit = originalCommit
|
||||
buildTime = originalBuildTime
|
||||
})
|
||||
}
|
||||
|
||||
+7
-1
@@ -5,8 +5,12 @@ version: "3"
|
||||
|
||||
vars:
|
||||
DOCKERFILE: "build/Dockerfile"
|
||||
BUILD_TIME:
|
||||
sh: date -u +"%Y-%m-%dT%H:%M:%SZ"
|
||||
GIT_SHORT_COMMIT:
|
||||
sh: git rev-parse --short HEAD
|
||||
GIT_VERSION:
|
||||
sh: git describe --tags --always
|
||||
sh: echo "$(date -u +"%Y%m%d.%H%M%S")-$(git rev-parse --short HEAD)"
|
||||
GIT_COMMIT:
|
||||
sh: git rev-parse HEAD
|
||||
|
||||
@@ -21,6 +25,7 @@ tasks:
|
||||
docker build \
|
||||
--build-arg "GIT_VERSION={{.GIT_VERSION}}" \
|
||||
--build-arg "GIT_COMMIT={{.GIT_COMMIT}}" \
|
||||
--build-arg "BUILD_TIME={{.BUILD_TIME}}" \
|
||||
--build-arg BUILDKIT_INLINE_CACHE=1 \
|
||||
-t {{.IMAGE_NAME}}:latest \
|
||||
-t {{.IMAGE_NAME}}:{{.GIT_VERSION}} \
|
||||
@@ -32,5 +37,6 @@ tasks:
|
||||
docker build \
|
||||
--build-arg "GIT_VERSION={{.GIT_VERSION}}" \
|
||||
--build-arg "GIT_COMMIT={{.GIT_COMMIT}}" \
|
||||
--build-arg "BUILD_TIME={{.BUILD_TIME}}" \
|
||||
-t {{.IMAGE_NAME}}:debug \
|
||||
-f build/Dockerfile.debug .
|
||||
|
||||
Reference in New Issue
Block a user