1717# ## Run builds using Google Cloud Build ##
1818#
1919# This script runs the builds defined in `ci/cloudbuild/builds/` on the local
20- # machine (if `--local` is specified) or in the cloud using Google Cloud Build
21- # (the default). A single argument indicating the build name is required. The
22- # distro indicates the `<distro>.Dockerfile` to use for the build (ignored if
23- # using `--local`). The distro is looked up from the specified build's trigger
24- # file (`ci/cloudbuild/triggers/<build-name>.yaml`), but the distro can be
20+ # machine (if `--local` is specified), in the local docker (if `--docker` is
21+ # specified), or in the cloud using Google Cloud Build (the default). A single
22+ # argument indicating the build name is required. The distro indicates the
23+ # `<distro>.Dockerfile` to use for the build (ignored if using `--local`). The
24+ # distro is looked up from the specified build's trigger file
25+ # (`ci/cloudbuild/triggers/<build-name>.yaml`), but the distro can be
2526# overridden with the optional `--distro=<arg>` flag.
2627#
2728# Usage: build.sh [options] <build-name>
2829#
2930# Options:
30- # --distro=<name> The distro name to use
31- # -p|--project=<name> The Cloud Project ID to use
31+ # --distro=<name> The distro name to use
3232# -l|--local Run the build in the local environment
33+ # -d|--docker Run the build in a local docker
34+ # -s|--docker-shell Run a shell in the build's docker container
35+ # -p|--project=<name> The Cloud Project ID to use
3336# -h|--help Print this help message
3437#
3538# Build names:
@@ -48,15 +51,17 @@ function print_usage() {
4851
4952# Use getopt to parse and normalize all the args.
5053PARSED=" $( getopt -a \
51- --options=" p:lh " \
52- --longoptions=" distro:,project:,local,help" \
54+ --options=" p:ldsh " \
55+ --longoptions=" distro:,project:,local,docker,docker-shell, help" \
5356 --name=" ${PROGRAM_NAME} " \
5457 -- " $@ " ) "
5558eval set -- " ${PARSED} "
5659
5760DISTRO=" "
5861PROJECT_ID=" "
5962LOCAL_BUILD=" false"
63+ DOCKER_BUILD=" false"
64+ DOCKER_SHELL=" false"
6065while true ; do
6166 case " $1 " in
6267 --distro)
@@ -71,6 +76,15 @@ while true; do
7176 LOCAL_BUILD=" true"
7277 shift
7378 ;;
79+ -d | --docker)
80+ DOCKER_BUILD=" true"
81+ shift
82+ ;;
83+ -s | --docker-shell)
84+ DOCKER_BUILD=" true"
85+ DOCKER_SHELL=" true"
86+ shift
87+ ;;
7488 -h | --help)
7589 print_usage
7690 exit 0
@@ -83,14 +97,25 @@ while true; do
8397done
8498readonly PROJECT_ID
8599
86- if (( $# == 0 )) ; then
87- echo " Missing build name"
100+ if (( $# != 1 )) ; then
101+ echo " Must specify exactly one build name"
88102 print_usage
89103 exit 1
90104fi
91105readonly BUILD_NAME=" $1 "
92106
107+ # --local is the most fundamental build mode, in that all other builds
108+ # eventually call this one. For example, a --docker build will build the
109+ # specified docker image, then in a container from that image it will run the
110+ # --local build. Similarly, the GCB build will submit the build to GCB, which
111+ # will call the --local build.
93112if [[ " ${LOCAL_BUILD} " = " true" ]]; then
113+ test -n " ${DISTRO} " && io::log_red " Local build ignoring --distro=${DISTRO} "
114+ if [[ " ${DOCKER_BUILD} " = " true" ]]; then
115+ echo " Only one of --local or --docker may be specified"
116+ print_usage
117+ exit 1
118+ fi
94119 io::log_h1 " Starting local build: ${BUILD_NAME} "
95120 readonly TIMEFORMAT=" ==> 🕑 ${BUILD_NAME} completed in %R seconds"
96121 time " ${PROGRAM_DIR} /builds/${BUILD_NAME} .sh"
@@ -109,6 +134,44 @@ if [[ -z "${DISTRO}" ]]; then
109134fi
110135readonly DISTRO
111136
137+ # Uses docker to locally build the specified image and run the build command.
138+ # Docker builds store their outputs on the host system in `build-out/`.
139+ if [[ " ${DOCKER_BUILD} " = " true" ]]; then
140+ io::log_h1 " Starting docker build: ${BUILD_NAME} "
141+ out_dir=" ${PROJECT_ROOT} /build-out/${DISTRO} -${BUILD_NAME} "
142+ out_home=" ${out_dir} /h"
143+ out_cmake=" ${out_dir} /cmake-out"
144+ mkdir -p " ${out_home} " " ${out_cmake} "
145+ image=" gcb-${DISTRO} :latest"
146+ io::log_h2 " Building docker image: ${image} "
147+ docker build -t " ${image} " " --build-arg=NCPU=$( nproc) " \
148+ -f " ci/cloudbuild/${DISTRO} .Dockerfile" ci
149+ io::log_h2 " Starting container for ${image} running ${BUILD_NAME} "
150+ run_flags=(
151+ " --interactive"
152+ " --tty"
153+ " --rm"
154+ " --user=$( id -u) :$( id -g) "
155+ " --env=USER=$( id -un) "
156+ # Mounts an empty volume over "build-out" to isolate builds from each
157+ # other. Doesn't affect GCB builds, but it helps our local docker builds.
158+ " --volume=/workspace/build-out"
159+ " --volume=${PROJECT_ROOT} :/workspace:Z"
160+ " --workdir=/workspace"
161+ " --volume=${out_cmake} :/workspace/cmake-out:Z"
162+ " --volume=${out_home} :/h:Z"
163+ " --env=HOME=/h"
164+ )
165+ cmd=(ci/cloudbuild/build.sh --local " ${BUILD_NAME} " )
166+ if [[ " ${DOCKER_SHELL} " = " true" ]]; then
167+ io::log " Starting shell, to manually run the requested build use:"
168+ echo " ==> ${cmd[*]} "
169+ cmd=(" bash" )
170+ fi
171+ docker run " ${run_flags[@]} " " ${image} " " ${cmd[@]} "
172+ exit
173+ fi
174+
112175# Surface invalid arguments early rather than waiting for GCB to fail.
113176if [ ! -r " ${PROGRAM_DIR} /${DISTRO} .Dockerfile" ]; then
114177 echo " Unknown distro: ${DISTRO} "
@@ -120,11 +183,12 @@ elif [ ! -x "${PROGRAM_DIR}/builds/${BUILD_NAME}.sh" ]; then
120183 exit 1
121184fi
122185
186+ # Uses Google Cloud build to run the specified build.
187+ io::log_h1 " Starting cloud build: ${BUILD_NAME} "
123188account=" $( gcloud config list account --format " value(core.account)" ) "
124189subs=" _DISTRO=${DISTRO} "
125190subs+=" ,_BUILD_NAME=${BUILD_NAME} "
126191subs+=" ,_CACHE_TYPE=manual-${account} "
127- io::log_h1 " Starting cloud build: ${BUILD_NAME} "
128192io::log " Substitutions ${subs} "
129193args=(
130194 " --config=ci/cloudbuild/cloudbuild.yaml"
@@ -133,4 +197,4 @@ args=(
133197if [[ -n " ${PROJECT_ID} " ]]; then
134198 args+=(" --project=${PROJECT_ID} " )
135199fi
136- exec gcloud builds submit " ${args[@]} " .
200+ gcloud builds submit " ${args[@]} " .
0 commit comments