Skip to content

Commit d09b2ce

Browse files
authored
Add version flags and build target (#11)
1 parent 1117652 commit d09b2ce

File tree

9 files changed

+226
-3
lines changed

9 files changed

+226
-3
lines changed

README.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
# Go development helpers
22

3-
## Usage
3+
## Installation
44

55
Add a test file (e.g. `dev_test.go`) to your module with unused import.
6+
67
```go
78
package mymodule_test
89

910
import _ "github.com/bool64/dev" // Include development helpers to project.
1011
```
1112

1213
Add `Makefile` to your module with includes standard targets.
14+
1315
```Makefile
1416
GOLANGCI_LINT_VERSION := "v1.35.2" # Optional.
1517

@@ -54,6 +56,7 @@ test: test-unit
5456
```
5557

5658
Then `make` will have these targets:
59+
5760
```
5861
Usage
5962
test: Run tests
@@ -64,4 +67,10 @@ Usage
6467
bench: Run benchmark, iterations count controlled by BENCH_COUNT, default 5.
6568
github-actions: Replace GitHub Actions from template
6669
67-
```
70+
```
71+
72+
## Build Versioning
73+
74+
You can include `$(DEVGO_PATH)/makefiles/build.mk` to add automated versioning of build artifacts. Make will
75+
configure `ldflags` to set up [version info](./version/info.go), then you can access it in runtime with `version.Info()`
76+
or expose with [HTTP handler](./version/handler.go). Version information also includes versions of dependencies.

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
module github.com/bool64/dev
22

33
go 1.11
4+
5+
require github.com/stretchr/testify v1.7.0

go.sum

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
2+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
4+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
5+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
6+
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
7+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
8+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
9+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
10+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
11+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

makefiles/build.mk

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
GO ?= go
2+
3+
# Override in app Makefile to add custom ldflags, example BUILD_LDFLAGS="-s -w"
4+
BUILD_LDFLAGS ?= ""
5+
6+
# Override in app Makefile to control build target, example BUILD_PKG=./cmd/my-app
7+
BUILD_PKG ?= .
8+
9+
# Override in app Makefile to control build artifact destination.
10+
BUILD_DIR ?= ./bin
11+
12+
## Build Linux binary
13+
build-linux:
14+
@echo "Building Linux AMD64 binary, GOFLAGS: $(GOFLAGS)"
15+
@GOOS=linux GOARCH=amd64 $(GO) build -ldflags "$(shell bash $(DEVGO_SCRIPTS)/version-ldflags.sh && echo $(BUILD_LDFLAGS))" -o $(BUILD_DIR)/ $(BUILD_PKG)
16+
17+
## Build binary
18+
build:
19+
@echo "Building binary, GOFLAGS: $(GOFLAGS)"
20+
@$(GO) build -ldflags "$(shell bash $(DEVGO_SCRIPTS)/version-ldflags.sh && echo $(BUILD_LDFLAGS))" -o $(BUILD_DIR)/ $(BUILD_PKG)
21+
22+
## Build and run binary
23+
run:
24+
@echo "Running binary"
25+
@$(GO) run -ldflags "$(shell bash $(DEVGO_SCRIPTS)/version-ldflags.sh && echo $(BUILD_LDFLAGS))" $(BUILD_PKG)
26+
27+
.PHONY: build-linux build run

scripts/version-ldflags.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ fi
1010
build_user="$USER"
1111
build_date=$(date +%FT%T%Z)
1212

13-
version_pkg=github.com/bool64/dev-go/version
13+
version_pkg=github.com/bool64/dev/version
1414

1515
echo -X "$version_pkg".version="$VERSION" -X "$version_pkg".branch="$branch" -X "$version_pkg".revision="$revision" -X "$version_pkg".buildUser="$build_user" -X "$version_pkg".buildDate="$build_date"

version/handler.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package version
2+
3+
import (
4+
"encoding/json"
5+
"net/http"
6+
)
7+
8+
// Handler serves version information with HTTP.
9+
func Handler(w http.ResponseWriter, _ *http.Request) {
10+
b, err := json.Marshal(Info())
11+
if err != nil {
12+
http.Error(w, err.Error(), http.StatusInternalServerError)
13+
}
14+
15+
w.Header().Set("Content-Type", "application/json")
16+
_, _ = w.Write(b)
17+
}

version/info.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Package version contains build information.
2+
package version
3+
4+
import "runtime"
5+
6+
// Build information. Populated at build-time.
7+
// nolint:gochecknoglobals
8+
var (
9+
version = "dev"
10+
revision string
11+
branch string
12+
buildUser string
13+
buildDate string
14+
dependencies map[string]string
15+
)
16+
17+
// Information holds app version info.
18+
type Information struct {
19+
Version string `json:"version,omitempty"`
20+
Revision string `json:"revision,omitempty"`
21+
Branch string `json:"branch,omitempty"`
22+
BuildUser string `json:"build_user,omitempty"`
23+
BuildDate string `json:"build_date,omitempty"`
24+
GoVersion string `json:"go_version,omitempty"`
25+
Dependencies map[string]string `json:"dependencies,omitempty"`
26+
}
27+
28+
// Info returns app version info.
29+
func Info() Information {
30+
return Information{
31+
Version: version,
32+
Revision: revision,
33+
Branch: branch,
34+
BuildUser: buildUser,
35+
BuildDate: buildDate,
36+
GoVersion: runtime.Version(),
37+
Dependencies: dependencies,
38+
}
39+
}
40+
41+
// String return version information as string.
42+
func (i Information) String() string {
43+
res := ""
44+
45+
if i.Version != "" {
46+
res += ", Version: " + i.Version
47+
}
48+
49+
if i.Revision != "" {
50+
res += ", Revision: " + i.Revision
51+
}
52+
53+
if i.Branch != "" {
54+
res += ", Branch: " + i.Branch
55+
}
56+
57+
if i.BuildUser != "" {
58+
res += ", BuildUser: " + i.BuildUser
59+
}
60+
61+
if i.BuildDate != "" {
62+
res += ", BuildDate: " + i.BuildDate
63+
}
64+
65+
res += ", GoVersion: " + runtime.Version()
66+
67+
return res[2:]
68+
}
69+
70+
// Values return version information as string map.
71+
func (i Information) Values() map[string]string {
72+
return map[string]string{
73+
"version": i.Version,
74+
"revision": i.Revision,
75+
"branch": i.Branch,
76+
"build_user": i.BuildUser,
77+
"build_date": i.BuildDate,
78+
"go_version": i.GoVersion,
79+
}
80+
}

version/info_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package version
2+
3+
import (
4+
"fmt"
5+
"runtime"
6+
"testing"
7+
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
func TestInformation_String(t *testing.T) {
12+
version = "v3.2.1"
13+
branch = ""
14+
revision = ""
15+
buildDate = ""
16+
buildUser = ""
17+
18+
assert.Equal(t, "Version: v3.2.1, GoVersion: "+runtime.Version(), Info().String())
19+
20+
version = "v1.2.3"
21+
branch = "refs/heads/master"
22+
revision = "111765232072440cc598b189e284c9a4450a6018"
23+
buildUser = "user"
24+
buildDate = "2021-01-13 22:13:41"
25+
26+
assert.Equal(t, fmt.Sprintf("Version: %s, Revision: %s, Branch: %s, BuildUser: %s, BuildDate: %s, GoVersion: %s",
27+
version, revision, branch, buildUser, buildDate, runtime.Version()), Info().String())
28+
}
29+
30+
func TestInformation_Values(t *testing.T) {
31+
version = "v3.2.1"
32+
branch = ""
33+
revision = ""
34+
buildDate = ""
35+
buildUser = ""
36+
37+
assert.Equal(t, map[string]string{
38+
"branch": "", "build_date": "", "build_user": "", "go_version": runtime.Version(),
39+
"revision": "", "version": "v3.2.1",
40+
}, Info().Values())
41+
42+
version = "v1.2.3"
43+
branch = "refs/heads/master"
44+
revision = "111765232072440cc598b189e284c9a4450a6018"
45+
buildDate = "2021-01-13 22:13:41"
46+
buildUser = "user"
47+
48+
assert.Equal(t, map[string]string{
49+
"branch": branch, "build_date": buildDate, "build_user": buildUser,
50+
"go_version": runtime.Version(), "revision": revision, "version": version,
51+
}, Info().Values())
52+
}

version/mod.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// +build go1.12
2+
3+
package version
4+
5+
import (
6+
"fmt"
7+
"runtime/debug"
8+
)
9+
10+
//nolint:gochecknoinits
11+
func init() {
12+
if info, available := debug.ReadBuildInfo(); available {
13+
if version == "dev" && info.Main.Version != "(devel)" {
14+
version = info.Main.Version
15+
revision = fmt.Sprintf("(unknown, mod sum: %q)", info.Main.Sum)
16+
buildUser = "(unknown)"
17+
buildDate = "(unknown)"
18+
}
19+
20+
dependencies = make(map[string]string, len(info.Deps))
21+
for _, dep := range info.Deps {
22+
dependencies[dep.Path] = dep.Version
23+
}
24+
}
25+
}

0 commit comments

Comments
 (0)