-
Notifications
You must be signed in to change notification settings - Fork 1
/
build.bash
executable file
·299 lines (250 loc) · 9.19 KB
/
build.bash
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
#!/usr/bin/env bash
# @(#) build.bash - shell script for building docker images
#
# Copyright (C) 2018 Maricopa County Library District, All Rights Reserved.
# Releaesd under The MIT License
# https://github.com/MCLD/greatreadingadventure/blob/develop/LICENSE
#
# Second revision based on "Minimal safe Bash script template" by Maciej Radzikowski
# https://betterdev.blog/minimal-safe-bash-script-template/
set -Eeuo pipefail
trap cleanup SIGINT SIGTERM ERR EXIT
script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd -P)
usage() {
cat <<EOF
Usage: $(basename "${BASH_SOURCE[0]}") [-h] [-v] [-df Dockerfile] [-p] [Docker tag]
Build the project in the current directory using Docker.
Available options:
-h, --help Print this help and exit
-v, --verbose Print script debug info
-df, --dockerfile Use the specified Dockerfile
-p, --publish Run the release-publish.bash script in the container (if it's present)
Environment variables:
- BLD_DOCKER_IMAGE - optional - name of Docker image, uses directory name by default
- CR_HOST - optional - hostname of the container registry, defaults Docker default (Docker Hub)
- CR_OWNER - optional - owner of the container registry
- CR_PASSWORD - optional - password to log into the container registry
- CR_USER - optional - username to log in to the container registry
- GHCR_OWNER - optional - owner of the GitHub Container Registry (defaults to GHCR_USER)
- GHCR_PAT - optional - GitHub Container Registry Personal Access Token
- GHCR_USER - optional - username to log in to the GitHub Container Registry
Version 1.1.0 released 2021-12-02
EOF
exit
}
cleanup() {
trap - SIGINT SIGTERM ERR EXIT
# script cleanup here
}
setup_colors() {
if [[ -t 2 ]] && [[ -z "${NO_COLOR-}" ]] && [[ "${TERM-}" != "dumb" ]]; then
NOFORMAT='\033[0m' RED='\033[0;31m' GREEN='\033[0;32m' ORANGE='\033[0;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' YELLOW='\033[1;33m'
else
NOFORMAT='' RED='' GREEN='' ORANGE='' BLUE='' PURPLE='' CYAN='' YELLOW=''
fi
}
msg() {
echo >&2 -e "${1-}"
}
die() {
local msg=$1
local code=${2-1} # default exit status 1
msg "$msg"
exit "$code"
}
parse_params() {
dockerfile=''
publish=0
while :; do
case "${1-}" in
-h | --help) usage ;;
-v | --verbose) set -x ;;
--no-color) NO_COLOR=1 ;;
-df | --dockerfile)
dockerfile="${2-}"
shift
;;
-p | --publish)
publish=1
;;
-?*) die "Unknown option: $1" ;;
*) break ;;
esac
shift
done
readonly dockertag="${1-}"
return 0
}
parse_params "$@"
setup_colors
# Constants, variables
BLD_COMMIT=$(git rev-parse --short HEAD)
readonly BLD_COMMIT
BLD_VERSION_DATE=$(date -u +'%Y%m%d_%H%M%SZ')
readonly BLD_VERSION_DATE
BLD_PUSH=false
BLD_RELEASE=false
BLD_VERSION=unknown
BLD_RELEASE_VERSION=''
readonly BLD_STARTAT=$SECONDS
# Try getting branch from Azure DevOps
readonly AZURE_BRANCH=${BUILD_SOURCEBRANCH-}
BLD_BRANCH=''
BLD_GITBRANCH=${AZURE_BRANCH#refs/heads/}
if [[ -n $BLD_GITBRANCH ]]; then
BLD_BRANCH=$BLD_GITBRANCH
msg "${BLUE}===${NOFORMAT} Branch from Azure DevOps: $BLD_BRANCH"
fi
if [[ -z ${BLD_BRANCH} ]]; then
# Try getting branch from git
if BLD_GITBRANCH=$(git symbolic-ref --short -q HEAD); then
BLD_BRANCH=$BLD_GITBRANCH
msg "${BLUE}===${NOFORMAT} Branch from git: $BLD_BRANCH"
fi
fi
if [[ $BLD_BRANCH = "develop"
|| $BLD_BRANCH = "main"
|| $BLD_BRANCH = "master"
|| $BLD_BRANCH = "test" ]]; then
BLD_DOCKER_TAG=$BLD_BRANCH
BLD_VERSION=${BLD_BRANCH}-${BLD_VERSION_DATE}
BLD_PUSH=true
elif [[ "$BLD_BRANCH" =~ release/([0-9]+\.[0-9]+\.[0-9]+.*) ]]; then
BLD_RELEASE_VERSION=${BASH_REMATCH[1]}
BLD_DOCKER_TAG=v${BLD_RELEASE_VERSION}
BLD_VERSION=v${BLD_RELEASE_VERSION}
BLD_RELEASE=true
BLD_PUSH=true
else
BLD_DOCKER_TAG=$BLD_COMMIT
BLD_VERSION=${BLD_COMMIT}-${BLD_VERSION_DATE}
fi
# Check if we should use a different Dockerfile
if [[ -z $dockerfile ]]; then
BLD_DOCKERFILE="Dockerfile"
else
BLD_DOCKERFILE="$dockerfile"
msg "${BLUE}===${NOFORMAT} Using Dockerfile: $BLD_DOCKERFILE"
fi
# Ensure a configured Docker image name
if [[ -z ${BLD_DOCKER_IMAGE-} ]]; then
BLD_DIRECTORY=${PWD##*/}
BLD_DOCKER_IMAGE=${BLD_DIRECTORY,,}
msg "${ORANGE}===${NOFORMAT} No BLD_DOCKER_IMAGE configured, using this directory name: $BLD_DOCKER_IMAGE"
fi
# Perform release prep if necessary and script is present
if [[ $BLD_RELEASE = "true" && -f "release-prep.bash" ]]; then
msg "${BLUE}===${NOFORMAT} Running release preparation for version $BLD_RELEASE_VERSION"
#shellcheck disable=SC1091
source release-prep.bash
msg "${GREEN}===${NOFORMAT} Release preparation script complete"
fi
# If there's a specified Docker tag, use it
if [[ -n $dockertag ]]; then
BLD_DOCKER_TAG="$dockertag"
msg "${BLUE}===${NOFORMAT} Using specified Docker tag $BLD_DOCKER_TAG"
fi
# Construct complete Docker image and tag from provided values
BLD_DOCKER_LATEST=${BLD_DOCKER_IMAGE}:latest
BLD_DOCKER_IMAGE=${BLD_DOCKER_IMAGE}:${BLD_DOCKER_TAG}
BLD_FULL_DOCKER_IMAGE=${BLD_DOCKER_IMAGE}
BLD_FULL_DOCKER_LATEST=${BLD_DOCKER_LATEST}
if [[ -n ${CR_OWNER-} ]]; then
msg "${BLUE}===${NOFORMAT} Adding container registry owner $CR_OWNER"
BLD_FULL_DOCKER_IMAGE=${CR_OWNER}/${BLD_FULL_DOCKER_IMAGE}
BLD_FULL_DOCKER_LATEST=${CR_OWNER}/${BLD_FULL_DOCKER_LATEST}
fi
if [[ -n ${CR_HOST-} ]]; then
msg "${BLUE}===${NOFORMAT} Adding container registry host $CR_HOST"
BLD_FULL_DOCKER_IMAGE=${CR_HOST}/${BLD_FULL_DOCKER_IMAGE}
BLD_FULL_DOCKER_LATEST=${CR_HOST}/${BLD_FULL_DOCKER_LATEST}
fi
msg "${BLUE}===${NOFORMAT} Building branch $BLD_BRANCH commit $BLD_COMMIT as Docker image $BLD_FULL_DOCKER_IMAGE"
msg "${BLUE}===${NOFORMAT} Image version: $BLD_VERSION"
if [[ $BLD_PUSH = true ]]; then
docker build -f "$BLD_DOCKERFILE" -t "$BLD_FULL_DOCKER_IMAGE" \
--build-arg BRANCH="$BLD_BRANCH" \
--build-arg IMAGE_CREATED="$BLD_VERSION_DATE" \
--build-arg IMAGE_REVISION="$BLD_COMMIT" \
--build-arg IMAGE_VERSION="$BLD_VERSION" .
msg "${GREEN}===${NOFORMAT} Docker image built"
dockeruser=${CR_USER-}
dockerpass=${CR_PASSWORD-}
if [[ -z $dockeruser || -z $dockerpass ]]; then
msg "${ORANGE}===${NOFORMAT} Not pushing Docker image: username or password not specified"
else
msg "${BLUE}===${NOFORMAT} Authenticating..."
if [[ -z ${CR_HOST-} ]]; then
echo "$dockerpass" | \
docker login -u "$dockeruser" --password-stdin || exit $?
else
echo "$dockerpass" | \
docker login -u "$dockeruser" --password-stdin "${CR_HOST-}" || exit $?
fi
msg "${BLUE}===${NOFORMAT} Pushing image $BLD_FULL_DOCKER_IMAGE"
docker push "$BLD_FULL_DOCKER_IMAGE"
if [[ $BLD_RELEASE = "true" ]]; then
msg "${BLUE}===${NOFORMAT} Tagging and pushing $BLD_FULL_DOCKER_LATEST"
docker tag "$BLD_FULL_DOCKER_IMAGE" "$BLD_FULL_DOCKER_LATEST"
docker push "$BLD_FULL_DOCKER_LATEST"
fi
msg "${GREEN}===${NOFORMAT} Docker image pushed"
msg "${BLUE}===${NOFORMAT} Executing logout"
if [[ -z ${CR_HOST-} ]]; then
docker logout
else
docker logout "${CR_HOST-}"
fi
fi
ghcruser=${GHCR_USER-}
if [[ -n $ghcruser ]]; then
ghcrowner=${GHCR_OWNER-}
if [[ -z $ghcrowner ]]; then
ghcrowner=$ghcruser
fi
msg "${BLUE}===${NOFORMAT} Pushing image to ghcr.io/${ghcrowner}/${BLD_DOCKER_IMAGE}"
docker tag "${BLD_FULL_DOCKER_IMAGE}" "ghcr.io/${ghcrowner}/${BLD_DOCKER_IMAGE}"
echo "$GHCR_PAT" | \
docker login ghcr.io -u "${ghcruser}" --password-stdin || exit $?
docker push "ghcr.io/${ghcrowner}/${BLD_DOCKER_IMAGE}"
if [[ $BLD_RELEASE = "true" ]]; then
msg "${BLUE}===${NOFORMAT} Tagging and pushing ghcr.io/${ghcrowner}/${BLD_DOCKER_LATEST}"
docker tag "${BLD_FULL_DOCKER_IMAGE}" "ghcr.io/${ghcrowner}/${BLD_DOCKER_LATEST}"
docker push "ghcr.io/${ghcrowner}/${BLD_DOCKER_LATEST}"
fi
docker logout ghcr.io
msg "${GREEN}===${NOFORMAT} Docker image pushed to ghcr.io"
fi
# Perform release publish in the Docker machine if configuration is present
if [[ $BLD_RELEASE = "true" && -f "release-publish.bash" && publish -eq 1 ]]; then
msg "${BLUE}===${NOFORMAT} Publishing release package for $BLD_RELEASE_VERSION"
mkdir -p publish
if [[ -f "release.env" ]]; then
docker run -i \
--rm \
--entrypoint "/app/release-publish.bash" \
--env-file release.env \
-e BLD_RELEASE_VERSION="$BLD_RELEASE_VERSION" \
-v "${PWD}/package:/package" \
"$BLD_FULL_DOCKER_IMAGE"
else
docker run -i \
--rm \
--entrypoint "/app/release-publish.bash" \
-e BLD_RELEASE_VERSION="$BLD_RELEASE_VERSION" \
-v "${PWD}/package:/package" \
"$BLD_FULL_DOCKER_IMAGE"
fi
msg "${GREEN}===${NOFORMAT} Publish script complete"
fi
else
docker build -f "$BLD_DOCKERFILE" -t "$BLD_FULL_DOCKER_IMAGE" \
--build-arg BRANCH="$BLD_BRANCH" \
--build-arg IMAGE_CREATED="$BLD_VERSION_DATE" \
--build-arg IMAGE_REVISION="$BLD_COMMIT" \
--build-arg IMAGE_VERSION="$BLD_VERSION" \
--target build .
msg "${GREEN}===${NOFORMAT} Docker image built"
msg "${ORANGE}===${NOFORMAT} Not pushing Docker image: branch is not develop, main, test, or versioned release"
fi
msg "${PURPLE}===${NOFORMAT} Build script complete in $((SECONDS - BLD_STARTAT)) seconds."