diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index 803cb1b8..cea37e79 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -156,6 +156,8 @@ jobs: run: | sudo apt-get update sudo apt-get install --yes --no-install-recommends ripgrep + - name: Reclaim unused hosted-runner space + run: bash scripts/prepare-linux-docker-runner.sh - name: Run unified deployment smoke run: timeout --signal=TERM --kill-after=45s 32m bash scripts/unified-deployment-smoke.sh - name: Run tht update smoke diff --git a/scripts/prepare-linux-docker-runner.sh b/scripts/prepare-linux-docker-runner.sh new file mode 100755 index 00000000..259bcb30 --- /dev/null +++ b/scripts/prepare-linux-docker-runner.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +set -euo pipefail + +# The local distribution gate pulls the 7 GB Ollama image, downloads the default embedding +# model, builds the application images, and then archives every durable volume. GitHub's hosted +# Linux image also ships toolchains this job never uses. Remove only those known, runner-owned +# installations so the backup is tested with the production semantic stack instead of a stub. +[[ "$(uname -s)" == Linux ]] || { + printf 'Linux is required for hosted-runner disk preparation.\n' >&2 + exit 1 +} + +readonly unused_toolchains=( + /usr/local/lib/android + /usr/share/dotnet + /opt/ghc + /usr/local/.ghcup +) + +for path in "${unused_toolchains[@]}"; do + [[ -e "$path" || -L "$path" ]] || continue + sudo rm -rf -- "$path" +done + +sudo apt-get clean +docker system prune --all --force +df -h / +docker system df diff --git a/scripts/unified-deployment-smoke.sh b/scripts/unified-deployment-smoke.sh index 629902c4..244f5365 100755 --- a/scripts/unified-deployment-smoke.sh +++ b/scripts/unified-deployment-smoke.sh @@ -2469,12 +2469,14 @@ task13_self_test_registry_fingerprint() { task13_self_test_source_contract() { local root host_network push_command registry_function workflow uses_count pinned_uses_count + local runner_preparation path local auth_runtime_mount auth_root_mount auth_projection auth_runtime_owner local pi_auth_bind pi_projection registry_runtime_mount registry_root_mount registry_projection local application_secret_bind application_secret_mount application_secret_projection local application_secret_parent_owner application_secret_file_owner root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)" workflow="$root/.github/workflows/deployment.yml" + runner_preparation="$root/scripts/prepare-linux-docker-runner.sh" host_network='--network'' host' push_command='docker image ''push' registry_function='task13_start_''registry' @@ -2543,6 +2545,16 @@ task13_self_test_source_contract() { || task13_fail "CI lacks an outer timeout for the unified deployment smoke" grep -Eq 'timeout .*scripts/tht-update-smoke\.sh' "$workflow" \ || task13_fail "CI lacks an outer timeout for the tht update smoke" + grep -Fq 'bash scripts/prepare-linux-docker-runner.sh' "$workflow" \ + || task13_fail "CI must reclaim unused hosted-runner toolchains before the Docker release smoke" + [[ -x "$runner_preparation" ]] \ + || task13_fail "the Linux Docker runner preparation must be executable" + for path in /usr/local/lib/android /usr/share/dotnet /opt/ghc /usr/local/.ghcup; do + grep -Fq -- "$path" "$runner_preparation" \ + || task13_fail "the Linux Docker runner preparation is missing the scoped path: $path" + done + ! grep -Eq '/opt/hostedtoolcache([/[:space:]]|$)|rm[[:space:]]+-rf[[:space:]]+--?[[:space:]]+/($|[[:space:]])' "$runner_preparation" \ + || task13_fail "the Linux Docker runner preparation must not remove required tool caches or broad roots" uses_count="$(grep -Ec '^[[:space:]]+uses:' "$workflow")" pinned_uses_count="$(grep -Ec '^[[:space:]]+uses: [^[:space:]]+@[0-9a-f]{40}([[:space:]]|$)' "$workflow")" [[ "$uses_count" -gt 0 && "$uses_count" -eq "$pinned_uses_count" ]] \