-
-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
Description
Problem
Version is hardcoded as "development" with no way to inject build version during release.
Current Implementation
// cmd/logwrap/main.go:18
const version = "development"Output:
$ logwrap --version
logwrap version developmentIssues:
- Can't identify which release is installed
- No build metadata (commit hash, build date)
- Hard to troubleshoot issues ("which version are you running?")
Proposed Solution
Use -ldflags during build to inject version information.
Implementation
// cmd/logwrap/main.go
var (
// Injected at build time via -ldflags
version = "development"
commit = "unknown"
buildDate = "unknown"
)
func printVersion() {
fmt.Printf("logwrap version %s\n", version)
fmt.Printf(" commit: %s\n", commit)
fmt.Printf(" built: %s\n", buildDate)
}Build Command
# Manual build
go build -ldflags "\
-X main.version=v1.0.0 \
-X main.commit=$(git rev-parse HEAD) \
-X main.buildDate=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
./cmd/logwrap
# Output:
$ logwrap --version
logwrap version v1.0.0
commit: a1b2c3d4e5f6...
built: 2024-01-15T14:30:00ZGoReleaser Integration
Update .goreleaser.yml:
builds:
- id: logwrap
binary: logwrap
main: ./cmd/logwrap
ldflags:
- -s -w
- -X main.version={{.Version}}
- -X main.commit={{.Commit}}
- -X main.buildDate={{.Date}}
env:
- CGO_ENABLED=0
goos:
- linux
- darwin
- windows
goarch:
- amd64
- arm64Taskfile Integration
Update Taskfile.yml:
vars:
VERSION:
sh: git describe --tags --always --dirty
COMMIT:
sh: git rev-parse HEAD
BUILD_DATE:
sh: date -u +%Y-%m-%dT%H:%M:%SZ
tasks:
build:
desc: Build the binary
cmds:
- go build -ldflags "
-X main.version={{.VERSION}}
-X main.commit={{.COMMIT}}
-X main.buildDate={{.BUILD_DATE}}"
-o bin/logwrap ./cmd/logwrapGitHub Actions Integration
# .github/workflows/release.yml
- name: Build with version info
run: |
VERSION=${{ github.ref_name }}
COMMIT=${{ github.sha }}
BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
go build -ldflags "
-X main.version=${VERSION}
-X main.commit=${COMMIT}
-X main.buildDate=${BUILD_DATE}" \
-o logwrap ./cmd/logwrapVersion Output Formats
Simple (current)
$ logwrap --version
logwrap version v1.0.0Detailed
$ logwrap --version
logwrap version v1.0.0
commit: a1b2c3d4e5f6...
built: 2024-01-15T14:30:00Z
go: go1.22.1
os/arch: linux/amd64JSON (for scripts)
$ logwrap --version --json
{
"version": "v1.0.0",
"commit": "a1b2c3d4e5f6...",
"buildDate": "2024-01-15T14:30:00Z",
"goVersion": "go1.22.1",
"os": "linux",
"arch": "amd64"
}Implementation Checklist
Required:
- Change
versionfrom const to var - Add
commitandbuildDatevariables - Update
.goreleaser.ymlwith ldflags - Update
Taskfile.ymlwith version injection - Test with
task build
Nice to Have:
- Add detailed version output
- Add JSON format for --version
- Add runtime info (Go version, OS, arch)
- Update GitHub Actions workflows
Testing
# Build with version
task build
# Check version
./bin/logwrap --version
# Should show actual version, not "development"
# Verify ldflags worked
go version -m ./bin/logwrap | grep main
# Should show injected valuesBenefits
User Support:
- Easy to identify installed version
- Better bug reports ("I'm using v1.2.3")
- Easier troubleshooting
Release Management:
- Track which commits are in production
- Verify binary freshness
- Audit trail for deployments
Development:
- Distinguish dev builds from releases
- CI/CD integration
- Automated versioning
Alternative: Embed Version File
Instead of ldflags, embed version file:
//go:embed VERSION
var version string
func init() {
version = strings.TrimSpace(version)
}Pros: Simpler, no build flags needed
Cons: Requires VERSION file, less flexible
Recommendation: Use ldflags (industry standard, works with GoReleaser)
Related Issues
- None directly, but good DevOps practice
References
- Go ldflags: https://pkg.go.dev/cmd/link
- GoReleaser ldflags: https://goreleaser.com/customization/build/
- Semantic versioning: https://semver.org/
Reactions are currently unavailable