generated from adrienaury/go-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
build.yml
407 lines (388 loc) · 16.8 KB
/
build.yml
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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
default: "help"
expose:
[
"help",
"info",
"promote",
"refresh",
"compile",
"lint",
"test",
"release",
"test-int",
"publish",
"docker",
"docker-tag",
"docker-push",
"license",
]
configuration: ["~/.dockerhub.yml", "~/.github.yml"] # DO NOT COMMIT THESE FILES
# ~/.dockerhub.yml should contains:
# DOCKERHUB_USER: <your dockerhub user>
# DOCKERHUB_PASS: <your dockerhub password or a dockerhub token>
# ~/.github.yml should contains:
# GITHUB_TOKEN: <your github token>
properties:
# Build Configuration (edit this section to override default values)
BY: "" # Leave empty to default to the user.email property in git configuration
MODULE: "" # Leave empty to default to the git remote url (e.g. "github.com/<usename>/<reponame>")
PROJECT: "" # Leave empty to default to the git repository name (e.g. "<reponame>")
LDFLAGS: "" # Add custom standard ldflags, will be applied everywhere everytime
BUILD_DIR: "bin" # Subfolder where the build will output, should be ignored by .gitignore
# Build parameters (use the -props flag or change these default values)
tag: "" # Default to the current branch or tag, can be overriden
latest: false # Do not tag the Docker image with latest, specify othewise with `-props "{latest: true}"`
ldflags: "" # Specify a additional ldflags with `-props "{ldflags: '<flags>'}"`
buildpaths: [] # By default, all paths under the cmd/ folder are built, specify a different folder list with `-props "{buildpaths: ["other/path", "to/build"]}"`
linters: [] # List of linters to run on the lint target, if left empty : run all linters
lintersno: # List of linters to exclude on running the lint target
[
"scopelint",
"interfacer",
"maligned",
"forbidigo",
"gci",
"golint",
"wrapcheck",
"gosec",
]
snapshot: false # If true, do not upload release when publish target is used
dockerfiles: # List of Dockerfiles to build, defined by a map of {key=Dockerfile name ; value=path to build context}, the image name will be determined by the extension of the Dockerfile
Dockerfile: . # Build a file named Dockerfile at the root of the workspace, will produce image name "<DOCKERHUB_USER>/<PROJECT>"
Dockerfile.webserver: . # Build a file named Dockerfile.webserver at the root of the workspace, will produce image name "<DOCKERHUB_USER>/<PROJECT>-webserver"
noticefile: "NOTICE.md" # Path and name of the file generated by the license target.
license: # License scanning parameters, see https://github.com/mitchellh/golicense#configuration-file for more info
allow: [] # example: ["MIT", "Apache-2.0"]
deny: [] # example: ["LGPL-2.1"]
override: {} # example: github.com/rs/zerolog: LGPL-2.1
translate: {} # example: gopkg.in/foo/bar.v2: github.com/foo/bar
shell: ["zsh", "-c"]
targets:
help:
doc: "Print this message"
steps:
# - $: 'neon -info' => incorrect order, issue to open
- $: |
print -P "%BAvailable targets%b"
print
print -P "%B%F{blue}help%f%b Print this message"
print -P "%B%F{blue}info%f%b Print build informations"
print -P "%B%F{blue}promote%f%b Promote the project with a new tag based on git log history"
print -P "%B%F{blue}refresh%f%b Refresh go modules (add missing and remove unused modules) [info]"
print -P "%B%F{blue}compile%f%b Compile binary files locally [info->refresh]"
print -P "%B%F{blue}lint%f%b Examine source code and report suspicious constructs [info->refresh]"
print -P "%B%F{blue}test%f%b Run all tests with coverage [info->refresh->lint]"
print -P "%B%F{blue}release%f%b Compile binary files for production [info->refresh->lint->test]"
print -P "%B%F{blue}test-int%f%b Run all integration tests [info->refresh->lint->test->release]"
print -P "%B%F{blue}publish%f%b Publish tagged binary to Github [info->refresh->lint->test->release->test-int]"
print -P "%B%F{blue}docker%f%b Build docker images [info]"
print -P "%B%F{blue}docker-tag%f%b Tag docker images [info->docker]"
print -P "%B%F{blue}docker-push%f%b Publish docker images to Dockerhub [info->docker->docker-tag]"
print -P "%B%F{blue}license%f%b Scan licenses from binaries and generate notice file [info->refresh->compile]"
print
print -P "%BExample:%b neon -props '{latest: true}' promote publish docker-push"
print
print -P "%BTarget dependencies%b"
print
print -P "→ help"
print -P "→ promote"
print -P "→ info ┰ docker → docker-tag → docker-push"
print -P " ┖ refresh ┰ compile → license"
print -P " ┖ lint → test → release → test-int → publish"
info:
doc: "Print build informations"
steps:
- $: mkdir -p ={BUILD_DIR}
- if: tag == ""
then:
- $: "git describe --tags --exact-match 2>/dev/null || git symbolic-ref -q --short HEAD"
1=: "tag"
3x: true
else:
- $: "echo -n ={tag}"
1=: "tag"
3x: true
- $: 'echo -n "={tag}" | sed -e s/^v//'
1=: "version"
3x: true
- $: "git rev-parse HEAD 2>/dev/null"
1=: "commit"
3x: true
- "date = now()[0:10]"
- if: BY == ""
then:
- $: "git config user.email"
1=: "by"
3x: true
else:
- $: "echo -n ={BY}"
1=: "by"
3x: true
- $: 'if expr match "={version}" "v\?[0-9]\+\.[0-9]\+\.[0-9]\+" 1>/dev/null 2>&1; then echo -n "yes"; else echo -n "no"; fi'
1=: "is_release"
3x: true
- $: "cut -f1 -d."
<: "=version"
1=: "version_major"
3x: true
- $: "cut -f2 -d."
<: "=version"
1=: "version_minor"
3x: true
- $: "cut -f3 -d."
<: "=version"
1=: "version_patch"
3x: true
- if: MODULE == ""
then:
- $: "git config --local remote.origin.url | sed -n 's#^.*//\\(.*\\)\\.git$#\\1#p' | tr '[:upper:]' '[:lower:]'" # .*//(.*)\.git => https://github.com/<user>/<repo>.git => github.com/<user>/<repo>
1=: "mod"
3x: true
else:
- $: "echo -n ={MODULE}"
1=: "mod"
3x: true
- if: PROJECT == ""
then:
- $: "cut -f3 -d/"
<: "=mod"
1=: "project"
3x: true
else:
- $: "echo -n ={PROJECT}"
1=: "project"
3x: true
- print: |-
MODULE = ={mod}
PROJECT = ={project}
TAG = ={tag}
COMMIT = ={commit}
DATE = ={date}
BY = ={by}
RELEASE = ={is_release}
- if: 'is_release == "yes"'
then:
- print: |-
VERSION = ={version_major}.={version_minor}.={version_patch}
promote:
doc: "Promote the project with a new tag based on git log history"
steps:
- if: tag==""
then:
- $: svu next || echo -n v0.1.0
3x: true
1=: tag
- $: "git tag ={tag}"
2x: true
- $: "echo Promoted to ={tag}"
refresh:
doc: "Refresh go modules (add missing and remove unused modules)"
depends: "info"
steps:
- if: "!exists('go.mod')"
then:
- $: "go mod init ={mod}"
- $: "go mod tidy"
# run "neon -props '{buildpaths: ["path/to/main/package1","path/to/main/package2"]}' compile" to compile specific targets
# example : neon -props '{buildpaths: ["cmd/cli"]}' compile
compile:
doc: "Compile binary files locally"
depends: ["info", "refresh"]
steps:
- ldflags = ldflags + " -X main.version=" + tag + " -X main.commit=" + commit + " -X main.buildDate=" + date + " -X main.builtBy=" + by
- if: len(buildpaths) == 0
then:
- buildpaths = appendpath("cmd", find("cmd", "*"))
- for: path
in: buildpaths
do:
- print: Building ={path}
- |
pathcomponents = split(unixpath(path), "/")
name = pathcomponents[len(pathcomponents)-1]
- $: go build -ldflags "-X main.name=={name} ={ldflags} ={LDFLAGS}" -o ./={BUILD_DIR}/={name} ./={path}
lint:
doc: "Examine source code and report suspicious constructs"
depends: ["info", "refresh"]
steps:
- if: len(linters) == 0
then:
- $: golangci-lint run --enable-all ={replace(join(appendpath("--disable", lintersno), " "), "/", " ")}
:: true
else:
- $: golangci-lint run ={replace(join(appendpath("--enable", linters), " "), "/", " ")} ={replace(join(appendpath("--disable", lintersno), " "), "/", " ")}
:: true
test:
doc: "Run all tests with coverage"
depends: ["info", "refresh", "lint"]
steps:
- $: go test -coverprofile=./={BUILD_DIR}/coverage.txt -covermode=atomic ./...
bench:
doc: "Run all bench"
depends: ["info", "refresh"]
steps:
- $: go test -bench=. -benchmem ./... -run=^# -benchtime=10s | tee ./={BUILD_DIR}/benchstats.txt
# run "neon -props '{buildpaths: ["path/to/main/package1","path/to/main/package2"]}' release" to release specific targets
# example : neon -props '{buildpaths: ["cmd/cli"]}' release
release:
doc: "Compile binary files for production"
depends: ["info", "refresh", "lint", "test"]
steps:
- ldflags = ldflags + " -s -w" # Omit the DWARF symbol table. Omit the symbol table and debug information.
- call: compile
test-int:
doc: "Run all integration tests"
depends: ["info", "refresh", "lint", "test", "release", "bench"]
steps:
- $: venom run test/suites/*
# run "neon -props '{buildpaths: ["path/to/main/package1","path/to/main/package2"]}' publish" to publish specific targets
# example : neon -props '{buildpaths: ["cmd/cli"]}' publish
publish:
doc: "Publish tagged binaries to Github"
depends: ["info", "refresh", "lint", "test", "release", "test-int"]
steps:
- if: len(buildpaths) == 0
then:
- buildpaths = appendpath("cmd", find("cmd", "*"))
- ldflags = ldflags + " -s -w" # Omit the DWARF symbol table. Omit the symbol table and debug information.
- ldflags = ldflags + " -X main.version=" + tag + " -X main.commit=" + commit + " -X main.buildDate=" + date + " -X main.builtBy=" + by
- $: (export LDFLAGS="={ldflags}"; export BUILDPATHS="={buildpaths}"; cat .goreleaser.template.yml | gomplate)
1>: ={BUILD_DIR}/.goreleaser.yml
1x: true
- if: snapshot
then:
- $: goreleaser release -f ={BUILD_DIR}/.goreleaser.yml --rm-dist --snapshot
else:
- $: (export GITHUB_TOKEN=={GITHUB_TOKEN}; goreleaser release -f ={BUILD_DIR}/.goreleaser.yml --rm-dist)
- $: go mod tidy
# run "neon -props '{dockerfiles: {"path/to/Dockerfile1": "path/to/root/build/context"}}' docker" to build specific Dockerfiles
# example : neon -props '{dockerfiles: {"Dockerfile": "."}}' docker
docker:
doc: "Build docker images"
depends: ["info"]
steps:
- try:
- $: "# ={DOCKERHUB_USER}"
3x: true
catch:
- print: |
To use this target, make sure your DOCKERHUB_USER is set in the file ~/.dockerhub.yml
The content of the file should be :
DOCKERHUB_USER: <your dockerhub user>
DOCKERHUB_PASS: <your dockerhub password or a dockerhub token>
- $: return 1
- for: key
in: keys(dockerfiles)
do:
- |
keycomponents = split(key, ".")
suffix = ""
if len(keycomponents) > 1 {
suffix = "-" + keycomponents[len(keycomponents)-1]
}
- $: "sudo docker build -q --iidfile ={BUILD_DIR}/last-={key} -t ={DOCKERHUB_USER}/={project}={suffix}:={tag} -f ={key} ={dockerfiles[key]}"
1x: true
- $: "sudo docker images --no-trunc | grep $(cat ={BUILD_DIR}/last-={key})"
# run "neon -props '{latest: true}' docker-tag" to include latest tag
docker-tag:
doc: "Tag docker images"
# unless: 'is_release != "yes"' => is_release unknown variable, issue to open
depends: ["info", "docker"]
steps:
- if: 'is_release == "yes"'
then:
- try:
- $: "# ={DOCKERHUB_USER}"
3x: true
catch:
- print: |
To use this target, make sure your credentials are set in the file ~/.dockerhub.yml
The content of the file should be :
DOCKERHUB_USER: <your dockerhub user>
DOCKERHUB_PASS: <your dockerhub password or a dockerhub token>
- $: return 1
- for: key
in: keys(dockerfiles)
do:
- |
keycomponents = split(key, ".")
suffix = ""
if len(keycomponents) > 1 {
suffix = "-" + keycomponents[len(keycomponents)-1]
}
- $: "sudo docker tag ={DOCKERHUB_USER}/={project}={suffix}:={tag} ={DOCKERHUB_USER}/={project}={suffix}:v={version_major}"
- $: "sudo docker tag ={DOCKERHUB_USER}/={project}={suffix}:={tag} ={DOCKERHUB_USER}/={project}={suffix}:v={version_major}.={version_minor}"
- if: "latest"
then:
- $: "sudo docker tag ={DOCKERHUB_USER}/={project}={suffix}:={tag} ={DOCKERHUB_USER}/={project}={suffix}:latest"
- $: "sudo docker images --no-trunc | grep $(cat ={BUILD_DIR}/last-={key})"
else:
- print: "Skipping release target (not a release)"
color: red
docker-login:
steps:
- try:
- $: "sudo docker login -u ={DOCKERHUB_USER} -p ={DOCKERHUB_PASS}"
2x: true
catch:
- print: |
To use this target, make sure your credentials are valid in the file ~/.dockerhub.yml
The content of the file should be :
DOCKERHUB_USER: <your dockerhub user>
DOCKERHUB_PASS: <your dockerhub password or a dockerhub token>
- $: return 1
# run "neon -props '{latest: true}' docker-push" to include latest tag
docker-push:
doc: "Push docker images to Dockerhub"
# unless: 'is_release != "yes"' => is_release unknown variable, issue to open
depends: ["docker", "docker-tag", "docker-login"]
steps:
- if: 'is_release == "yes"'
then:
- for: key
in: keys(dockerfiles)
do:
- |
keycomponents = split(key, ".")
suffix = ""
if len(keycomponents) > 1 {
suffix = "-" + keycomponents[len(keycomponents)-1]
}
- $: "sudo docker push ={DOCKERHUB_USER}/={project}={suffix}:v={version_major}"
- $: "sudo docker push ={DOCKERHUB_USER}/={project}={suffix}:v={version_major}.={version_minor}"
- $: "sudo docker push ={DOCKERHUB_USER}/={project}={suffix}:v={version_major}.={version_minor}.={version_patch}"
- if: "latest"
then:
- $: "sudo docker push ={DOCKERHUB_USER}/={project}={suffix}:latest"
else:
- print: "Skipping release target (not a release)"
color: red
license:
doc: "Scan licenses from binaries and generate notice file"
depends: ["info", "refresh", "compile"]
steps:
- $: echo -e "# 3rd-Party Software Licenses\n" > ={noticefile}
- $: echo "The following 3rd-party software components may be used by or distributed with this project. Any information relevant to third-party vendors listed below are collected using common, reasonable means." >> ={noticefile}
- try:
- $: echo -n "={GITHUB_TOKEN}"
1=: token
3x: true
catch:
- print: |
This target works better if a valid GITHUB_TOKEN is defined in the file ~/.github.yml (without it you might reach the maximum call/hour limit of the GitHub API)
The content of the file should be :
GITHUB_TOKEN: <your github token>
- token=""
- write: ={BUILD_DIR}/license.json
text: ={jsonencode(license)}
- for: path
in: buildpaths
do:
- |
pathcomponents = split(unixpath(path), "/")
name = pathcomponents[len(pathcomponents)-1]
- print: Scanning ={name}
- $: |
echo -e "\n## ={name}\n" >> ={noticefile}
set -o pipefail errexit
(export GITHUB_TOKEN=={token}; golicense -plain ={BUILD_DIR}/license.json ={BUILD_DIR}/={name} | awk '{ printf "{\"module\":\"%s\"", $1; $1=""; gsub("\"","\\\"",$0); printf ",\"license\":\"%s\"}\n", substr($0,2) }' | mlr --ijson --omd sort -f module then cat >> ={noticefile})