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) --target <target> [options]
13 Distribution to build packages for
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 [[ -z "$TARGET" ]]; then
143 echo "FATAL: --target must be specified" >&2
145 elif [[ ! -d "$WORKSPACE/build/package-build-dockerfiles/$TARGET" ]]; then
146 echo "FATAL: unknown build target '$TARGET'" >&2
150 if [[ -n "$ARVADOS_BUILDING_VERSION" ]]; then
151 echo "build version='$ARVADOS_BUILDING_VERSION', package iteration='$ARVADOS_BUILDING_ITERATION'"
154 if [[ -n "$test_packages" ]]; then
155 # Packages are built world-readable, so package indexes should be too,
156 # especially because since 2022 apt uses an unprivileged user `_apt` to
157 # retrieve everything. Ensure it has permissions to read the packages
158 # when mounted as a volume inside the Docker container.
159 chmod a+rx "$WORKSPACE" "$WORKSPACE/packages" "$WORKSPACE/packages/$TARGET"
161 if [[ -n "$(find $WORKSPACE/packages/$TARGET -name '*.rpm')" ]] ; then
162 CREATEREPO="$(command -v createrepo createrepo_c | tail -n1)"
163 if [[ -z "$CREATEREPO" ]]; then
165 echo >&2 "Error: please install createrepo. E.g. sudo apt install createrepo-c"
169 "$CREATEREPO" $WORKSPACE/packages/$TARGET
172 if [[ -n "$(find $WORKSPACE/packages/$TARGET -name '*.deb')" ]] ; then
174 /usr/bin/which dpkg-scanpackages >/dev/null
175 if [[ "$?" != "0" ]]; then
177 echo >&2 "Error: please install dpkg-dev. E.g. sudo apt-get install dpkg-dev"
181 /usr/bin/which apt-ftparchive >/dev/null
182 if [[ "$?" != "0" ]]; then
184 echo >&2 "Error: please install apt-utils. E.g. sudo apt-get install apt-utils"
189 (cd $WORKSPACE/packages/$TARGET
190 dpkg-scanpackages --multiversion . 2> >(grep -v 'warning' 1>&2) | tee Packages | gzip -c > Packages.gz
191 apt-ftparchive -o APT::FTPArchive::Release::Origin=Arvados release . > Release
195 COMMAND="/jenkins/package-testing/test-packages-$TARGET.sh"
196 IMAGE="arvados/package-test:$TARGET"
199 IMAGE="arvados/build:$TARGET"
200 if [[ "$COMMAND" != "" ]]; then
201 COMMAND="bash /jenkins/$COMMAND --target $TARGET$DEBUG"
205 JENKINS_DIR=$(dirname "$(readlink -e "$0")")
207 if [[ "$SKIP_DOCKER_BUILD" != 1 ]] ; then
208 if [[ -n "$test_packages" ]]; then
209 pushd "$JENKINS_DIR/package-test-dockerfiles"
211 pushd "$JENKINS_DIR/package-build-dockerfiles"
212 make "$TARGET/generated"
215 GOVERSION=$(grep 'const goversion =' $WORKSPACE/lib/install/deps.go |awk -F'"' '{print $2}')
219 time docker build --tag "$IMAGE" \
220 --build-arg HOSTTYPE=$HOSTTYPE \
221 --build-arg BRANCH=$(git rev-parse HEAD) \
222 --build-arg GOVERSION=$GOVERSION --no-cache .
226 if test -z "$packages" ; then
227 packages="arvados-api-server
230 arvados-dispatch-cloud
232 arvados-docker-cleaner
240 crunch-dispatch-local
241 crunch-dispatch-slurm
251 python3-arvados-cwl-runner
253 python3-arvados-python-client
254 python3-arvados-user-activity
255 python3-arvados-cluster-activity
256 python3-crunchstat-summary"
263 mkdir -p "$WORKSPACE/services/api/vendor/cache-$TARGET"
266 -v "$JENKINS_DIR:/jenkins"
267 -v "$WORKSPACE:/arvados"
268 --tmpfs /arvados/services/api/.bundle:rw,noexec,nosuid,size=1m
269 --tmpfs /arvados/services/api/vendor:rw,exec,nosuid,size=1g
270 -v "$WORKSPACE/services/api/vendor/cache-$TARGET:/arvados/services/api/vendor/cache"
273 if [[ -n "$test_packages" ]]; then
274 for p in $packages ; do
275 if [[ -n "$ONLY_BUILD" ]] && [[ "$p" != "$ONLY_BUILD" ]]; then
278 if [[ -e "${WORKSPACE}/packages/.last_test_${TARGET}" ]] && [[ -z "$FORCE_TEST" ]]; then
279 MATCH=`find ${WORKSPACE}/packages/ -newer ${WORKSPACE}/packages/.last_test_${TARGET} -regex .*${TARGET}/$p.*`
280 if [[ "$MATCH" == "" ]]; then
281 # No new package has been built that needs testing
282 echo "Skipping $p test because no new package was built since the last test."
286 # If we're testing all packages, we should not error out on packages that don't exist.
287 # If we are testing one specific package only (i.e. --only-test was given), we should
288 # error out if that package does not exist.
289 if [[ -z "$testing_one_package" ]]; then
290 MATCH=`find ${WORKSPACE}/packages/ -regextype posix-extended -regex .*${TARGET}/$p.*\\(deb\\|rpm\\)`
291 if [[ "$MATCH" == "" ]]; then
292 # No new package has been built that needs testing
293 echo "Skipping $p test because no package file is available to test."
298 echo "START: $p test on $IMAGE" >&2
301 "${docker_volume_args[@]}" \
302 --env ARVADOS_DEBUG=$ARVADOS_DEBUG \
303 --env "TARGET=$TARGET" \
304 --env "WORKSPACE=/arvados" \
307 echo "OK: $p test on $IMAGE succeeded" >&2
310 package_fails="$package_fails $p"
311 echo "ERROR: $p test on $IMAGE failed with exit status $FINAL_EXITCODE" >&2
315 if [[ "$FINAL_EXITCODE" == "0" ]]; then
316 touch ${WORKSPACE}/packages/.last_test_${TARGET}
320 echo "START: build packages on $IMAGE" >&2
321 # Move existing packages and other files into the processed/ subdirectory
322 if [[ ! -e "${WORKSPACE}/packages/${TARGET}/processed" ]]; then
323 mkdir -p "${WORKSPACE}/packages/${TARGET}/processed"
326 mv -f ${WORKSPACE}/packages/${TARGET}/* ${WORKSPACE}/packages/${TARGET}/processed/ 2>/dev/null
328 # give bundle (almost) all the cores. See also the MAKE env var that is passed into the
329 # docker run command below.
330 # Cf. https://build.betterup.com/one-weird-trick-that-will-speed-up-your-bundle-install/
331 tmpfile=$(mktemp /tmp/run-build-packages-one-target.XXXXXX)
332 cores=$(let a=$(grep -c processor /proc/cpuinfo )-1; echo $a)
333 printf -- "---\nBUNDLE_JOBS: \"$cores\"" > $tmpfile
337 "${docker_volume_args[@]}" \
338 -v $tmpfile:/root/.bundle/config \
339 --env ARVADOS_BUILDING_VERSION="$ARVADOS_BUILDING_VERSION" \
340 --env ARVADOS_BUILDING_ITERATION="$ARVADOS_BUILDING_ITERATION" \
341 --env ARVADOS_DEBUG=$ARVADOS_DEBUG \
342 --env "ONLY_BUILD=$ONLY_BUILD" \
343 --env "FORCE_BUILD=$FORCE_BUILD" \
345 --env "MAKE=make --jobs $cores" \
349 echo "OK: build packages on $IMAGE succeeded" >&2
352 echo "ERROR: build packages on $IMAGE failed with exit status $FINAL_EXITCODE" >&2
354 # Clean up the bundle config file
358 if test -n "$package_fails" ; then
359 echo "Failed package tests:$package_fails" >&2