diff --git a/.github/actions/free-runner-disk/action.yml b/.github/actions/free-runner-disk/action.yml new file mode 100644 index 00000000..84a8f857 --- /dev/null +++ b/.github/actions/free-runner-disk/action.yml @@ -0,0 +1,16 @@ +name: Free runner disk +description: Remove preinstalled toolchains the build never uses from a hosted Linux runner +runs: + using: composite + steps: + # The hosted Ubuntu image leaves too little free space for a full + # instrumented or all-feature workspace build beside the restored caches + # and the native oracle. These toolchains are never used by this build. + # Self-hosted runners keep their own provisioning. + - name: Remove unused hosted toolchains + if: runner.os == 'Linux' && runner.environment == 'github-hosted' + shell: bash + run: | + df -h / + sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL + df -h / diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d8377c1..f4575bbe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,6 +56,7 @@ jobs: - uses: actions/checkout@v7 with: persist-credentials: false + - uses: ./.github/actions/free-runner-disk - name: Read pinned oracle revisions id: coverage-oracles run: | @@ -334,6 +335,7 @@ jobs: - uses: actions/checkout@v7 with: persist-credentials: false + - uses: ./.github/actions/free-runner-disk - name: Read pinned donor revision id: test-donor-revision run: | diff --git a/tools/xml-sec-tools/src/workflow_contracts.rs b/tools/xml-sec-tools/src/workflow_contracts.rs index 97d357c9..fd9e54b6 100644 --- a/tools/xml-sec-tools/src/workflow_contracts.rs +++ b/tools/xml-sec-tools/src/workflow_contracts.rs @@ -253,6 +253,27 @@ fn runner_image_identity_is_read_at_runtime_rather_than_an_empty_env_context() { } } +#[test] +fn the_heaviest_jobs_free_hosted_runner_disk_before_restoring_any_cache() { + // Full-workspace builds beside the caches and the native oracle exhaust the + // hosted image's disk; the space must be freed before anything is restored. + let action = read(".github/actions/free-runner-disk/action.yml"); + assert!(action.contains("if: runner.os == 'Linux' && runner.environment == 'github-hosted'")); + let workflow = read(".github/workflows/ci.yml"); + for job in ["coverage", "test-matrix"] { + let body = section(&workflow, job); + let freed = body + .find("uses: ./.github/actions/free-runner-disk") + .unwrap_or_else(|| panic!("{job} frees no disk")); + for cache in ["rust-build-cache", "xmlsec-oracle-cache"] { + let restored = body + .find(&format!("uses: ./.github/actions/{cache}")) + .unwrap(); + assert!(freed < restored, "{job}: {cache}"); + } + } +} + #[test] fn coverage_checkout_references_resolve_existing_pinned_oracle_revisions() { // Validate the actual setup program, not just YAML syntax: a misspelled