2 # Copyright (C) The Arvados Authors. All rights reserved.
4 # SPDX-License-Identifier: AGPL-3.0
6 read -rd "\000" helpmessage <<EOF
7 $(basename $0): Orchestrate run-build-packages.sh for one target
10 WORKSPACE=/path/to/arvados $(basename $0) [options]
13 Distribution to build packages for (default: debian10)
15 Build command to execute (default: use built-in Docker image command)
17 Run package install test script "test-packages-[target].sh"
19 Output debug information (default: false)
20 --only-build <package>
21 Build only a specific package
23 Test only a specific package
25 Build a specific architecture (amd64 or arm64, defaults to native architecture)
27 Build even if the package exists upstream or if it has already been
30 Test even if there is no new untested package
31 --build-version <string>
32 Version to build (default:
33 \$ARVADOS_BUILDING_VERSION-\$ARVADOS_BUILDING_ITERATION or
34 0.1.timestamp.commithash)
36 Don't try to build Docker images
38 WORKSPACE=path Path to the Arvados source tree to build packages from
44 if ! [[ -n "$WORKSPACE" ]]; then
45 echo >&2 "$helpmessage"
47 echo >&2 "Error: WORKSPACE environment variable not set"
52 if ! [[ -d "$WORKSPACE" ]]; then
53 echo >&2 "$helpmessage"
55 echo >&2 "Error: $WORKSPACE is not a directory"
60 PARSEDOPTS=$(getopt --name "$0" --longoptions \
61 help,debug,test-packages,target:,command:,only-test:,force-test,only-build:,force-build,arch:,build-version:,skip-docker-build \
72 eval set -- "$PARSEDOPTS"
73 while [ $# -gt 0 ]; do
76 echo >&2 "$helpmessage"
95 ONLY_BUILD="$2"; shift
111 if [[ -z "$2" ]]; then
113 elif ! [[ "$2" =~ (.*)-(.*) ]]; then
114 echo >&2 "FATAL: --build-version '$2' does not include an iteration. Try '${2}-1'?"
116 elif ! [[ "$2" =~ ^[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+|)(~rc[0-9]+|~dev[0-9]+|)-[0-9]+$ ]]; then
117 echo >&2 "FATAL: --build-version '$2' is invalid, must match pattern ^[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+|)(~rc[0-9]+|~dev[0-9]+|)-[0-9]+$"
120 [[ "$2" =~ (.*)-(.*) ]]
121 ARVADOS_BUILDING_VERSION="${BASH_REMATCH[1]}"
122 ARVADOS_BUILDING_ITERATION="${BASH_REMATCH[2]}"
130 if [ $# -gt 1 ]; then
131 echo >&2 "$0: unrecognized argument '$2'. Try: $0 --help"
140 orig_umask="$(umask)"
142 if [[ -n "$ARVADOS_BUILDING_VERSION" ]]; then
143 echo "build version='$ARVADOS_BUILDING_VERSION', package iteration='$ARVADOS_BUILDING_ITERATION'"
146 if [[ -n "$test_packages" ]]; then
147 # Packages are built world-readable, so package indexes should be too,
148 # especially because since 2022 apt uses an unprivileged user `_apt` to
149 # retrieve everything. Ensure it has permissions to read the packages
150 # when mounted as a volume inside the Docker container.
151 chmod a+rx "$WORKSPACE" "$WORKSPACE/packages" "$WORKSPACE/packages/$TARGET"
153 if [[ -n "$(find $WORKSPACE/packages/$TARGET -name '*.rpm')" ]] ; then
154 CREATEREPO="$(command -v createrepo createrepo_c | tail -n1)"
155 if [[ -z "$CREATEREPO" ]]; then
157 echo >&2 "Error: please install createrepo. E.g. sudo apt install createrepo-c"
161 "$CREATEREPO" $WORKSPACE/packages/$TARGET
164 if [[ -n "$(find $WORKSPACE/packages/$TARGET -name '*.deb')" ]] ; then
166 /usr/bin/which dpkg-scanpackages >/dev/null
167 if [[ "$?" != "0" ]]; then
169 echo >&2 "Error: please install dpkg-dev. E.g. sudo apt-get install dpkg-dev"
173 /usr/bin/which apt-ftparchive >/dev/null
174 if [[ "$?" != "0" ]]; then
176 echo >&2 "Error: please install apt-utils. E.g. sudo apt-get install apt-utils"
181 (cd $WORKSPACE/packages/$TARGET
182 dpkg-scanpackages --multiversion . 2> >(grep -v 'warning' 1>&2) | tee Packages | gzip -c > Packages.gz
183 apt-ftparchive -o APT::FTPArchive::Release::Origin=Arvados release . > Release
187 COMMAND="/jenkins/package-testing/test-packages-$TARGET.sh"
188 IMAGE="arvados/package-test:$TARGET"
191 IMAGE="arvados/build:$TARGET"
192 if [[ "$COMMAND" != "" ]]; then
193 COMMAND="/usr/local/rvm/bin/rvm-exec default bash /jenkins/$COMMAND --target $TARGET$DEBUG"
197 JENKINS_DIR=$(dirname "$(readlink -e "$0")")
199 if [[ "$SKIP_DOCKER_BUILD" != 1 ]] ; then
200 if [[ -n "$test_packages" ]]; then
201 pushd "$JENKINS_DIR/package-test-dockerfiles"
202 make "$TARGET/generated"
204 pushd "$JENKINS_DIR/package-build-dockerfiles"
205 make "$TARGET/generated"
208 GOVERSION=$(grep 'const goversion =' $WORKSPACE/lib/install/deps.go |awk -F'"' '{print $2}')
212 time docker build --tag "$IMAGE" \
213 --build-arg HOSTTYPE=$HOSTTYPE \
214 --build-arg BRANCH=$(git rev-parse HEAD) \
215 --build-arg GOVERSION=$GOVERSION --no-cache .
219 if test -z "$packages" ; then
220 packages="arvados-api-server
223 arvados-dispatch-cloud
225 arvados-docker-cleaner
234 crunch-dispatch-local
235 crunch-dispatch-slurm
249 python3-arvados-python-client
250 python3-arvados-cwl-runner
251 python3-crunchstat-summary
252 python3-arvados-user-activity"
259 mkdir -p "$WORKSPACE/services/api/vendor/cache-$TARGET"
262 -v "$JENKINS_DIR:/jenkins"
263 -v "$WORKSPACE:/arvados"
264 -v /arvados/services/api/vendor/bundle
265 -v "$WORKSPACE/services/api/vendor/cache-$TARGET:/arvados/services/api/vendor/cache"
268 if [[ -n "$test_packages" ]]; then
269 for p in $packages ; do
270 if [[ -n "$ONLY_BUILD" ]] && [[ "$p" != "$ONLY_BUILD" ]]; then
273 if [[ -e "${WORKSPACE}/packages/.last_test_${TARGET}" ]] && [[ -z "$FORCE_TEST" ]]; then
274 MATCH=`find ${WORKSPACE}/packages/ -newer ${WORKSPACE}/packages/.last_test_${TARGET} -regex .*${TARGET}/$p.*`
275 if [[ "$MATCH" == "" ]]; then
276 # No new package has been built that needs testing
277 echo "Skipping $p test because no new package was built since the last test."
281 # If we're testing all packages, we should not error out on packages that don't exist.
282 # If we are testing one specific package only (i.e. --only-test was given), we should
283 # error out if that package does not exist.
284 if [[ -z "$testing_one_package" ]]; then
285 MATCH=`find ${WORKSPACE}/packages/ -regextype posix-extended -regex .*${TARGET}/$p.*\\(deb\\|rpm\\)`
286 if [[ "$MATCH" == "" ]]; then
287 # No new package has been built that needs testing
288 echo "Skipping $p test because no package file is available to test."
293 echo "START: $p test on $IMAGE" >&2
296 "${docker_volume_args[@]}" \
297 --env ARVADOS_DEBUG=$ARVADOS_DEBUG \
298 --env "TARGET=$TARGET" \
299 --env "WORKSPACE=/arvados" \
302 echo "OK: $p test on $IMAGE succeeded" >&2
305 package_fails="$package_fails $p"
306 echo "ERROR: $p test on $IMAGE failed with exit status $FINAL_EXITCODE" >&2
310 if [[ "$FINAL_EXITCODE" == "0" ]]; then
311 touch ${WORKSPACE}/packages/.last_test_${TARGET}
315 echo "START: build packages on $IMAGE" >&2
316 # Move existing packages and other files into the processed/ subdirectory
317 if [[ ! -e "${WORKSPACE}/packages/${TARGET}/processed" ]]; then
318 mkdir -p "${WORKSPACE}/packages/${TARGET}/processed"
321 mv -f ${WORKSPACE}/packages/${TARGET}/* ${WORKSPACE}/packages/${TARGET}/processed/ 2>/dev/null
323 # give bundle (almost) all the cores. See also the MAKE env var that is passed into the
324 # docker run command below.
325 # Cf. https://build.betterup.com/one-weird-trick-that-will-speed-up-your-bundle-install/
326 tmpfile=$(mktemp /tmp/run-build-packages-one-target.XXXXXX)
327 cores=$(let a=$(grep -c processor /proc/cpuinfo )-1; echo $a)
328 printf -- "---\nBUNDLE_JOBS: \"$cores\"" > $tmpfile
332 "${docker_volume_args[@]}" \
333 -v $tmpfile:/root/.bundle/config \
334 --env ARVADOS_BUILDING_VERSION="$ARVADOS_BUILDING_VERSION" \
335 --env ARVADOS_BUILDING_ITERATION="$ARVADOS_BUILDING_ITERATION" \
336 --env ARVADOS_DEBUG=$ARVADOS_DEBUG \
337 --env "ONLY_BUILD=$ONLY_BUILD" \
338 --env "FORCE_BUILD=$FORCE_BUILD" \
340 --env "MAKE=make --jobs $cores" \
344 echo "OK: build packages on $IMAGE succeeded" >&2
347 echo "ERROR: build packages on $IMAGE failed with exit status $FINAL_EXITCODE" >&2
349 # Clean up the bundle config file
353 if test -n "$package_fails" ; then
354 echo "Failed package tests:$package_fails" >&2