48eb3d5007
Project CI / AI game creator shell Rust crates (push) Successful in 2m22s
Project CI / AI game creator shell Rust smoke (push) Successful in 3m13s
Project CI / AI game creator shell Rust lane 2/2 (push) Successful in 8m28s
Project CI / AI game creator shell Rust lane 1/2 (push) Successful in 8m58s
Project CI / Backend tests (push) Successful in 7m16s
Project CI / Native shell tests (push) Successful in 8m10s
Project CI / Frontend tests (push) Successful in 3m49s
Project CI / Repository checks (push) Successful in 4m8s
Project CI / AI game creator shell web tests (push) Successful in 4m1s
Reviewed-on: https://git.genarrative.world/git/GenarrativeAI/Genarrative/pulls/456 Co-authored-by: Linghong <ink29535@proton.me> Co-committed-by: Linghong <ink29535@proton.me>
87 lines
4.0 KiB
Bash
87 lines
4.0 KiB
Bash
#!/usr/bin/env bash
|
|
# 仅消费镜像内的可信快照;所有写入留在当前容器的可写层。
|
|
set -euo pipefail
|
|
|
|
cache_root="${GENARRATIVE_CI_RUST_CACHE_ROOT:-/opt/genarrative-ci/rust-cache}"
|
|
cache_binary="${cache_root}/sccache"
|
|
state="${GENARRATIVE_CI_RUST_CACHE_STATE:-}"
|
|
|
|
configure_local_cache() {
|
|
# 不继承开发机/其它流水线的 OSS、S3、GHA 或 daemon 配置。
|
|
local variable
|
|
for variable in ${!SCCACHE_@}; do unset "${variable}"; done
|
|
export SCCACHE_CONF="${state}/config"
|
|
export SCCACHE_DIR="${cache_root}/objects"
|
|
export SCCACHE_CACHE_SIZE=2G
|
|
export SCCACHE_SERVER_UDS="${state}/server.sock"
|
|
# 单个不可缓存的链接/测试阶段可能超过一分钟;保持统计直到 report 显式停止。
|
|
export SCCACHE_IDLE_TIMEOUT=0
|
|
export SCCACHE_IGNORE_SERVER_IO_ERROR=1
|
|
}
|
|
|
|
case "${1:-}" in
|
|
prepare)
|
|
: "${GITHUB_ENV:?GITHUB_ENV is required}"
|
|
printf 'RUSTC_WRAPPER=\nCARGO_BUILD_RUSTC_WRAPPER=\nGENARRATIVE_CI_RUST_CACHE_STATE=\n' >> "${GITHUB_ENV}"
|
|
fallback() { printf '[rust-cache] mode=direct reason=%s\n' "$1"; exit 0; }
|
|
[[ -x "${cache_binary}" && -d "${cache_root}/objects" && -f "${cache_root}/rustc.txt" && -f "${cache_root}/source-commit.txt" && -f "${cache_root}/workspace.txt" ]] \
|
|
|| fallback snapshot-unavailable
|
|
if ! rustc -vV | cmp -s - "${cache_root}/rustc.txt"; then
|
|
fallback toolchain-mismatch
|
|
fi
|
|
if [[ "$(pwd -P)" != "$(cat "${cache_root}/workspace.txt")" ]]; then
|
|
fallback workspace-mismatch
|
|
fi
|
|
# 使用短 Unix socket 路径,避免共享固定端口或超出 sockaddr_un 长度。
|
|
state="$(mktemp -d /tmp/ci-rust-cache.XXXXXX)"
|
|
printf 'server_startup_timeout_ms = 5000\n' > "${state}/config"
|
|
configure_local_cache
|
|
# 探测必须暴露 daemon 故障;只有正式编译允许 sccache 的 IO 回退。
|
|
unset SCCACHE_IGNORE_SERVER_IO_ERROR
|
|
if ! timeout --kill-after=2 15 "${cache_binary}" "$(command -v rustc)" -vV > "${state}/probe.log" 2>&1; then
|
|
timeout --kill-after=2 5 "${cache_binary}" --stop-server >/dev/null 2>&1 || true
|
|
rm -rf -- "${state}"
|
|
fallback wrapper-probe-failed
|
|
fi
|
|
script_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)/$(basename "${BASH_SOURCE[0]}")"
|
|
# wrapper 路径也参与 Rust cache key;固定容器内路径,隔离由 job 容器保证。
|
|
wrapper_path="${cache_root}/rustc-wrapper"
|
|
printf '#!/usr/bin/env bash\nexec bash %q "$@"\n' "${script_path}" > "${wrapper_path}"
|
|
chmod 700 "${wrapper_path}"
|
|
{
|
|
printf 'GENARRATIVE_CI_RUST_CACHE_ROOT=%s\n' "${cache_root}"
|
|
printf 'GENARRATIVE_CI_RUST_CACHE_STATE=%s\n' "${state}"
|
|
printf 'RUSTC_WRAPPER=%s\nCARGO_BUILD_RUSTC_WRAPPER=%s\n' "${wrapper_path}" "${wrapper_path}"
|
|
} >> "${GITHUB_ENV}"
|
|
printf '[rust-cache] mode=sccache snapshot=%s\n' "$(cat "${cache_root}/source-commit.txt")"
|
|
;;
|
|
report)
|
|
if [[ -n "${state}" && -d "${state}" ]]; then
|
|
configure_local_cache
|
|
timeout --kill-after=2 5 "${cache_binary}" --show-stats || true
|
|
timeout --kill-after=2 5 "${cache_binary}" --stop-server >/dev/null 2>&1 || true
|
|
rm -rf -- "${state}"
|
|
else
|
|
printf '[rust-cache] mode=direct\n'
|
|
fi
|
|
;;
|
|
*)
|
|
# Cargo wrapper 协议:第一个参数是真实 rustc。失去缓存状态时仍执行原编译。
|
|
if [[ -z "${state}" || ! -f "${state}/config" || -f "${state}/disabled" || ! -x "${cache_binary}" ]]; then
|
|
exec "$@"
|
|
fi
|
|
configure_local_cache
|
|
status=0
|
|
"${cache_binary}" "$@" || status=$?
|
|
if [[ "${status}" == 2 ]]; then
|
|
# 固定 sccache 版本的自身错误码为 2;实际 rustc 失败通常为 1/101。
|
|
# 只重试这次编译,不重跑 Cargo 或测试,真实编译错误仍按 rustc 状态返回。
|
|
echo '[rust-cache] cache infrastructure failed; compiling directly' >&2
|
|
# 后续 crate 直接编译,避免坏 daemon 让每个 crate 都支付一次启动超时。
|
|
: > "${state}/disabled"
|
|
exec "$@"
|
|
fi
|
|
exit "${status}"
|
|
;;
|
|
esac
|