From 7d256a999f92840a241768bde71c367829d866a3 Mon Sep 17 00:00:00 2001 From: Ben Vincent Date: Wed, 25 Mar 2026 15:55:17 +1100 Subject: [PATCH] Add version subcommand and Makefile semver bump targets - var version injected at build time via -X main.version=$(VERSION) - VERSION derives from 'git describe --tags' so built binaries show the exact tag (or tag+commits+sha for dirty/untagged builds) - 'make patch/minor/major' reads the latest vX.Y.Z tag and creates the next one; starts from v0.0.0 if no tags exist yet --- Makefile | 25 +++++++++++++++++++++++-- main.go | 10 ++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 0459ade..e44aeb7 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ BINARY := node-lookup -GOFLAGS := -ldflags="-s -w" +VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo dev) +GOFLAGS := -ldflags="-s -w -X main.version=$(VERSION)" -.PHONY: all build test lint clean install +.PHONY: all build test lint clean install patch minor major all: build @@ -19,3 +20,23 @@ clean: install: go install $(GOFLAGS) ./... + +# Bump helpers — reads the latest semver tag and creates the next one. +# If no tag exists yet, starts from v0.0.0. +_LATEST := $(shell git tag --sort=-v:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$$' | head -1) +_BASE := $(if $(_LATEST),$(_LATEST),v0.0.0) +_MAJ := $(shell echo $(_BASE) | sed 's/^v//' | cut -d. -f1) +_MIN := $(shell echo $(_BASE) | sed 's/^v//' | cut -d. -f2) +_PAT := $(shell echo $(_BASE) | sed 's/^v//' | cut -d. -f3) + +patch: + @NEW=v$(_MAJ).$(_MIN).$(shell expr $(_PAT) + 1); \ + git tag $$NEW && echo "Tagged $$NEW" + +minor: + @NEW=v$(_MAJ).$(shell expr $(_MIN) + 1).0; \ + git tag $$NEW && echo "Tagged $$NEW" + +major: + @NEW=v$(shell expr $(_MAJ) + 1).0.0; \ + git tag $$NEW && echo "Tagged $$NEW" diff --git a/main.go b/main.go index 652207a..b6ff5a1 100644 --- a/main.go +++ b/main.go @@ -25,6 +25,8 @@ const ( appName = "node-lookup" ) +var version = "dev" + // config holds all configurable values. Fields map 1:1 to config file keys, // env vars (NODE_LOOKUP_*), and (where applicable) CLI flags. type config struct { @@ -397,6 +399,14 @@ func main() { configCmd.AddCommand(configInitCmd, configShowCmd) rootCmd.AddCommand(configCmd) + versionCmd := &cobra.Command{ + Use: "version", + Short: "Print the version", + Run: func(cmd *cobra.Command, args []string) { fmt.Println(version) }, + SilenceUsage: true, + } + rootCmd.AddCommand(versionCmd) + if err := rootCmd.Execute(); err != nil { os.Exit(1) }