Files
ci/bin/gocache

45 lines
2.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# gocache — this org's Go module and build cache, carried between runners.
#
# gocache restore <module-dir> # prints hit=exact|partial|miss to $GITHUB_OUTPUT
# gocache save <module-dir> # writes on a trusted ref, on a miss, and nowhere else
#
# A runner is a pod that lives for one job, so a cache on its disk dies with it.
# Measured across 188 job logs: not one Go cache was restored, and 142 Go-gate
# minutes were 31 downloading modules, 69 compiling and 41 testing. A second
# pass over a warm cache compiled hanzoai/commerce's vet in 15s instead of 198s.
#
# The store, who may write, the parts and the index are bin/cache's; this script
# names what Go caches and what that is valid for.
#
# THE KEY: <owner/repo>/<go version>-<arch>/<sha256 of go.sum>. Modules are a
# function of go.sum, and a build cache is only valid for the toolchain and
# architecture that wrote it. A key that misses restores the newest key the repo
# saved (`latest`), so a go.sum bump still reuses every module that did not move.
#
# Go trusts GOMODCACHE and GOCACHE without re-hashing them, which is why only a
# trusted ref writes (bin/cache).
#
# ENV: everything bin/cache reads (HANZO_API_TOKEN, HANZO_API, CACHE_BUCKET, CACHE_PART).
set -uo pipefail
cmd="${1:-}"; dir="${2:-.}"
out="${GITHUB_OUTPUT:-/dev/null}"
skip() { echo "::notice::gocache: $*"; echo "hit=miss" >> "$out"; exit 0; }
case "$cmd" in restore|save) ;; *) echo "usage: gocache restore|save <module-dir>" >&2; exit 2 ;; esac
command -v go >/dev/null 2>&1 || skip "go is not on this runner"
[ -f "$dir/go.sum" ] || skip "$dir has no go.sum"
mod=$(go env GOMODCACHE); build=$(go env GOCACHE)
# Every later step reads the caches from exactly these directories, so a gate
# that names its own with `${GOCACHE:-…}` (hanzo-inc/cloud's do) builds into what
# was restored, and save archives what the gate built.
[ "$cmd" = restore ] && printf 'GOMODCACHE=%s\nGOCACHE=%s\n' "$mod" "$build" >> "${GITHUB_ENV:-/dev/null}"
if [ "$cmd" = save ]; then
[ -d "$mod" ] || { echo "gocache: no module cache to save"; exit 0; }
mkdir -p "$build" # a gate that compiled nothing still leaves modules worth keeping
fi
exec "$(dirname "$0")/cache" "$cmd" "$(go env GOVERSION)-$(go env GOARCH)" \
"$(sha256sum "$dir/go.sum" | cut -c1-32)" mod="$mod" build="$build"