vahiiiid/go-rest-api-boilerplate

Add Version Information and Build Metadata to Application

Open

#70 opened on Oct 18, 2025

 (2 comments) (0 reactions) (0 assignees)Go (23 forks)auto 404
enhancementgood first issue

Repository metrics

Stars
 (60 stars)
PR merge metrics
 (PR metrics pending)

Description

Problem

The application has no version information or build metadata, making it difficult to:

  • Track which version is running in production
  • Debug deployment issues
  • Correlate logs/errors with releases
  • Verify successful deployments
  • Support customers effectively

Current State

No version information visible anywhere:

  • Not in logs
  • Not in health check
  • Not exposed via API
  • Cannot determine what's running

Proposed Solution

Add build-time version injection and expose it via API.

1. Add Version Variables in main.go

package main

var (
    version   = "dev"       // Set via -ldflags at build time
    commit    = "none"      // Git commit hash
    buildDate = "unknown"   // Build timestamp
    goVersion = runtime.Version()
)

func main() {
    log.Printf("Starting %s", getVersionInfo())
    // ... rest of startup
}

func getVersionInfo() string {
    return fmt.Sprintf("v%s (commit: %s, built: %s, go: %s)",
        version, commit[:7], buildDate, goVersion)
}

2. Update Dockerfile for Build-Time Injection

# Get build args
ARG VERSION=dev
ARG COMMIT=unknown
ARG BUILD_DATE=unknown

# Build with ldflags
RUN go build -ldflags="\
    -X main.version=${VERSION} \
    -X main.commit=${COMMIT} \
    -X main.buildDate=${BUILD_DATE}" \
    -o main ./cmd/server

3. Add Version Endpoint

// internal/server/router.go
router.GET("/version", func(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
        "version":    version,
        "commit":     commit,
        "buildDate":  buildDate,
        "goVersion":  goVersion,
    })
})

4. Enhance Health Check

router.GET("/health", func(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
        "status":    "ok",
        "version":   version,
        "timestamp": time.Now(),
    })
})

5. Update Makefile for Local Builds

VERSION ?= $(shell git describe --tags --always --dirty)
COMMIT ?= $(shell git rev-parse HEAD)
BUILD_DATE ?= $(shell date -u +"%Y-%m-%dT%H:%M:%SZ")

.PHONY: build
build:
\t@go build -ldflags="\
\t\t-X main.version=${VERSION} \
\t\t-X main.commit=${COMMIT} \
\t\t-X main.buildDate=${BUILD_DATE}" \
\t\t-o bin/server ./cmd/server

Benefits

  • ✅ Track running versions in production
  • ✅ Better deployment verification
  • ✅ Easier debugging and support
  • ✅ Version endpoint for monitoring tools
  • ✅ Improved observability
  • ✅ Professional production readiness

Implementation Checklist

  • Add version variables to cmd/server/main.go
  • Log version info at startup
  • Create /version endpoint
  • Update /health to include version
  • Update Dockerfile with build args
  • Update Makefile with ldflags
  • Update CI/CD to inject version info
  • Update docker-compose.yml with build args
  • Add version to Swagger docs
  • Update documentation

Example Output

Startup Logs

Starting GRAB API v1.2.3 (commit: abc1234, built: 2025-10-18T10:30:00Z, go: go1.24.0)
Server starting on :8080

GET /version

{
  "version": "1.2.3",
  "commit": "abc1234567890abcdef1234567890abcdef1234",
  "buildDate": "2025-10-18T10:30:00Z",
  "goVersion": "go1.24.0"
}

References

Priority

IMPORTANT - Improves production operations

Related Issues

  • #15 (Graceful Shutdown) - Part of production readiness
  • #11 (Prometheus Metrics) - Can expose version as metric

Contributor guide