Skip to content

Commit

Permalink
Improve Application Versioning (#171)
Browse files Browse the repository at this point in the history
* Improve Application Versioning

This will allow for better bug reports and information the binary running.
This information can be retrieved upon providing the -v or --version
flag

* fixup: fix update-version and use variables to be more consistent
  • Loading branch information
jcscottiii authored and kcajmagic committed Oct 14, 2019
1 parent 7d6eecc commit 62263ec
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 18 deletions.
36 changes: 24 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@ DEFAULT: build
GO ?= go
GOFMT ?= $(GO)fmt
APP := caduceus
DOCKER_ORG := xmidt
FIRST_GOPATH := $(firstword $(subst :, ,$(shell $(GO) env GOPATH)))
BINARY := $(FIRST_GOPATH)/bin/$(APP)

PROGVER = $(shell grep 'applicationVersion.*= ' main.go | awk '{print $$3}' | sed -e 's/\"//g')
PROGVER = $(shell git describe --tags `git rev-list --tags --max-count=1` | tail -1 | sed 's/v\(.*\)/\1/')
RPM_VERSION=$(shell echo $(PROGVER) | sed 's/\(.*\)-\(.*\)/\1/')
RPM_RELEASE=$(shell echo $(PROGVER) | sed -n 's/.*-\(.*\)/\1/p' | grep . && (echo "$(echo $(PROGVER) | sed 's/.*-\(.*\)/\1/')") || echo "1")
BUILDTIME = $(shell date -u '+%Y-%m-%d %H:%M:%S')
GITCOMMIT = $(shell git rev-parse --short HEAD)

.PHONY: go-mod-vendor
go-mod-vendor:
Expand All @@ -18,16 +23,16 @@ build: go-mod-vendor

rpm:
mkdir -p ./.ignore/SOURCES
tar -czf ./.ignore/SOURCES/$(APP)-$(PROGVER).tar.gz --transform 's/^\./$(APP)-$(PROGVER)/' --exclude ./.git --exclude ./.ignore --exclude ./conf --exclude ./deploy --exclude ./vendor --exclude ./vendor .
tar -czf ./.ignore/SOURCES/$(APP)-$(RPM_VERSION)-$(RPM_RELEASE).tar.gz --transform 's/^\./$(APP)-$(RPM_VERSION)-$(RPM_RELEASE)/' --exclude ./.git --exclude ./.ignore --exclude ./conf --exclude ./deploy --exclude ./vendor --exclude ./vendor .
cp conf/$(APP).service ./.ignore/SOURCES
cp $(APP).yaml ./.ignore/SOURCES
cp LICENSE ./.ignore/SOURCES
cp NOTICE ./.ignore/SOURCES
cp CHANGELOG.md ./.ignore/SOURCES
rpmbuild --define "_topdir $(CURDIR)/.ignore" \
--define "_version $(PROGVER)" \
--define "_release 1" \
-ba deploy/packaging/$(APP).spec
--define "_version $(RPM_VERSION)" \
--define "_release $(RPM_RELEASE)" \
-ba deploy/packaging/$(APP).spec

.PHONY: version
version:
Expand All @@ -44,28 +49,35 @@ endif
.PHONY: update-version
update-version:
@echo "Update Version $(PROGVER) to $(RUN_ARGS)"
sed -i "s/$(PROGVER)/$(RUN_ARGS)/g" main.go
git tag v$(RUN_ARGS)


.PHONY: install
install: go-mod-vendor
echo $(GO) build -o $(BINARY) $(PROGVER)
go install -ldflags "-X 'main.BuildTime=$(BUILDTIME)' -X main.GitCommit=$(GITCOMMIT) -X main.Version=$(PROGVER)"

.PHONY: release-artifacts
release-artifacts: go-mod-vendor
mkdir -p ./.ignore
GOOS=darwin GOARCH=amd64 $(GO) build -o ./.ignore/$(APP)-$(PROGVER).darwin-amd64
GOOS=linux GOARCH=amd64 $(GO) build -o ./.ignore/$(APP)-$(PROGVER).linux-amd64
GOOS=darwin GOARCH=amd64 $(GO) build -ldflags "-X 'main.BuildTime=$(BUILDTIME)' -X main.GitCommit=$(GITCOMMIT) -X main.Version=$(PROGVER)" -o ./.ignore/$(APP)-$(PROGVER).darwin-amd64
GOOS=linux GOARCH=amd64 $(GO) build -ldflags "-X 'main.BuildTime=$(BUILDTIME)' -X main.GitCommit=$(GITCOMMIT) -X main.Version=$(PROGVER)" -o ./.ignore/$(APP)-$(PROGVER).linux-amd64

.PHONY: docker
docker:
docker build -f ./deploy/Dockerfile -t $(APP):$(PROGVER) .
docker build \
--build-arg VERSION=$(PROGVER) \
--build-arg GITCOMMIT=$(GITCOMMIT) \
--build-arg BUILDTIME='$(BUILDTIME)' \
-f ./deploy/Dockerfile -t $(DOCKER_ORG)/$(APP):$(PROGVER) .

# build docker without running modules
.PHONY: local-docker
local-docker:
GOOS=linux GOARCH=amd64 $(GO) build -o $(APP)_linux_amd64
docker build -f ./deploy/Dockerfile.local -t $(APP):local .
docker build \
--build-arg VERSION=$(PROGVER)+local \
--build-arg GITCOMMIT=$(GITCOMMIT) \
--build-arg BUILDTIME='$(BUILDTIME)' \
-f ./deploy/Dockerfile.local -t $(DOCKER_ORG)/$(APP):local .

.PHONY: style
style:
Expand Down
5 changes: 4 additions & 1 deletion deploy/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ FROM golang:alpine as builder
MAINTAINER Jack Murdock <[email protected]>

WORKDIR /go/src/github.com/xmidt-org/caduceus
ARG VERSION=undefined
ARG GITCOMMIT=undefined
ARG BUILDTIME=undefined

RUN apk update && apk upgrade && \
apk add --no-cache bash git openssh

COPY . .
RUN GO111MODULE=on go build -o caduceus_linux_amd64
RUN GO111MODULE=on go build -ldflags "-X 'main.BuildTime=${BUILDTIME}' -X main.GitCommit=${GITCOMMIT} -X main.Version=${VERSION}" -o caduceus_linux_amd64

FROM alpine

Expand Down
5 changes: 4 additions & 1 deletion deploy/Dockerfile.local
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ FROM golang:alpine as builder
MAINTAINER Jack Murdock <[email protected]>

WORKDIR /go/src/github.com/xmidt-org/caduceus
ARG VERSION=undefined
ARG GITCOMMIT=undefined
ARG BUILDTIME=undefined

RUN apk add --update git curl

COPY . .

RUN go build -o caduceus_linux_amd64
RUN go build -ldflags "-X 'main.BuildTime=${BUILDTIME}' -X main.GitCommit=${GITCOMMIT} -X main.Version=${VERSION}" -o caduceus_linux_amd64

FROM alpine

Expand Down
2 changes: 1 addition & 1 deletion deploy/packaging/caduceus.spec
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ BuildRequires: golang >= 1.12
The Xmidt API interface server.

%build
GO111MODULE=on go build -o $RPM_SOURCE_DIR/%{name} %{_topdir}/..
GO111MODULE=on go build -ldflags "-X 'main.BuildTime=`date -u '+%Y-%m-%d %H:%M:%S'`' -X main.GitCommit=`git rev-parse --short HEAD` -X main.Version=%{_version}" -o $RPM_SOURCE_DIR/%{name} %{_topdir}/..

%install
echo rm -rf %{buildroot}
Expand Down
47 changes: 44 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ package main
import (
"crypto/tls"
"fmt"
"io"
"net/http"
_ "net/http/pprof"
"net/url"
"os"
"os/signal"
"runtime"
"time"

"github.com/go-kit/kit/log/level"
Expand All @@ -39,9 +41,14 @@ import (
)

const (
applicationName = "caduceus"
DEFAULT_KEY_ID = "current"
applicationVersion = "0.2.1"
applicationName = "caduceus"
DEFAULT_KEY_ID = "current"
)

var (
GitCommit = "undefined"
Version = "undefined"
BuildTime = "undefined"
)

// caduceus is the driver function for Caduceus. It performs everything main() would do,
Expand All @@ -57,6 +64,18 @@ func caduceus(arguments []string) int {
logger, metricsRegistry, webPA, err = server.Initialize(applicationName, arguments, f, v, Metrics, webhook.Metrics, aws.Metrics)
)

if parseErr, done := printVersion(f, arguments); done {
// if we're done, we're exiting no matter what
if parseErr != nil {
friendlyError := fmt.Sprintf("failed to parse arguments. detailed error: %s", parseErr)
logging.Error(logger).Log(
logging.ErrorKey(),
friendlyError)
os.Exit(1)
}
os.Exit(0)
}

if err != nil {
fmt.Fprintf(os.Stderr, "Unable to initialize Viper environment: %s\n", err)
return 1
Expand Down Expand Up @@ -224,6 +243,28 @@ func caduceus(arguments []string) int {
return 0
}

func printVersion(f *pflag.FlagSet, arguments []string) (error, bool) {
printVer := f.BoolP("version", "v", false, "displays the version number")
if err := f.Parse(arguments); err != nil {
return err, true
}

if *printVer {
printVersionInfo(os.Stdout)
return nil, true
}
return nil, false
}

func printVersionInfo(writer io.Writer) {
fmt.Fprintf(writer, "%s:\n", applicationName)
fmt.Fprintf(writer, " version: \t%s\n", Version)
fmt.Fprintf(writer, " go version: \t%s\n", runtime.Version())
fmt.Fprintf(writer, " built time: \t%s\n", BuildTime)
fmt.Fprintf(writer, " git commit: \t%s\n", GitCommit)
fmt.Fprintf(writer, " os/arch: \t%s/%s\n", runtime.GOOS, runtime.GOARCH)
}

func main() {
os.Exit(caduceus(os.Args))
}
75 changes: 75 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,85 @@
package main

import (
"bytes"
"os"
"strings"
"testing"

"github.com/stretchr/testify/assert"
)

func TestMain(m *testing.M) {
os.Exit(m.Run())
}

func TestPrintVersionInfo(t *testing.T) {
testCases := []struct {
name string
expectedOutput []string
overrideValues func()
lineCount int
}{
{
"default",
[]string{
"caduceus:",
"version: \tundefined",
"go version: \tgo",
"built time: \tundefined",
"git commit: \tundefined",
"os/arch: \t",
},
func() {},
6,
},
{
"set values",
[]string{
"caduceus:",
"version: \t1.0.0\n",
"go version: \tgo",
"built time: \tsome time\n",
"git commit: \tgit sha\n",
"os/arch: \t",
},
func() {
Version = "1.0.0"
BuildTime = "some time"
GitCommit = "git sha"
},
6,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
resetGlobals()
tc.overrideValues()
buf := &bytes.Buffer{}
printVersionInfo(buf)
count := 0
for {
line, err := buf.ReadString(byte('\n'))
if err != nil {
break
}
assert.Contains(t, line, tc.expectedOutput[count])
if strings.Contains(line, "\t") {
keyAndValue := strings.Split(line, "\t")
// The value after the tab should have more than 2 characters
// 1) the first character of the value and the new line
assert.True(t, len(keyAndValue[1]) > 2)
}
count++
}
assert.Equal(t, tc.lineCount, count)
resetGlobals()
})
}
}

func resetGlobals() {
Version = "undefined"
BuildTime = "undefined"
GitCommit = "undefined"
}

0 comments on commit 62263ec

Please sign in to comment.