Cache CI Docker images in ghcr registry

This commit is contained in:
Jakub Beránek 2024-01-21 14:26:20 +01:00
parent cb25c5bc3d
commit da5ab5ecd3
No known key found for this signature in database
GPG key ID: 909CD0D26483516B
3 changed files with 57 additions and 56 deletions

View file

@ -28,6 +28,7 @@ name: CI
- "**" - "**"
permissions: permissions:
contents: read contents: read
packages: write
defaults: defaults:
run: run:
shell: bash shell: bash
@ -42,6 +43,7 @@ jobs:
CI_JOB_NAME: "${{ matrix.name }}" CI_JOB_NAME: "${{ matrix.name }}"
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}" HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}"
DOCKER_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
SCCACHE_BUCKET: rust-lang-ci-sccache2 SCCACHE_BUCKET: rust-lang-ci-sccache2
TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
CACHE_DOMAIN: ci-caches.rust-lang.org CACHE_DOMAIN: ci-caches.rust-lang.org
@ -172,6 +174,7 @@ jobs:
CI_JOB_NAME: "${{ matrix.name }}" CI_JOB_NAME: "${{ matrix.name }}"
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}" HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}"
DOCKER_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
SCCACHE_BUCKET: rust-lang-ci-sccache2 SCCACHE_BUCKET: rust-lang-ci-sccache2
DEPLOY_BUCKET: rust-lang-ci2 DEPLOY_BUCKET: rust-lang-ci2
TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
@ -554,6 +557,7 @@ jobs:
CI_JOB_NAME: "${{ matrix.name }}" CI_JOB_NAME: "${{ matrix.name }}"
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}" HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}"
DOCKER_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
SCCACHE_BUCKET: rust-lang-ci-sccache2 SCCACHE_BUCKET: rust-lang-ci-sccache2
DEPLOY_BUCKET: rust-lang-ci2 DEPLOY_BUCKET: rust-lang-ci2
TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"

View file

@ -74,25 +74,6 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
cksum=$(sha512sum $hash_key | \ cksum=$(sha512sum $hash_key | \
awk '{print $1}') 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"
docker_archive_hash=$(sha512sum /tmp/rustci_docker_cache | awk '{print $1}')
echo "Downloaded archive hash: ${docker_archive_hash}"
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
printf "Downloaded containers:\n$loaded_images\n"
fi fi
dockerfile="$docker_dir/$image/Dockerfile" dockerfile="$docker_dir/$image/Dockerfile"
@ -103,46 +84,60 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
context="$script_dir" context="$script_dir"
fi fi
echo "::group::Building docker image for $image" echo "::group::Building docker image for $image"
echo "Image input checksum ${cksum}"
# As of August 2023, Github Actions have updated Docker to 23.X, # On non-CI or PR jobs, we don't have permissions to write to the registry cache, so we should
# which uses the BuildKit by default. It currently throws aways all # not use `docker login` nor caching.
# intermediate layers, which breaks our usage of S3 layer caching. if [[ "$CI" == "" ]] || [[ "$PR_CI_JOB" == "1" ]];
# Therefore we opt-in to the old build backend for now. then
export DOCKER_BUILDKIT=0 retry docker build --rm -t rust-ci -f "$dockerfile" "$context"
retry docker \ else
build \ REGISTRY=ghcr.io
--rm \ # Most probably rust-lang-ci, but in general the owner of the repository where CI runs
-t rust-ci \ REGISTRY_USERNAME=${GITHUB_REPOSITORY_OWNER}
-f "$dockerfile" \ # Tag used to push the final Docker image, so that it can be pulled by e.g. rustup
"$context" IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci:${cksum}
echo "::endgroup::" # Tag used to cache the Docker build
# It seems that it cannot be the same as $IMAGE_TAG, otherwise it overwrites the cache
CACHE_IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci-cache:${cksum}
if [ "$CI" != "" ]; then # Log into the Docker registry, so that we can read/write cache and the final image
s3url="s3://$SCCACHE_BUCKET/docker/$cksum" echo ${DOCKER_TOKEN} | docker login ${REGISTRY} \
upload="aws s3 cp - $s3url" --username ${REGISTRY_USERNAME} \
digest=$(docker inspect rust-ci --format '{{.Id}}') --password-stdin
echo "Built container $digest"
if ! grep -q "$digest" <(echo "$loaded_images"); then # Enable a new Docker driver so that --cache-from/to works with a registry backend
echo "Uploading finished image $digest to $url" docker buildx create --use --driver docker-container
set +e
# Print image history for easier debugging of layer SHAs # Build the image using registry caching backend
docker history rust-ci retry docker \
docker history -q rust-ci | \ buildx \
grep -v missing | \ build \
xargs docker save | \ --rm \
gzip | \ -t rust-ci \
$upload -f "$dockerfile" \
set -e --cache-from type=registry,ref=${CACHE_IMAGE_TAG} \
else --cache-to type=registry,ref=${CACHE_IMAGE_TAG},compression=zstd \
echo "Looks like docker image is the same as before, not uploading" --output=type=docker \
fi "$context"
# Record the container image for reuse, e.g. by rustup.rs builds
info="$dist/image-$image.txt" # Print images for debugging purposes
mkdir -p "$dist" docker images
echo "$url" >"$info"
echo "$digest" >>"$info" # Tag the built image and push it to the registry
cat "$info" docker tag rust-ci "${IMAGE_TAG}"
docker push "${IMAGE_TAG}"
# Record the container registry tag/url for reuse, e.g. by rustup.rs builds
# It should be possible to run `docker pull <$IMAGE_TAG>` to download the image
info="$dist/image-$image.txt"
mkdir -p "$dist"
echo "${IMAGE_TAG}" > "$info"
cat "$info"
echo "To download the image, run docker pull ${IMAGE_TAG}"
fi fi
echo "::endgroup::"
elif [ -f "$docker_dir/disabled/$image/Dockerfile" ]; then elif [ -f "$docker_dir/disabled/$image/Dockerfile" ]; then
if isCI; then if isCI; then
echo Cannot run disabled images on CI! echo Cannot run disabled images on CI!

View file

@ -34,6 +34,7 @@ x--expand-yaml-anchors--remove:
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
# commit of PR sha or commit sha. `GITHUB_SHA` is not accurate for PRs. # commit of PR sha or commit sha. `GITHUB_SHA` is not accurate for PRs.
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
DOCKER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- &public-variables - &public-variables
SCCACHE_BUCKET: rust-lang-ci-sccache2 SCCACHE_BUCKET: rust-lang-ci-sccache2
@ -301,6 +302,7 @@ on:
permissions: permissions:
contents: read contents: read
packages: write
defaults: defaults:
run: run: