-
Notifications
You must be signed in to change notification settings - Fork 1
/
Makefile
217 lines (176 loc) · 7.29 KB
/
Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# This file is intended as a starting point for a customized makefile for a Go project.
#
# Targets:
# all: Format, check, build, and test the code
# setup: Install build/test toolchain dependencies (e.g. gox)
# lint: Run linters against source code
# bump-{major,minor,patch}: create a new semver git tag
# release-{major,minor,patch}: push a tagged release
# format: Format the source files
# build: Build the command(s) for target OS/arch combinations
# install: Install the command(s)
# clean: Clean the build/test artifacts
# report: Generate build/test reports
# check: Run tests
# bench: Run benchmarks
# dist: zip/tar binaries & documentation
# debug: print parameters
#
# Parameters:
# VERSION: release version in semver format
# BUILD_TAGS: additional build tags to pass to go build
# DISTDIR: path to save distribution files
# RPTDIR: path to save build/test reports
#
# Assumptions:
# - Your package contains a cmd/ package, containing a directory for each produced binary.
# - You have cloc installed and accessible in the PATH.
# - Your GOPATH and GOROOT are set correctly.
# - Your makefile is in the root of your package and does not have a space in its file name.
# - Your root package contains global string variables Version and Build, to receive the bild version number and commit ID, respectively.
#
# Features:
# - report generates files that can be consumed by Jenkins, as well as a list of external dependencies.
# - setup installs all the tools aside from cloc.
# - Works on Windows and with paths containing spaces.
# - Works when executing from outside the makefile directory using -f.
# - Targets are useful both in CI and developer workstations.
# - Handles cross-compiation for multiple OSes and architectures.
# - Bundles binaries and documentation into compressed archives, using tar/gz for Linux and Darwin, and zip for Windows.
# Parameters
PKG = code.ndumas.com/ndumas/obsidian-pipeline
NAME = obsidian-pipeline
DOC = README.md LICENSE
# Replace backslashes with forward slashes for use on Windows.
# Make is !@#$ing weird.
E :=
BSLASH := \$E
FSLASH := /
# Directories
WD := $(subst $(BSLASH),$(FSLASH),$(shell pwd))
MD := $(subst $(BSLASH),$(FSLASH),$(shell dirname "$(realpath $(lastword $(MAKEFILE_LIST)))"))
PKGDIR = $(MD)
CMDDIR = $(PKGDIR)/cmd
DISTDIR ?= $(WD)/dist
RPTDIR ?= $(WD)/reports
GP = $(subst $(BSLASH),$(FSLASH),$(GOPATH))
# Parameters
VERSION ?= $(shell git -C "$(MD)" describe --tags --dirty=-dev)
COMMIT_ID := $(shell git -C "$(MD)" rev-parse HEAD | head -c8)
BUILD_TAGS ?= release
CMDPKG = $(PKG)/cmd
CMDS := $(shell find "$(CMDDIR)/" -mindepth 1 -maxdepth 1 -type d | sed 's/ /\\ /g' | xargs -n1 basename)
BENCHCPUS ?= 1,2,4
# Commands
GOCMD = go
ARCHES ?= amd64 386
OSES ?= windows linux darwin
OUTTPL = $(DISTDIR)/$(NAME)-$(VERSION)-{{.OS}}_{{.Arch}}/{{.Dir}}
LDFLAGS = -X $(PKG).Version=$(VERSION) -X $(PKG).Build=$(COMMIT_ID)
GOBUILD = gox -osarch="!darwin/386" -rebuild -gocmd="$(GOCMD)" -arch="$(ARCHES)" -os="$(OSES)" -output="$(OUTTPL)" -tags "$(BUILD_TAGS)" -ldflags "$(LDFLAGS)"
GOCLEAN = $(GOCMD) clean
GOINSTALL = $(GOCMD) install -a -tags "$(BUILD_TAGS)" -ldflags "$(LDFLAGS)"
GOTEST = $(GOCMD) test -v -tags "$(BUILD_TAGS)"
DISABLED_LINTERS = varnamelen,interfacer,ifshort,exhaustivestruct,maligned,varcheck,scopelint,structcheck,deadcode,nosnakecase,golint,depguard
GOLINT = golangci-lint run --enable-all --disable "$(DISABLED_LINTERS)" --timeout=30s --tests
GODEP = $(GOCMD) get -d -t
GOFMT = goreturns -w
GOBENCH = $(GOCMD) test -v -tags "$(BUILD_TAGS)" -cpu=$(BENCHCPUS) -run=NOTHING -bench=. -benchmem -outputdir "$(RPTDIR)"
GZCMD = tar -czf
ZIPCMD = zip
SHACMD = sha256sum
SLOCCMD = cloc --by-file --xml --exclude-dir="vendor" --include-lang="Go"
XUCMD = go2xunit
DOCKER_CMD=docker --config ~/.docker/
# Dynamic Targets
INSTALL_TARGETS := $(addprefix install-,$(CMDS))
.PHONY: all
all: debug setup dep format lint test bench build dist
git-push:
git push origin main --tags
git push github main --tags
release-major: bump-major git-push
release-minor: bump-minor git-push
release-patch: bump-patch git-push
setup: setup-dirs setup-build setup-format setup-lint setup-reports setup-bump
setup-bump:
go install github.com/guilhem/bump@latest
bump-major: setup-bump
bump major
bump-minor: setup-bump
bump minor
bump-patch: setup-bump
bump patch
setup-reports: setup-dirs
go install github.com/tebeka/go2xunit@latest
setup-build: setup-dirs
go install github.com/mitchellh/gox@latest
setup-format: setup-dirs
go install github.com/sqs/goreturns@latest
setup-lint: setup-dirs
go install github.com/golangci/golangci-lint/cmd/[email protected]
setup-dirs:
mkdir -p "$(RPTDIR)"
mkdir -p "$(DISTDIR)"
clean:
$(GOCLEAN) $(PKG)
rm -vrf "$(DISTDIR)"/*
rm -vf "$(RPTDIR)"/*
format:
$(GOFMT) "$(PKGDIR)"
dep:
$(GODEP) $(PKG)/...
lint: setup-dirs dep
$(GOLINT) "$(PKGDIR)" | tee "$(RPTDIR)/lint.out"
check: setup-dirs clean dep
$(GOTEST) $$(go list "$(PKG)/..." | grep -v /vendor/) | tee "$(RPTDIR)/test.out"
bench: setup-dirs clean dep
$(GOBENCH) $$(go list "$(PKG)/..." | grep -v /vendor/) | tee "$(RPTDIR)/bench.out"
report: check
cd "$(PKGDIR)";$(SLOCCMD) --out="$(RPTDIR)/cloc.xml" . | tee "$(RPTDIR)/cloc.out"
cat "$(RPTDIR)/test.out" | $(XUCMD) -output "$(RPTDIR)/tests.xml"
go list -f '{{join .Deps "\n"}}' "$(CMDPKG)/..." | sort | uniq | xargs -I {} sh -c "go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}' {} | tee -a '$(RPTDIR)/deps.out'"
build: $(CMDS)
$(CMDS): setup-dirs dep
$(GOBUILD) "$(CMDPKG)/$@" | tee "$(RPTDIR)/[email protected]"
install: $(INSTALL_TARGETS)
$(INSTALL_TARGETS):
$(GOINSTALL) "$(CMDPKG)/$(subst install-,,$@)"
dist: clean build
for docfile in $(DOC); do \
for dir in "$(DISTDIR)"/*; do \
cp "$(PKGDIR)/$$docfile" "$$dir/"; \
done; \
done
cd "$(DISTDIR)"; for dir in ./*linux*; do $(GZCMD) "$(basename "$$dir").tar.gz" "$$dir"; done
cd "$(DISTDIR)"; for dir in ./*windows*; do $(ZIPCMD) "$(basename "$$dir").zip" "$$dir"; done
cd "$(DISTDIR)"; for dir in ./*darwin*; do $(GZCMD) "$(basename "$$dir").tar.gz" "$$dir"; done
cd "$(DISTDIR)"; find . -maxdepth 1 -type f -printf "$(SHACMD) %P | tee \"./%P.sha\"\n" | sh
$(info "Built v$(VERSION), build $(COMMIT_ID)")
.PHONY: docker
docker: docker-image docker-push
.PHONY: docker-push
docker-push:
$(DOCKER_CMD) tag code.ndumas.com/ndumas/obsidian-pipeline:$(VERSION) code.ndumas.com/ndumas/obsidian-pipeline:latest
$(DOCKER_CMD) push code.ndumas.com/ndumas/obsidian-pipeline:latest
$(DOCKER_CMD) push code.ndumas.com/ndumas/obsidian-pipeline:$(VERSION)
.PHONY: docker-image
docker-image:
$(DOCKER_CMD) build --build-arg VERSION=$(VERSION) -t code.ndumas.com/ndumas/obsidian-pipeline:$(VERSION) .
.PHONY: build-alpine
build-alpine:
# this version breaks build variable injection
# CGO_ENABLED=0 GOOS=linux go build -ldflags="buildmode=exe $(LDFLAGS) -linkmode external -w -extldflags '-static' " -o $(DISTDIR)/$(NAME)-$(VERSION)-alpine/obp cmd/obp/*.go
CGO_ENABLED=0 GOOS=linux go build -ldflags="$(LDFLAGS)" -o $(DISTDIR)/$(NAME)-$(VERSION)-alpine/obp cmd/obp/*.go
debug:
$(info MD=$(MD))
$(info WD=$(WD))
$(info PKG=$(PKG))
$(info PKGDIR=$(PKGDIR))
$(info DISTDIR=$(DISTDIR))
$(info VERSION=$(VERSION))
$(info COMMIT_ID=$(COMMIT_ID))
$(info BUILD_TAGS=$(BUILD_TAGS))
$(info CMDS=$(CMDS))
$(info BUILD_TARGETS=$(BUILD_TARGETS))
$(info INSTALL_TARGETS=$(INSTALL_TARGETS))