Skip to content

Commit da5ab5e

Browse files
committed
Cache CI Docker images in ghcr registry
1 parent cb25c5b commit da5ab5e

File tree

3 files changed

+58
-57
lines changed

3 files changed

+58
-57
lines changed

.github/workflows/ci.yml

+4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ name: CI
2828
- "**"
2929
permissions:
3030
contents: read
31+
packages: write
3132
defaults:
3233
run:
3334
shell: bash
@@ -42,6 +43,7 @@ jobs:
4243
CI_JOB_NAME: "${{ matrix.name }}"
4344
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
4445
HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}"
46+
DOCKER_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
4547
SCCACHE_BUCKET: rust-lang-ci-sccache2
4648
TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
4749
CACHE_DOMAIN: ci-caches.rust-lang.org
@@ -172,6 +174,7 @@ jobs:
172174
CI_JOB_NAME: "${{ matrix.name }}"
173175
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
174176
HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}"
177+
DOCKER_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
175178
SCCACHE_BUCKET: rust-lang-ci-sccache2
176179
DEPLOY_BUCKET: rust-lang-ci2
177180
TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
@@ -554,6 +557,7 @@ jobs:
554557
CI_JOB_NAME: "${{ matrix.name }}"
555558
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
556559
HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}"
560+
DOCKER_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
557561
SCCACHE_BUCKET: rust-lang-ci-sccache2
558562
DEPLOY_BUCKET: rust-lang-ci2
559563
TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"

src/ci/docker/run.sh

+52-57
Original file line numberDiff line numberDiff line change
@@ -74,25 +74,6 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
7474

7575
cksum=$(sha512sum $hash_key | \
7676
awk '{print $1}')
77-
78-
url="https://$CACHE_DOMAIN/docker/$cksum"
79-
80-
echo "Attempting to download $url"
81-
rm -f /tmp/rustci_docker_cache
82-
set +e
83-
retry curl --max-time 600 -y 30 -Y 10 --connect-timeout 30 -f -L -C - \
84-
-o /tmp/rustci_docker_cache "$url"
85-
86-
docker_archive_hash=$(sha512sum /tmp/rustci_docker_cache | awk '{print $1}')
87-
echo "Downloaded archive hash: ${docker_archive_hash}"
88-
89-
echo "Loading images into docker"
90-
# docker load sometimes hangs in the CI, so time out after 10 minutes with TERM,
91-
# KILL after 12 minutes
92-
loaded_images=$(/usr/bin/timeout -k 720 600 docker load -i /tmp/rustci_docker_cache \
93-
| sed 's/.* sha/sha/')
94-
set -e
95-
printf "Downloaded containers:\n$loaded_images\n"
9677
fi
9778

9879
dockerfile="$docker_dir/$image/Dockerfile"
@@ -103,46 +84,60 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
10384
context="$script_dir"
10485
fi
10586
echo "::group::Building docker image for $image"
87+
echo "Image input checksum ${cksum}"
10688

107-
# As of August 2023, Github Actions have updated Docker to 23.X,
108-
# which uses the BuildKit by default. It currently throws aways all
109-
# intermediate layers, which breaks our usage of S3 layer caching.
110-
# Therefore we opt-in to the old build backend for now.
111-
export DOCKER_BUILDKIT=0
112-
retry docker \
113-
build \
114-
--rm \
115-
-t rust-ci \
116-
-f "$dockerfile" \
117-
"$context"
118-
echo "::endgroup::"
119-
120-
if [ "$CI" != "" ]; then
121-
s3url="s3://$SCCACHE_BUCKET/docker/$cksum"
122-
upload="aws s3 cp - $s3url"
123-
digest=$(docker inspect rust-ci --format '{{.Id}}')
124-
echo "Built container $digest"
125-
if ! grep -q "$digest" <(echo "$loaded_images"); then
126-
echo "Uploading finished image $digest to $url"
127-
set +e
128-
# Print image history for easier debugging of layer SHAs
129-
docker history rust-ci
130-
docker history -q rust-ci | \
131-
grep -v missing | \
132-
xargs docker save | \
133-
gzip | \
134-
$upload
135-
set -e
136-
else
137-
echo "Looks like docker image is the same as before, not uploading"
138-
fi
139-
# Record the container image for reuse, e.g. by rustup.rs builds
140-
info="$dist/image-$image.txt"
141-
mkdir -p "$dist"
142-
echo "$url" >"$info"
143-
echo "$digest" >>"$info"
144-
cat "$info"
89+
# On non-CI or PR jobs, we don't have permissions to write to the registry cache, so we should
90+
# not use `docker login` nor caching.
91+
if [[ "$CI" == "" ]] || [[ "$PR_CI_JOB" == "1" ]];
92+
then
93+
retry docker build --rm -t rust-ci -f "$dockerfile" "$context"
94+
else
95+
REGISTRY=ghcr.io
96+
# Most probably rust-lang-ci, but in general the owner of the repository where CI runs
97+
REGISTRY_USERNAME=${GITHUB_REPOSITORY_OWNER}
98+
# Tag used to push the final Docker image, so that it can be pulled by e.g. rustup
99+
IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci:${cksum}
100+
# Tag used to cache the Docker build
101+
# It seems that it cannot be the same as $IMAGE_TAG, otherwise it overwrites the cache
102+
CACHE_IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci-cache:${cksum}
103+
104+
# Log into the Docker registry, so that we can read/write cache and the final image
105+
echo ${DOCKER_TOKEN} | docker login ${REGISTRY} \
106+
--username ${REGISTRY_USERNAME} \
107+
--password-stdin
108+
109+
# Enable a new Docker driver so that --cache-from/to works with a registry backend
110+
docker buildx create --use --driver docker-container
111+
112+
# Build the image using registry caching backend
113+
retry docker \
114+
buildx \
115+
build \
116+
--rm \
117+
-t rust-ci \
118+
-f "$dockerfile" \
119+
--cache-from type=registry,ref=${CACHE_IMAGE_TAG} \
120+
--cache-to type=registry,ref=${CACHE_IMAGE_TAG},compression=zstd \
121+
--output=type=docker \
122+
"$context"
123+
124+
# Print images for debugging purposes
125+
docker images
126+
127+
# Tag the built image and push it to the registry
128+
docker tag rust-ci "${IMAGE_TAG}"
129+
docker push "${IMAGE_TAG}"
130+
131+
# Record the container registry tag/url for reuse, e.g. by rustup.rs builds
132+
# It should be possible to run `docker pull <$IMAGE_TAG>` to download the image
133+
info="$dist/image-$image.txt"
134+
mkdir -p "$dist"
135+
echo "${IMAGE_TAG}" > "$info"
136+
cat "$info"
137+
138+
echo "To download the image, run docker pull ${IMAGE_TAG}"
145139
fi
140+
echo "::endgroup::"
146141
elif [ -f "$docker_dir/disabled/$image/Dockerfile" ]; then
147142
if isCI; then
148143
echo Cannot run disabled images on CI!

src/ci/github-actions/ci.yml

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ x--expand-yaml-anchors--remove:
3434
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
3535
# commit of PR sha or commit sha. `GITHUB_SHA` is not accurate for PRs.
3636
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
37+
DOCKER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3738

3839
- &public-variables
3940
SCCACHE_BUCKET: rust-lang-ci-sccache2
@@ -301,6 +302,7 @@ on:
301302

302303
permissions:
303304
contents: read
305+
packages: write
304306

305307
defaults:
306308
run:

0 commit comments

Comments
 (0)