Jay Taylor's notes

back to listing index

shipbuilder/Makefile at master · jaytaylor/shipbuilder

[web search]
Original source (github.com)
Tags: make shipbuilder jay-taylor one-makefile-to-rule-them-all pipedream
Clipped on: 2020-03-30

Skip to content
Image (Asset 1/3) alt= You have unread notifications
Branch: master

shipbuilder / Makefile

Find file Copy path
Image (Asset 3/3) alt= Open this file in GitHub Desktop
1 ################################################################################
2 # START of configuration #
3
4 GITHUB_REPO ?= shipbuilder
5 GITHUB_ORG ?= jaytaylor
6 GITHUB_DOMAIN ?= github.com
7 GITHUB_API ?= https://$(GITHUB_DOMAIN)/api/v3
8 GITHUB_TOKEN ?=
9 # DOCKER_REGISTRY ?= hub.docker.com
10
11 # END of configuration #
12 ################################################################################
13
14 SHELL := /bin/bash
15
16 RM := rm -rf
17
18 EXIT_ON_ERROR := set -o errexit && set -o pipefail && set -o nounset &&
19
20 # Supported operating systems.
21 OSES := linux darwin
22
23 # OS class (e.g. "Linux", "Darwin").
24 UNAME_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
25 # # Machine architecture (e.g. "x86_64").
26 # UNAME_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
27 # NB: Sourced from: https://git.kernel.org/pub/scm/git/git.git/tree/config.mak.uname
28
29 TARGETS := $(shell \
30 grep --files-with-matches --recursive '^package main$$' */*.go \
31 | xargs -n1 dirname \
32 | sort \
33 | uniq \
34 )
35
36 VERSION_RAW := $(shell \
37 git describe --abbrev=4 --dirty --always --tags \
38 | tr -d '\n' \
39 )
40
41 # NB: For ubuntu packaging version name compatibility, add a leading '0-' when
42 # the version doesn't start with a number.
43 VERSION := $(shell \
44 if ! [[ $(VERSION_RAW) =~ ^[0-9] ]] ; then echo -n '0-' ; fi \
45 && echo -n $(VERSION_RAW) \
46 )
47
48 VERSION_CLEAN = $(VERSION:v%=%)
49
50 RPM_VERSION = $(shell echo $(VERSION) | tr '-' '_')
51 RPM_FILENAME = $(GITHUB_REPO)-$(RPM_VERSION)-1.x86_64.rpm
52 DEB_FILENAME = $(GITHUB_REPO)_$(VERSION)_amd64.deb
53
54 DESCRIPTION = $(shell \
55 git tag --list -n999 $$(echo $(VERSION) | sed -e 's/-dirty$$//' -e 's/^0-//') \
56 | sed "s/'/''/g" \
57 | sed '1 s/^[^ ]* *//' \
58 | awk 1 ORS='\\n' \
59 )
60
61 all: get test build
62
63 get:
64 $(EXIT_ON_ERROR) go get ./...
65
66 generate:
67 $(EXIT_ON_ERROR) echo -e 'package data\nfunc Asset(name string) ([]byte, error) { return nil, nil }' > pkg/bindata_buildpacks/data/buildpacks_data.go
68 $(EXIT_ON_ERROR) find . -type f -name '*.go' | grep -v '^\(\.\/\)\?\(vendor\)' | xargs -n1 dirname | sort | uniq | xargs -n1 go generate
69
70 test: generate
71 $(EXIT_ON_ERROR) go test -race -v $$(go list ./... | grep -v /vendor/) || ( rc=$$? && echo "rc=$${rc}" && exit $${rc} )
72
73 # Generate build targets for long form,
74 # e.g. `make shipbuilder/shipbuilder-linux`.
75 $(foreach target,$(TARGETS),$(foreach os,$(OSES),$(target)/$(target)-$(os))): generate
76 $(eval tool := $(subst /,,$(dir $@)))
77 $(eval binary := $(subst $(dir $@),,$@))
78 $(eval os := $(subst $(dir $@)$(tool)-,,$@))
79 @echo "info: Building tool=$(tool) binary=$(binary) os=$(os) verion=$(VERSION_CLEAN)"
80 $(EXIT_ON_ERROR) cd $(tool) && GOOS=$(os) GOARCH=amd64 go build \
81 -ldflags "-X $(GITHUB_DOMAIN)/$(GITHUB_ORG)/$(GITHUB_REPO)/pkg/version.Version=$(VERSION_CLEAN) \
82 $(shell bash -c 'test -x ldflags.sh && ./ldflags.sh || :')" \
83 -o $(binary)
84
85 # Generate build targets for single-OS short form,
86 # e.g. `make shipbuilder-linux`.
87 $(foreach target,$(TARGETS),$(foreach os,$(OSES),$(target)-$(os))):
88 $(eval tool := $@)
89 @# Strip all `-DOLLAR(os)' strings from $(tool).
90 $(foreach os,$(OSES), \
91 $(eval tool := $(subst -$(os),,$(tool))) \
92 )
93 $(eval os := $(subst $(tool)-,,$@))
94 $(EXIT_ON_ERROR) make $(tool)/$(tool)-$(os)
95
96 .SECONDEXPANSION:
97 # NB: See https://www.gnu.org/software/make/manual/html_node/Secondary-Expansion.html
98 # for information on how `.SECONDARYEXPANSION` works. The general idea is
99 # enabling a double-var expansion capability; as in `$$..`.
100
101 # Generate build targets for multi-OS short form,
102 # e.g. `make shipbuilder`.
103 $(foreach target,$(TARGETS),$(target)): $(foreach os,$(OSES), $$@-$(os) )
104
105 build: $(foreach target,$(TARGETS),$(foreach os,$(OSES),$(target)/$(target)-$(os)))
106
107 # Generate generalized build targets for each OS,
108 # e.g. `make build-linux`.
109 $(foreach os,$(OSES),build-$(os)): $(foreach target,$(TARGETS), $(target)/$(target)-$$(subst build-,,$$@) )
110
111 # Generate packaging targets for each OS,
112 # e.g. `make package-linux`.
113 $(foreach os,$(OSES),package-$(os)): build-$$(subst package-,,$$@)
114 $(eval os := $(subst package-,,$@))
115 $(EXIT_ON_ERROR) mkdir -p build/$(os) dist
116 $(EXIT_ON_ERROR) $(foreach target,$(TARGETS), \
117 cp $(target)/$(target)-$(os) build/$(os)/$(target) ; \
118 )
119 $(EXIT_ON_ERROR) cd build/$(os) && tar -cjvf ../../dist/$(GITHUB_REPO)-$(VERSION)-$(os).tar.bz *
120
121 # Installs Ubuntu dependencies for RPM construction.
122 # TODO: Detect OS and support both Ubuntu and Centos.
123 deps:
124 ifeq ($(UNAME_S),Linux)
125 @#$(EXIT_ON_ERROR) command gcc || sudo --non-interactive apt-get install --yes gcc
126 @#$(EXIT_ON_ERROR) command gem || sudo --non-interactive apt-get install --yes gem
127 @#$(EXIT_ON_ERROR) command git || sudo --non-interactive apt-get install --yes git
128 @#$(EXIT_ON_ERROR) command unzip || sudo --non-interactive apt-get install --yes unzip
129 $(EXIT_ON_ERROR) sudo --non-interactive apt-get install --yes bzr gcc gem git rpm ruby-dev rubygems unzip
130 $(EXIT_ON_ERROR) command -v fpm 1>/dev/null 2>/dev/null || sudo --non-interactive gem install fpm
131 else
132 ifeq ($(UNAME_S),Darwin)
133 $(EXIT_ON_ERROR) command -v fpm 1>/dev/null 2>/dev/null || sudo --non-interactive gem install fpm
134 @# NB: gtar is required by for fpm to work properly on macOS.
135 @#
136 @# Avoids errors like:
137 @#
138 @# tar: Option --owner=0 is not supported
139 @# tar: Option --group=0 is not supported
140 @#
141 $(EXIT_ON_ERROR) command -v gtar 1>/dev/null 2>/dev/null || brew install gtar
142 else
143 $(EXIT_ON_ERROR) @echo "Unrecognized operation system: $(UNAME_S)" 1>&2 && exit 1
144 endif
145 endif
146
147 _create_environment:
148 @$(EXIT_ON_ERROR) test -d env || ( echo 'error: missing required "env" configuration directory' 1>&2 && exit 1 )
149 $(EXIT_ON_ERROR) echo -n '' > build/environment
150 $(EXIT_ON_ERROR) cd env && for f in $$(ls -1) ; do echo "$${f}='$$(cat "$${f}")'" >> ../build/environment ; done ; cd - 1>/dev/null
151
152 _prep_fpm: _create_environment build-linux package-linux deps
153 $(EXIT_ON_ERROR) test -r build/environment || ( echo 'error: missing build/environment; hint: start out by copying build/environment.example' 1>&2 && exit 1 )
154 $(EXIT_ON_ERROR) \
155 mkdir -p dist \
156 && cd build \
157 && mkdir -p $(GITHUB_REPO)/etc/default $(GITHUB_REPO)/etc/$(GITHUB_REPO) $(GITHUB_REPO)/etc/systemd/system $(GITHUB_REPO)/usr/bin \
158 && cp linux/$(GITHUB_REPO) $(GITHUB_REPO)/usr/bin/$(GITHUB_REPO) \
159 && chmod 755 $(GITHUB_REPO)/usr/bin/$(GITHUB_REPO) \
160 && cp ../build/environment $(GITHUB_REPO)/etc/default/$(GITHUB_REPO) \
161 && chmod 644 $(GITHUB_REPO)/etc/default/$(GITHUB_REPO) \
162 && cp ../build/$(GITHUB_REPO).service $(GITHUB_REPO)/etc/systemd/system/
163
164 dist/$(DEB_FILENAME): _prep_fpm
165 $(EXIT_ON_ERROR) \
166 cd dist \
167 && fpm --input-type dir --output-type deb --chdir ../build/$(GITHUB_REPO) --name $(GITHUB_REPO) --version $(VERSION)
168
169 deb: dist/$(DEB_FILENAME)
170
171 dist/$(RPM_FILENAME): _prep_fpm
172 $(EXIT_ON_ERROR) \
173 cd dist \
174 && fpm --input-type dir --output-type rpm --chdir ../build/$(GITHUB_REPO) --name $(GITHUB_REPO) --version $(RPM_VERSION)
175
176 rpm: dist/$(RPM_FILENAME)
177
178 # docker:
179 # $(EXIT_ON_ERROR) sudo --non-interactive docker rmi -f $(GITHUB_ORG)/autocap:$(VERSION) || true
180 # $(EXIT_ON_ERROR) cd build && sudo --non-interactive docker build -t $(GITHUB_ORG)/autocap:$(VERSION) .
181
182 package: $(foreach os,$(OSES), package-$(os)) deb rpm docker
183
184 publish-github:
185 @echo "Publishing release to Github for version=$(VERSION)"
186
187 $(EXIT_ON_ERROR) test -n "$$(command -v github-release)" || go get github.com/aktau/github-release
188
189 $(EXIT_ON_ERROR) github-release release --user "$(GITHUB_ORG)" --repo "$(GITHUB_REPO)" --tag "$(VERSION)" --name "$(VERSION)" --description "$$(echo "$(DESCRIPTION)" | perl -pe 's/\\n/\n/g')"
190
191 $(foreach os,$(OSES), \
192 $(EXIT_ON_ERROR) \
193 github-release upload --user "$(GITHUB_ORG)" --repo "$(GITHUB_REPO)" --tag "$(VERSION)" --name "$(GITHUB_REPO)-$(VERSION)-$(os).tar.bz" --label "$(GITHUB_REPO)-$(VERSION)-$(os).tar.bz" --file "dist/$(GITHUB_REPO)-$(VERSION)-$(os).tar.bz" ; \
194 )
195
196 $(EXIT_ON_ERROR) github-release upload --user "$(GITHUB_ORG)" --repo "$(GITHUB_REPO)" --tag "$(VERSION)" --name "$(DEB_FILENAME)" --label "$(DEB_FILENAME)" --file "dist/$(DEB_FILENAME)"
197 $(EXIT_ON_ERROR) github-release upload --user "$(GITHUB_ORG)" --repo "$(GITHUB_REPO)" --tag "$(VERSION)" --name "$(RPM_FILENAME)" --label "$(RPM_FILENAME)" --file "dist/$(RPM_FILENAME)"
198
199 publish-packagecloud:
200 @echo "Publishing release to Packagecloud for version=$(VERSION)"
201
202 $(EXIT_ON_ERROR) test -n "$$(command -v pkgcloud-push)" || go get github.com/mlafeldt/pkgcloud/...
203 $(EXIT_ON_ERROR) pkgcloud-push $(GITHUB_ORG)/ops/el/7 dist/$(RPM_FILENAME)
204 $(EXIT_ON_ERROR) pkgcloud-push $(GITHUB_ORG)/ops/ubuntu/xenial dist/$(DEB_FILENAME)
205
206 publish-docker:
207 @echo "Publishing docker image to registry=$(DOCKER_REGISTRY) for version=$(VERSION)"
208
209 $(EXIT_ON_ERROR) sudo --non-interactive docker tag $(GITHUB_ORG)/autocap:$(VERSION) $(DOCKER_REGISTRY)/$(GITHUB_ORG)/autocap:$(VERSION)
210 $(EXIT_ON_ERROR) sudo --non-interactive docker push $(DOCKER_REGISTRY)/$(GITHUB_ORG)/autocap:$(VERSION)
211
212 publish-release: package publish-github publish-packagecloud publish-docker
213
214 list-targets:
215 @$(EXIT_ON_ERROR) echo "$$(echo $(TARGETS) | tr ' ' '\n')"
216
217 show-version:
218 @$(EXIT_ON_ERROR) echo $(VERSION)
219
220 clean:
221 $(EXIT_ON_ERROR) rm -rf $(foreach os,$(OSES), \
222 $(foreach target,$(TARGETS), \
223 $(target)/$(target)-$(os) \
224 ) \
225 ) \
226 $(foreach os,$(OSES), \
227 build/$(os) \
228 ) \
229 build/$(GITHUB_REPO) \
230 dist
231
232 .DEFAULT: all
233 .PHONY: all generate build $(foreach os,$(OSES), build-$(os) ) deps _prep_fpm deb rpm docker package publish-github publish-packagecloud publish-docker publish-release list-targets clean $(TARGETS)