-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbuild.sh
More file actions
executable file
·194 lines (165 loc) · 4.78 KB
/
Copy pathbuild.sh
File metadata and controls
executable file
·194 lines (165 loc) · 4.78 KB
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
#!/usr/bin/env bash
#
# Rebuild the sandbox template images in this repo and load them into sbx.
set -euo pipefail
ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
usage() {
cat <<'EOF'
Usage: ./build.sh [STACK...] [--build-only] [--prune]
Stacks (default: all three shipping ones):
swift swift/ -> swift-sbx:1
ts, typescript typescript/ -> typescript-sbx:1
py, python python/ -> python-sbx:1
sbx sbx/ -> sbx-sbx:1 (this repo's own; name it explicitly)
Options:
--build-only stop after `docker build`; no tar, no `sbx template load`.
The only mode that works inside a sandbox, where sbx's daemon
has no KVM to run on.
--prune run `docker builder prune -af` after all stacks are done
-h show this help
EOF
}
resolve_stack() {
case $1 in
swift) printf 'swift' ;;
ts | typescript) printf 'typescript' ;;
py | python) printf 'python' ;;
sbx) printf 'sbx' ;;
*) return 1 ;;
esac
}
PRUNE=0
BUILD_ONLY=0
STACKS=()
for arg in "$@"; do
case $arg in
--build-only)
BUILD_ONLY=1
;;
--prune)
PRUNE=1
;;
-h | --help)
usage
exit 0
;;
-*)
printf 'build.sh: unknown option: %s\n\n' "$arg" >&2
usage >&2
exit 2
;;
*)
if ! dir=$(resolve_stack "$arg"); then
printf 'build.sh: unknown stack: %s\n\n' "$arg" >&2
usage >&2
exit 2
fi
# `./build.sh ts typescript` names one stack twice; no point building it twice.
if [[ " ${STACKS[*]:-} " != *" $dir "* ]]; then
STACKS+=("$dir")
fi
;;
esac
done
if [[ ${#STACKS[@]} -eq 0 ]]; then
STACKS=(swift typescript python)
fi
if ! command -v docker >/dev/null 2>&1; then
printf 'build.sh: docker not found on PATH\n' >&2
exit 1
fi
# Only `sbx template load` truly needs sbx, so --build-only can do without it.
# Kit validation still runs whenever sbx is around, which in the sbx template it is.
HAVE_SBX=1
if ! command -v sbx >/dev/null 2>&1; then
if [[ $BUILD_ONLY -eq 0 ]]; then
printf 'build.sh: sbx not found on PATH\n' >&2
exit 1
fi
HAVE_SBX=0
printf 'build.sh: sbx not found, skipping kit validation\n' >&2
fi
if ! docker info >/dev/null 2>&1; then
printf 'build.sh: cannot talk to the Docker daemon - is Docker Desktop running?\n' >&2
exit 1
fi
if [[ $HAVE_SBX -eq 1 ]]; then
if ! sbx kit validate "$ROOT/shared/kit" >/dev/null; then
printf 'build.sh: shared/kit failed `sbx kit validate`\n' >&2
exit 1
fi
# Optional, and a stale one breaks `sbx create` rather than the build.
if [[ -f "$ROOT/local/kit/spec.yaml" ]]; then
if ! sbx kit validate "$ROOT/local/kit" >/dev/null; then
printf 'build.sh: local/kit failed `sbx kit validate`\n' >&2
exit 1
fi
fi
fi
for dir in "${STACKS[@]}"; do
if [[ ! -f "$ROOT/$dir/Dockerfile" ]]; then
printf 'build.sh: %s/Dockerfile is missing\n' "$dir" >&2
exit 1
fi
if [[ $HAVE_SBX -eq 1 ]] && ! sbx kit validate "$ROOT/$dir/kit" >/dev/null; then
printf 'build.sh: %s/kit failed `sbx kit validate`\n' "$dir" >&2
exit 1
fi
done
# So an interrupted run never leaves a multi-GB tar behind.
CURRENT_TAR=""
cleanup() {
if [[ -n $CURRENT_TAR && -f $CURRENT_TAR ]]; then
rm -f -- "$CURRENT_TAR"
fi
}
trap cleanup EXIT
# Failures are explicit: `set -e` is suppressed inside an `if` condition.
build_stack() {
local dir=$1
local tag="$dir-sbx:1"
local tar="$ROOT/$dir-sbx.tar"
printf '\n==> %s: building %s\n' "$dir" "$tag"
# The context is the repo root: the Dockerfiles COPY from shared/.
docker build --load -t "$tag" -f "$ROOT/$dir/Dockerfile" "$ROOT" || return 1
if [[ $BUILD_ONLY -eq 1 ]]; then
printf '==> %s: --build-only, leaving %s in the Docker image store\n' "$dir" "$tag"
return 0
fi
printf '==> %s: exporting to %s\n' "$dir" "$tar"
docker image save "$tag" -o "$tar" || return 1
printf '==> %s: loading into sbx\n' "$dir"
sbx template load "$tar" || return 1
# The template is loaded by now, so cleanup trouble only warrants a warning.
printf '==> %s: removing the Docker image and the tar\n' "$dir"
docker image rm "$tag" >/dev/null ||
printf '==> %s: warning: could not remove the Docker image %s\n' "$dir" "$tag" >&2
rm -f -- "$tar" ||
printf '==> %s: warning: could not remove %s\n' "$dir" "$tar" >&2
}
FAILED=()
for dir in "${STACKS[@]}"; do
CURRENT_TAR="$ROOT/$dir-sbx.tar"
if build_stack "$dir"; then
printf '==> %s: done\n' "$dir"
else
printf '==> %s: FAILED\n' "$dir" >&2
FAILED+=("$dir")
rm -f -- "$CURRENT_TAR"
fi
CURRENT_TAR=""
done
if [[ $PRUNE -eq 1 ]]; then
printf '\n==> pruning the Docker build cache\n'
docker builder prune -af
fi
printf '\n'
if [[ ${#FAILED[@]} -gt 0 ]]; then
printf 'Failed: %s\n' "${FAILED[*]}"
exit 1
fi
if [[ $BUILD_ONLY -eq 1 ]]; then
printf 'Images built, not loaded (--build-only). `docker image ls` to confirm.\n'
else
printf 'Templates loaded. `sbx template ls` to confirm.\n'
fi