...
1#!/bin/sh
2set -eu
3if [ ! -e "$(dirname "$0")/../../ci/sub/.git" ]; then
4 set -x
5 git submodule update --init
6 set +x
7fi
8. "$(dirname "$0")/../../ci/sub/lib.sh"
9cd -- "$(dirname "$0")/../.."
10
11help() {
12 cat <<EOF
13usage: $0 [--rebuild] [--local] [--dry-run] [--run=regex] [--host-only] [--lockfile-force]
14 [--install] [--uninstall]
15
16$0 builds D2 release archives into ./ci/release/build/<version>/d2-<VERSION>-<OS>-<ARCH>.tar.gz
17
18The version is detected via git describe which will use the git tag for the current
19commit if available.
20
21Flags:
22
23--rebuild
24 By default build.sh will avoid rebuilding finished assets if they already exist but if you
25 changed something and need to force rebuild, use this flag.
26
27--local
28 By default build.sh uses \$CI_D2_LINUX_AMD64, \$CI_D2_LINUX_ARM64,
29 \$CI_D2_MACOS_AMD64 and \$CI_D2_MACOS_ARM64 to build the release
30 archives. It's required for now due to the following issue:
31 https://github.com/terrastruct/d2/issues/31
32 With --local, build.sh will cross compile locally. warning: This is only for testing
33 purposes, do not use in production!
34
35--host-only
36 Use to build the release archive for the host OS-ARCH only. All logging is done to stderr
37 so in a script you can read from stdout to get the path to the release archive.
38
39--run=regex
40 Use to run only the OS-ARCH jobs that match the given regex. e.g. --run=linux only runs
41 the linux jobs. --run=linux-amd64 only runs the linux-amd64 job.
42
43--version vX.X.X
44 Use to overwrite the version detected from git.
45
46--lockfile-force
47 Forcefully take ownership of remote builder lockfiles.
48
49--install
50 Ensure a release using --host-only and install it.
51
52--uninstall
53 Ensure a release using --host-only and uninstall it.
54
55--push-docker
56 Push the built docker image. Unfortunately dockerx requires the multi-arch images be
57 pushed if required in the same invocation as build. dockerx cannot load multi-arch
58 images into the daemon for push later. It's not slow though to use --push-docker after
59 building the image as nearly all artifacts are cached.
60 Automatically set if called from release.sh
61
62--latest-docker
63 Mark the built image with the latest tag. Automatically set if called from release.sh
64EOF
65}
66
67main() {
68 while flag_parse "$@"; do
69 case "$FLAG" in
70 h|help)
71 help
72 return 0
73 ;;
74 rebuild)
75 flag_noarg && shift "$FLAGSHIFT"
76 REBUILD=1
77 ;;
78 local)
79 flag_noarg && shift "$FLAGSHIFT"
80 LOCAL=1
81 ;;
82 dry-run)
83 flag_noarg && shift "$FLAGSHIFT"
84 DRY_RUN=1
85 ;;
86 run)
87 flag_reqarg && shift "$FLAGSHIFT"
88 JOBFILTER=$FLAGARG
89 ;;
90 host-only)
91 flag_noarg && shift "$FLAGSHIFT"
92 HOST_ONLY=1
93 LOCAL=1
94 ;;
95 version)
96 flag_nonemptyarg && shift "$FLAGSHIFT"
97 VERSION=$FLAGARG
98 ;;
99 lockfile-force)
100 flag_noarg && shift "$FLAGSHIFT"
101 LOCKFILE_FORCE=1
102 ;;
103 install)
104 flag_noarg && shift "$FLAGSHIFT"
105 INSTALL=1
106 HOST_ONLY=1
107 LOCAL=1
108 ;;
109 uninstall)
110 flag_noarg && shift "$FLAGSHIFT"
111 UNINSTALL=1
112 HOST_ONLY=1
113 LOCAL=1
114 ;;
115 push-docker)
116 flag_noarg && shift "$FLAGSHIFT"
117 PUSH_DOCKER=1
118 ;;
119 latest-docker)
120 flag_noarg && shift "$FLAGSHIFT"
121 LATEST_DOCKER=1
122 ;;
123 *)
124 flag_errusage "unrecognized flag $FLAGRAW"
125 ;;
126 esac
127 done
128 shift "$FLAGSHIFT"
129 if [ $# -gt 0 ]; then
130 flag_errusage "no arguments are accepted"
131 fi
132
133 VERSION=${VERSION:-$(git_describe_ref)}
134 BUILD_DIR=ci/release/build/$VERSION
135 sh_c mkdir -p "$BUILD_DIR"
136 sh_c rm -f ci/release/build/latest
137 sh_c ln -s "$VERSION" ci/release/build/latest
138 if [ -n "${HOST_ONLY-}" ]; then
139 ensure_os
140 ensure_arch
141 runjob "$OS/$ARCH" "build"
142
143 if [ -n "${INSTALL-}" ]; then
144 sh_c make -sC "ci/release/build/$VERSION/$OS-$ARCH/d2-$VERSION" install
145 elif [ -n "${UNINSTALL-}" ]; then
146 sh_c make -sC "ci/release/build/$VERSION/$OS-$ARCH/d2-$VERSION" uninstall
147 fi
148 return 0
149 fi
150
151 runjob linux/amd64 'OS=linux ARCH=amd64 build' &
152 runjob linux/arm64 'OS=linux ARCH=arm64 build' &
153 runjob macos/amd64 'OS=macos ARCH=amd64 build' &
154 runjob macos/arm64 'OS=macos ARCH=arm64 build' &
155 runjob windows/amd64 'OS=windows ARCH=amd64 build' &
156 runjob windows/arm64 'OS=windows ARCH=arm64 build' &
157 waitjobs
158
159 runjob linux/docker build_docker &
160 runjob windows/amd64/msi 'OS=windows ARCH=amd64 build_windows_msi' &
161 waitjobs
162}
163
164build() {
165 HW_BUILD_DIR="$BUILD_DIR/$OS-$ARCH/d2-$VERSION"
166 ARCHIVE="$BUILD_DIR/d2-$VERSION-$OS-$ARCH.tar.gz"
167
168 if [ -e "$ARCHIVE" -a -z "${REBUILD-}" ]; then
169 log "skipping as already built at $ARCHIVE"
170 return 0
171 fi
172
173 if [ -n "${LOCAL-}" ]; then
174 build_local
175 return 0
176 fi
177
178 case $OS in
179 macos)
180 case $ARCH in
181 amd64)
182 REMOTE_HOST=$CI_D2_MACOS_AMD64 build_remote_macos
183 ;;
184 arm64)
185 REMOTE_HOST=$CI_D2_MACOS_ARM64 build_remote_macos
186 ;;
187 *)
188 warn "no builder for OS=$OS ARCH=$ARCH, building locally..."
189 build_local
190 ;;
191 esac
192 ;;
193 linux)
194 case $ARCH in
195 amd64)
196 REMOTE_HOST=$CI_D2_LINUX_AMD64 build_remote_linux
197 ;;
198 arm64)
199 REMOTE_HOST=$CI_D2_LINUX_ARM64 build_remote_linux
200 ;;
201 *)
202 warn "no builder for OS=$OS ARCH=$ARCH, building locally..."
203 build_local
204 ;;
205 esac
206 ;;
207 *)
208 warn "no builder for OS=$OS, building locally..."
209 build_local
210 ;;
211 esac
212}
213
214build_local() {
215 export DRY_RUN \
216 HW_BUILD_DIR \
217 VERSION \
218 OS \
219 ARCH \
220 ARCHIVE
221 sh_c ./ci/release/_build.sh
222}
223
224build_remote_macos() {(
225 sh_c lockfile_ssh "$REMOTE_HOST" .d2-build-lock
226 sh_c gitsync "$REMOTE_HOST" src/d2
227 sh_c ssh "$REMOTE_HOST" "COLOR=${COLOR-} \
228TERM=${TERM-} \
229DRY_RUN=${DRY_RUN-} \
230HW_BUILD_DIR=$HW_BUILD_DIR \
231VERSION=$VERSION \
232OS=$OS \
233ARCH=$ARCH \
234ARCHIVE=$ARCHIVE \
235PATH=\\\"/usr/local/bin:/usr/local/sbin:/opt/homebrew/bin:/opt/homebrew/sbin\\\${PATH+:\\\$PATH}\\\" \
236./src/d2/ci/release/_build.sh"
237 sh_c mkdir -p "$HW_BUILD_DIR"
238 sh_c rsync --archive --human-readable "$REMOTE_HOST:src/d2/$ARCHIVE" "$ARCHIVE"
239)}
240
241build_remote_linux() {(
242 sh_c lockfile_ssh "$REMOTE_HOST" .d2-build-lock
243 sh_c gitsync "$REMOTE_HOST" src/d2
244 sh_c ssh "$REMOTE_HOST" "COLOR=${COLOR-} \
245TERM=${TERM-} \
246DRY_RUN=${DRY_RUN-} \
247HW_BUILD_DIR=$HW_BUILD_DIR \
248VERSION=$VERSION \
249OS=$OS \
250ARCH=$ARCH \
251ARCHIVE=$ARCHIVE \
252./src/d2/ci/release/build_in_docker.sh"
253 sh_c mkdir -p "$HW_BUILD_DIR"
254 sh_c rsync --archive --human-readable "$REMOTE_HOST:src/d2/$ARCHIVE" "$ARCHIVE"
255)}
256
257build_docker() {
258 if [ -n "${LOCAL-}" ]; then
259 sh_c ./ci/release/docker/build.sh \
260 --version="$VERSION" \
261 ${PUSH_DOCKER:+--push} \
262 ${LATEST_DOCKER:+--latest}
263 return 0
264 fi
265
266 sh_c lockfile_ssh "$CI_D2_LINUX_ARM64" .d2-build-lock
267 sh_c gitsync "$CI_D2_LINUX_ARM64" src/d2
268 sh_c rsync --archive --human-readable \
269 "$BUILD_DIR/d2-$VERSION"-linux-*.tar.gz \
270 "$CI_D2_LINUX_ARM64:src/d2/$BUILD_DIR/"
271 sh_c ssh "$CI_D2_LINUX_ARM64" \
272 "D2_DOCKER_IMAGE=${D2_DOCKER_IMAGE-}" \
273 "RELEASE=${RELEASE-}" \
274 ./src/d2/ci/release/docker/build.sh \
275 --version="$VERSION" \
276 ${PUSH_DOCKER:+--push} \
277 ${LATEST_DOCKER:+--latest}
278}
279
280build_windows_msi() {
281 REMOTE_HOST=$CI_D2_WINDOWS_AMD64
282
283 ln -sf "../build/$VERSION/windows-amd64/d2-$VERSION/bin/d2.exe" ./ci/release/windows/d2.exe
284 sh_c rsync --archive --human-readable --copy-links --delete ./ci/release/windows/ "'$REMOTE_HOST:windows/'"
285 if ! echo "$VERSION" | grep '[0-9]\.[0-9]\.[0-9]'; then
286 WIX_VERSION=0.0.0
287 else
288 WIX_VERSION=$VERSION
289 fi
290 sh_c ssh "$REMOTE_HOST" "'cd ./windows && wix build -arch x64 -d D2Version=$WIX_VERSION ./d2.wxs'"
291
292 # --files-from shouldn't be necessary but for some reason selecting d2.msi directly
293 # makes rsync error with:
294 # ERROR: rejecting unrequested file-list name: ./windows/d2.msi
295 # rsync error: requested action not supported (code 4) at flist.c(1027) [Receiver=3.2.7]
296 rsync_files=$(mktempd)/rsync-files
297 echo d2.msi >$rsync_files
298 sh_c rsync --archive --human-readable --files-from "$rsync_files" "'$REMOTE_HOST:windows/'" "./ci/release/build/$VERSION/d2-$VERSION-$OS-$ARCH.msi"
299}
300
301main "$@"
View as plain text