Skip to content

Commit 607f4d5

Browse files
committed
Cirrus: Improve caching effectiveness
Prior to this commit, the cache maintained for the main branch has grown to over 16gigabytes. Uploading it is causing frequent branch-level CI failures due to being larger than the maximum allowable size by Cirrus. Attempt to fix this by introducing a cache-grooming script and altering the cache-key being used. Content for the grooming script comes mainly from three places: 1. [Cargo documentation](https://doc.rust-lang.org/nightly/cargo/guide/build-cache.html) 2. The rust-cache github action [(typescript) source code](https://github.com/Swatinem/rust-cache/tree/master/src) 3. This [cargo home in CI section](https://doc.rust-lang.org/nightly/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci) Signed-off-by: Chris Evich <[email protected]>
1 parent 749ce93 commit 607f4d5

File tree

3 files changed

+87
-8
lines changed

3 files changed

+87
-8
lines changed

.cirrus.yml

+13-8
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,15 @@ build_task:
5050
# all PRs & branches will share caches with other PRs and branches
5151
# for a given $DEST_BRANCH and vX value. Adjust vX if cache schema
5252
# changes.
53-
fingerprint_key: "cargo_v2_${DEST_BRANCH}_amd64"
53+
fingerprint_script: echo -e "cargo_v3_${DEST_BRANCH}_amd64\n---\n$(<Cargo.lock)\n---\n$(<Cargo.toml)"yy
5454
# Required to be set explicitly since fingerprint_key is also set
5555
reupload_on_changes: true
5656
targets_cache: &targets_cache
57-
# Similar to cargo_cache, but holds the actual compiled artifacts. This must
58-
# be scoped similar to bin_cache to avoid binary pollution across cache
59-
# contexts. For example, two PRs that happen to coincidentally change
60-
# and use cache. Adjust vX if cache schema changes.
57+
# Similar to cargo_cache, but holds the actual compiled dependent artifacts.
58+
# This should be scoped to a hash of the dependency-metadata lock file.
59+
# Cirrus-CI will automatically use separate caches for PRs and branches.
6160
folder: "$CARGO_TARGET_DIR"
62-
fingerprint_key: "targets_v2_${CIRRUS_TAG}${DEST_BRANCH}${CIRRUS_PR}_amd64" # Cache only within same tag, branch, or PR (branch will be 'pull/#')
61+
fingerprint_script: echo -e "targets_v3_${CIRRUS_TAG}${DEST_BRANCH}${CIRRUS_PR}_amd64\n---\n$(<Cargo.lock)\n---\n$(<Cargo.toml)"
6362
reupload_on_changes: true
6463
bin_cache: &bin_cache
6564
# This simply prevents rebuilding bin/netavark for every subsequent task.
@@ -70,6 +69,7 @@ build_task:
7069
reupload_on_changes: true
7170
setup_script: &setup "$SCRIPT_BASE/setup.sh"
7271
main_script: &main "$SCRIPT_BASE/runner.sh $CIRRUS_TASK_NAME"
72+
cache_grooming_script: &groom bash "$SCRIPT_BASE/cache_groom.sh"
7373
upload_caches: [ "cargo", "targets", "bin" ]
7474

7575

@@ -82,11 +82,15 @@ build_aarch64_task:
8282
architecture: arm64 # CAUTION: This has to be "arm64", not "aarch64"
8383
cargo_cache: &cargo_cache_aarch64
8484
folder: "$CARGO_HOME"
85-
fingerprint_key: "cargo_v2_${DEST_BRANCH}_aarch64"
85+
# N/B: Should exactly match (except for arch) line from build_task (above).
86+
# (No, there isn't an easy way to not duplicate most of this :()
87+
fingerprint_script: echo -e "cargo_v3_${DEST_BRANCH}_aarch64\n---\n$(<Cargo.lock)\n---\n$(<Cargo.toml)"yy
8688
reupload_on_changes: true
8789
targets_cache: &targets_cache_aarch64
8890
folder: "$CARGO_TARGET_DIR"
89-
fingerprint_key: "targets_v2_${CIRRUS_TAG}${DEST_BRANCH}${CIRRUS_PR}_aarch64" # Cache only within same tag, branch, or PR (branch will be 'pull/#')
91+
# N/B: Should exactly match (except for arch) line from build_task (above).
92+
# (No, there isn't an easy way to not duplicate most of this :()
93+
fingerprint_script: echo -e "targets_v3_${CIRRUS_TAG}${DEST_BRANCH}${CIRRUS_PR}_aarch64\n---\n$(<Cargo.lock)\n---\n$(<Cargo.toml)"
9094
reupload_on_changes: true
9195
bin_cache: &bin_cache_aarch64
9296
# This simply prevents rebuilding bin/netavark for every subsequent task.
@@ -95,6 +99,7 @@ build_aarch64_task:
9599
reupload_on_changes: true
96100
setup_script: *setup
97101
main_script: *main
102+
cache_grooming_script: *groom
98103
upload_caches: [ "cargo", "targets", "bin" ]
99104
# Downstream CI needs the aarch64 binaries from this CI system.
100105
# However, we don't want to confuse architectures.

contrib/cirrus/cache_groom.sh

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#!/bin/bash
2+
#
3+
# This script is intended to be run from Cirrus-CI to prepare the
4+
# rust targets cache for re-use during subsequent runs. This mainly
5+
# involves removing files and directories which change frequently
6+
# but are cheap/quick to regenerate - i.e. prevent "cache-flapping".
7+
# Any other use of this script is not supported and may cause harm.
8+
9+
set -eo pipefail
10+
11+
source $(dirname ${BASH_SOURCE[0]})/lib.sh
12+
13+
if [[ "$CIRRUS_CI" != true ]]; then
14+
die "Script is not intended for use outside of Cirrus-CI"
15+
fi
16+
17+
req_env_vars CARGO_HOME CARGO_TARGET_DIR CIRRUS_BUILD_ID
18+
19+
# Giant-meat-cleaver HACK: It's possible (with a long-running cache key) for
20+
# the targets and/or cargo cache to grow without-bound (gigabytes). Ref:
21+
# https://github.com/rust-lang/cargo/issues/5026
22+
# There isn't a good way to deal with this or account for outdated content
23+
# in some intelligent way w/o trolling through config and code files. So,
24+
# Any time the Cirrus-CI build ID is evenly divisible by some number (chosen
25+
# arbitrarily) clobber the whole thing and make the next run entirely
26+
# re-populate cache. This is ugly, but maybe the best option available :(
27+
if [[ "$CIRRUS_BRANCH" == "$DEST_BRANCH" ]] && ((CIRRUS_BUILD_ID%15==0)); then
28+
msg "It's a cache-clobber build, yay! The next build has been selected for"
29+
msg "forced cache-sterilization. That means it will be slow. Lucky you!"
30+
msg "This is necessary to prevent branch-level cache from infinitely growing."
31+
cd $CARGO_TARGET_DIR
32+
# Could use `cargo clean` for this, but it's easier to just clobber everything.
33+
rm -rf ./* ./.??*
34+
touch CACHE_WAS_CLOBBERED
35+
36+
cd $CARGO_HOME
37+
rm -rf ./* ./.??*
38+
touch CACHE_WAS_CLOBBERED
39+
exit 0
40+
fi
41+
42+
# Ref: https://doc.rust-lang.org/nightly/cargo/guide/build-cache.html
43+
# https://github.com/Swatinem/rust-cache/tree/master/src
44+
cd $CARGO_TARGET_DIR
45+
for targetname in $(find ./ -type d -maxdepth 1 -mindepth 1); do
46+
msg "Grooming $CARGO_TARGET_DIR/$targetname..."
47+
cd $CARGO_TARGET_DIR/$targetname
48+
# Any top-level hidden files or directories
49+
showrun rm -rf ./.??*
50+
# Example targets
51+
showrun rm -rf ./target/debug/examples
52+
# Documentation
53+
showrun rm -rf ./target/doc
54+
# Internal to rust build process
55+
showrun rm -rf ./target/debug/deps ./target/debug/incremental ./target/debug/build
56+
done
57+
58+
# Ref: https://doc.rust-lang.org/nightly/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci
59+
cd $CARGO_HOME
60+
for dirname in $(find ./ -type d -maxdepth 2 -mindepth 1); do
61+
case "$dirname" in
62+
./bin) ;& # same steps as next item
63+
./registry/index) ;&
64+
./registry/cache) ;&
65+
./git/db) continue ;; # Keep
66+
*) rm -rf $dirname ;; # Remove
67+
esac
68+
done

contrib/cirrus/lib.sh

+6
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ else # set default values - see make_cienv() below
3232
# VM Images are built with this setup
3333
CARGO_HOME="${CARGO_HOME:-/var/cache/cargo}"
3434
source $CARGO_HOME/env
35+
36+
# Make caching more effective - disable incremental compilation,
37+
# so that the Rust compiler doesn't waste time creating the
38+
# additional artifacts required for incremental builds.
39+
# Ref: https://github.com/marketplace/actions/rust-cache#cache-details
40+
CARGO_INCREMENTAL=0
3541
fi
3642

3743
# END Global export of all variables

0 commit comments

Comments
 (0)