diff options
Diffstat (limited to 'src/ci/docker/run.sh')
-rwxr-xr-x | src/ci/docker/run.sh | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh new file mode 100755 index 000000000..93b4f435d --- /dev/null +++ b/src/ci/docker/run.sh @@ -0,0 +1,265 @@ +#!/usr/bin/env bash + +set -e + +export MSYS_NO_PATHCONV=1 + +script=`cd $(dirname $0) && pwd`/`basename $0` + +image="" +dev=0 + +while [[ $# -gt 0 ]] +do + case "$1" in + --dev) + dev=1 + ;; + *) + if [ -n "$image" ] + then + echo "expected single argument for the image name" + exit 1 + fi + image="$1" + ;; + esac + shift +done + +script_dir="`dirname $script`" +docker_dir="${script_dir}/host-$(uname -m)" +ci_dir="`dirname $script_dir`" +src_dir="`dirname $ci_dir`" +root_dir="`dirname $src_dir`" + +objdir=$root_dir/obj +dist=$objdir/build/dist + +source "$ci_dir/shared.sh" + +CACHE_DOMAIN="${CACHE_DOMAIN:-ci-caches.rust-lang.org}" + +if [ -f "$docker_dir/$image/Dockerfile" ]; then + if [ "$CI" != "" ]; then + hash_key=/tmp/.docker-hash-key.txt + rm -f "${hash_key}" + echo $image >> $hash_key + + cat "$docker_dir/$image/Dockerfile" >> $hash_key + # Look for all source files involves in the COPY command + copied_files=/tmp/.docker-copied-files.txt + rm -f "$copied_files" + for i in $(sed -n -e '/^COPY --from=/! s/^COPY \(.*\) .*$/\1/p' \ + "$docker_dir/$image/Dockerfile"); do + # List the file names + find "$script_dir/$i" -type f >> $copied_files + done + # Sort the file names and cat the content into the hash key + sort $copied_files | xargs cat >> $hash_key + + # Include the architecture in the hash key, since our Linux CI does not + # only run in x86_64 machines. + uname -m >> $hash_key + + docker --version >> $hash_key + cksum=$(sha512sum $hash_key | \ + awk '{print $1}') + + url="https://$CACHE_DOMAIN/docker/$cksum" + + echo "Attempting to download $url" + rm -f /tmp/rustci_docker_cache + set +e + retry curl --max-time 600 -y 30 -Y 10 --connect-timeout 30 -f -L -C - \ + -o /tmp/rustci_docker_cache "$url" + echo "Loading images into docker" + # docker load sometimes hangs in the CI, so time out after 10 minutes with TERM, + # KILL after 12 minutes + loaded_images=$(/usr/bin/timeout -k 720 600 docker load -i /tmp/rustci_docker_cache \ + | sed 's/.* sha/sha/') + set -e + echo "Downloaded containers:\n$loaded_images" + fi + + dockerfile="$docker_dir/$image/Dockerfile" + if [ -x /usr/bin/cygpath ]; then + context="`cygpath -w $script_dir`" + dockerfile="`cygpath -w $dockerfile`" + else + context="$script_dir" + fi + retry docker \ + build \ + --rm \ + -t rust-ci \ + -f "$dockerfile" \ + "$context" + + if [ "$CI" != "" ]; then + s3url="s3://$SCCACHE_BUCKET/docker/$cksum" + upload="aws s3 cp - $s3url" + digest=$(docker inspect rust-ci --format '{{.Id}}') + echo "Built container $digest" + if ! grep -q "$digest" <(echo "$loaded_images"); then + echo "Uploading finished image to $url" + set +e + docker history -q rust-ci | \ + grep -v missing | \ + xargs docker save | \ + gzip | \ + $upload + set -e + else + echo "Looks like docker image is the same as before, not uploading" + fi + # Record the container image for reuse, e.g. by rustup.rs builds + info="$dist/image-$image.txt" + mkdir -p "$dist" + echo "$url" >"$info" + echo "$digest" >>"$info" + fi +elif [ -f "$docker_dir/disabled/$image/Dockerfile" ]; then + if isCI; then + echo Cannot run disabled images on CI! + exit 1 + fi + # Transform changes the context of disabled Dockerfiles to match the enabled ones + tar --transform 's#disabled/#./#' -C $script_dir -c . | docker \ + build \ + --rm \ + -t rust-ci \ + -f "host-$(uname -m)/$image/Dockerfile" \ + - +else + echo Invalid image: $image + + # Check whether the image exists for other architectures + for arch_dir in "${script_dir}"/host-*; do + # Avoid checking non-directories and the current host architecture directory + if ! [[ -d "${arch_dir}" ]]; then + continue + fi + if [[ "${arch_dir}" = "${docker_dir}" ]]; then + continue + fi + + arch_name="$(basename "${arch_dir}" | sed 's/^host-//')" + if [[ -f "${arch_dir}/${image}/Dockerfile" ]]; then + echo "Note: the image exists for the ${arch_name} host architecture" + elif [[ -f "${arch_dir}/disabled/${image}/Dockerfile" ]]; then + echo "Note: the disabled image exists for the ${arch_name} host architecture" + else + continue + fi + echo "Note: the current host architecture is $(uname -m)" + done + + exit 1 +fi + +mkdir -p $HOME/.cargo +mkdir -p $objdir/tmp +mkdir -p $objdir/cores +mkdir -p /tmp/toolstate + +args= +if [ "$SCCACHE_BUCKET" != "" ]; then + args="$args --env SCCACHE_BUCKET" + args="$args --env SCCACHE_REGION" + args="$args --env AWS_ACCESS_KEY_ID" + args="$args --env AWS_SECRET_ACCESS_KEY" +else + mkdir -p $HOME/.cache/sccache + args="$args --env SCCACHE_DIR=/sccache --volume $HOME/.cache/sccache:/sccache" +fi + +# Run containers as privileged as it should give them access to some more +# syscalls such as ptrace and whatnot. In the upgrade to LLVM 5.0 it was +# discovered that the leak sanitizer apparently needs these syscalls nowadays so +# we'll need `--privileged` for at least the `x86_64-gnu` builder, so this just +# goes ahead and sets it for all builders. +args="$args --privileged" + +# Things get a little weird if this script is already running in a docker +# container. If we're already in a docker container then we assume it's set up +# to do docker-in-docker where we have access to a working `docker` command. +# +# If this is the case (we check via the presence of `/.dockerenv`) +# then we can't actually use the `--volume` argument. Typically we use +# `--volume` to efficiently share the build and source directory between this +# script and the container we're about to spawn. If we're inside docker already +# though the `--volume` argument maps the *host's* folder to the container we're +# about to spawn, when in fact we want the folder in this container itself. To +# work around this we use a recipe cribbed from +# https://circleci.com/docs/2.0/building-docker-images/#mounting-folders to +# create a temporary container with a volume. We then copy the entire source +# directory into this container, and then use that copy in the container we're +# about to spawn. Finally after the build finishes we re-extract the object +# directory. +# +# Note that none of this is necessary if we're *not* in a docker-in-docker +# scenario. If this script is run on a bare metal host then we share a bunch of +# data directories to share as much data as possible. Note that we also use +# `LOCAL_USER_ID` (recognized in `src/ci/run.sh`) to ensure that files are all +# read/written as the same user as the bare-metal user. +if [ -f /.dockerenv ]; then + docker create -v /checkout --name checkout alpine:3.4 /bin/true + docker cp . checkout:/checkout + args="$args --volumes-from checkout" +else + args="$args --volume $root_dir:/checkout:ro" + args="$args --volume $objdir:/checkout/obj" + args="$args --volume $HOME/.cargo:/cargo" + args="$args --volume $HOME/rustsrc:$HOME/rustsrc" + args="$args --volume /tmp/toolstate:/tmp/toolstate" + args="$args --env LOCAL_USER_ID=`id -u`" +fi + +if [ "$dev" = "1" ] +then + # Interactive + TTY + args="$args -it" + command="/bin/bash" +else + command="/checkout/src/ci/run.sh" +fi + +if [ "$CI" != "" ]; then + # Get some needed information for $BASE_COMMIT + # + # This command gets the last merge commit which we'll use as base to list + # deleted files since then. + BASE_COMMIT="$(git log --author=bors@rust-lang.org -n 2 --pretty=format:%H | tail -n 1)" +else + BASE_COMMIT="" +fi + +docker \ + run \ + --workdir /checkout/obj \ + --env SRC=/checkout \ + $args \ + --env CARGO_HOME=/cargo \ + --env DEPLOY \ + --env DEPLOY_ALT \ + --env CI \ + --env TF_BUILD \ + --env BUILD_SOURCEBRANCHNAME \ + --env GITHUB_ACTIONS \ + --env GITHUB_REF \ + --env TOOLSTATE_REPO_ACCESS_TOKEN \ + --env TOOLSTATE_REPO \ + --env TOOLSTATE_PUBLISH \ + --env RUST_CI_OVERRIDE_RELEASE_CHANNEL \ + --env CI_JOB_NAME="${CI_JOB_NAME-$IMAGE}" \ + --env BASE_COMMIT="$BASE_COMMIT" \ + --init \ + --rm \ + rust-ci \ + $command + +if [ -f /.dockerenv ]; then + rm -rf $objdir + docker cp checkout:/checkout/obj $objdir +fi |