diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml index 141df1e2..8f7fae7a 100644 --- a/.github/actionlint.yaml +++ b/.github/actionlint.yaml @@ -2,8 +2,3 @@ self-hosted-runner: labels: - self-hosted-fast - self-hosted-light - # Blacksmith (Ubuntu 24.04 only; see the top of workflows/ci.yml). - - blacksmith-2vcpu-ubuntu-2404 - - blacksmith-4vcpu-ubuntu-2404 - - blacksmith-8vcpu-ubuntu-2404 - - blacksmith-16vcpu-ubuntu-2404 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 24760536..2bc22e20 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,20 +15,17 @@ # that skipped the queue still runs everything. Pull requests run the reference tests when the # command line (or anything it depends on) changes, and doc tests for the affected packages. # Cross-compilation is opt-in through Run workflow; release builds remain in release.yml. -# Three runner pools. Trusted runs (pushes to main, merge-queue groups and pull requests from a -# branch of this repository: people with write access) use our own machines: Select checks and -# ci on the self-hosted light runner (`self-hosted-light`, quick jobs, so they never wait behind -# a build), and the repository checks, Clippy, the doc tests, the reference tests and test -# shards 1-2 on the self-hosted runners (`self-hosted-fast`, warm build directories via -# scripts/ci/warm-target.sh). Everything else on Linux runs on Blacksmith's Ubuntu 24.04 runners -# (blacksmith-vcpu-ubuntu-2404; not 22.04: the goldens and the lavapipe pictures are recorded -# against 24.04's glibc and Mesa): fork pull requests, the nightly run, Run workflow, the test -# archive and test shards 3-4. The Windows jobs use GitHub's windows-latest. -# The test archive is never built on our own machines: one of them has a newer glibc, so its -# binaries wouldn't start on 24.04, while a 24.04 archive runs there unchanged (same -# /home/runner/work checkout path). Blacksmith counts as self-hosted to GitHub, so steps tell -# our machines apart by runner name (minisforum-*, ci-box-*), not by runner.environment. -# Our self-hosted runners refuse any job other than a trusted one. +# Trusted runs use both pools: pushes to main, merge-queue groups and pull requests from a branch +# of this repository (people with write access; fork pull requests never run on this machine). +# There, Select checks and ci run on the self-hosted light runner (`self-hosted-light`, quick +# jobs, so they never wait behind a build), and the repository checks, Clippy, the doc tests, +# the reference tests and test shards 1-2 on the self-hosted runners (`self-hosted-fast`, warm +# build directories via scripts/ci/warm-target.sh). Fork PRs' Linux jobs run on the isolated, ephemeral +# `self-hosted-untrusted` runners (no warm caches); everything else runs on GitHub's runners. +# The test archive is always built on GitHub's runners: the self-hosted machine has a newer +# glibc, so its binaries wouldn't start on ubuntu-24.04, while the archive runs there unchanged +# (same /home/runner/work checkout path). Fork pull requests, the nightly run and Run workflow +# use GitHub's runners only; the self-hosted runners refuse any other job. name: CI on: @@ -62,7 +59,7 @@ jobs: dependency-advisories: name: Dependency advisories if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -75,7 +72,7 @@ jobs: changes: name: Select checks # Trusted runs (see the top of this file) use the self-hosted runners. - runs-on: ${{ (github.event_name == 'merge_group' || (github.event_name == 'push' && github.ref == 'refs/heads/main') || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && github.head_ref != 'ci-blacksmith')) && 'self-hosted-light' || 'blacksmith-2vcpu-ubuntu-2404' }} + runs-on: ${{ (github.event_name == 'merge_group' || (github.event_name == 'push' && github.ref == 'refs/heads/main') || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository)) && 'self-hosted-light' || ((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) && 'self-hosted-untrusted' || 'ubuntu-24.04') }} permissions: contents: read # To ask whether the merge queue already tested a commit pushed to main. @@ -87,9 +84,10 @@ jobs: full: ${{ steps.paths.outputs.full }} packages: ${{ steps.paths.outputs.packages }} oracle: ${{ steps.paths.outputs.oracle }} - # Whether the other Linux jobs use our self-hosted runners too (Blacksmith's are - # self-hosted to GitHub as well, so this goes by runner name). - local: ${{ startsWith(runner.name, 'minisforum-') || startsWith(runner.name, 'ci-box-') }} + # Whether the other Linux jobs use the self-hosted runners too. + # Trusted self-hosted runs only: a fork PR's checks run on the untrusted pool and must never + # route the jobs after them to the trusted runners. + local: ${{ runner.environment == 'self-hosted' && !(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -164,6 +162,9 @@ jobs: if [ "$EVENT_NAME" = pull_request ] && [ "$full" != true ]; then case " $packages " in *" solidcraft-cli "*) ;; *) oracle=false ;; esac fi + # The pull request fast lane: Windows and the reference tests run on main (and the nightly), + # not on every pull request push; a break there is fixed forward on main. + if [ "$EVENT_NAME" = pull_request ]; then windows=false; oracle=false; fi { echo "native=$native" echo "kernel=$kernel" @@ -175,18 +176,18 @@ jobs: checks: name: Format and repository checks - runs-on: ${{ (github.event_name == 'merge_group' || (github.event_name == 'push' && github.ref == 'refs/heads/main') || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && github.head_ref != 'ci-blacksmith')) && 'self-hosted-fast' || 'blacksmith-4vcpu-ubuntu-2404' }} + runs-on: ${{ (github.event_name == 'merge_group' || (github.event_name == 'push' && github.ref == 'refs/heads/main') || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository)) && 'self-hosted-fast' || ((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) && 'self-hosted-untrusted' || 'ubuntu-24.04') }} timeout-minutes: 15 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Warm build directory (self-hosted runner) - if: startsWith(runner.name, 'minisforum-') || startsWith(runner.name, 'ci-box-') + if: runner.environment == 'self-hosted' && !(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) run: scripts/ci/warm-target.sh checks - uses: dtolnay/rust-toolchain@stable with: components: rustfmt - # Our self-hosted runners keep their build directory and Cargo home instead. - - if: ${{ !(startsWith(runner.name, 'minisforum-') || startsWith(runner.name, 'ci-box-')) }} + # The self-hosted runner keeps its build directory and Cargo home instead. + - if: runner.environment == 'github-hosted' uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: repo-checks @@ -212,18 +213,18 @@ jobs: name: Native Linux Clippy needs: changes if: needs.changes.outputs.native == 'true' - runs-on: ${{ needs.changes.outputs.local == 'true' && 'self-hosted-fast' || 'blacksmith-16vcpu-ubuntu-2404' }} + runs-on: ${{ needs.changes.outputs.local == 'true' && 'self-hosted-fast' || ((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) && 'self-hosted-untrusted' || 'ubuntu-24.04') }} timeout-minutes: 30 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Warm build directory (self-hosted runner) - if: startsWith(runner.name, 'minisforum-') || startsWith(runner.name, 'ci-box-') + if: runner.environment == 'self-hosted' && !(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) run: scripts/ci/warm-target.sh clippy - uses: dtolnay/rust-toolchain@stable with: components: clippy - # Our self-hosted runners keep their build directory and Cargo home instead. - - if: ${{ !(startsWith(runner.name, 'minisforum-') || startsWith(runner.name, 'ci-box-')) }} + # The self-hosted runner keeps its build directory and Cargo home instead. + - if: runner.environment == 'github-hosted' uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: native-clippy @@ -242,7 +243,7 @@ jobs: name: Build tests needs: changes if: needs.changes.outputs.native == 'true' - runs-on: blacksmith-16vcpu-ubuntu-2404 + runs-on: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) && 'self-hosted-untrusted' || 'ubuntu-24.04' }} timeout-minutes: 45 env: CARGO_INCREMENTAL: "0" @@ -285,12 +286,13 @@ jobs: tests: name: Native Linux tests (${{ matrix.shard }}/4) needs: [changes, build-tests] - runs-on: ${{ (needs.changes.outputs.local == 'true' && matrix.shard <= 2) && 'self-hosted-fast' || 'blacksmith-8vcpu-ubuntu-2404' }} + runs-on: ${{ (needs.changes.outputs.local == 'true' && matrix.shard <= 2) && 'self-hosted-fast' || ((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) && 'self-hosted-untrusted' || 'ubuntu-24.04') }} timeout-minutes: 60 strategy: fail-fast: false matrix: - shard: [1, 2, 3, 4] + # Pull requests test their affected crates in 2 shards; main and the nightly use 4. + shard: ${{ fromJSON(github.event_name == 'pull_request' && '[1, 2]' || '[1, 2, 3, 4]') }} env: # Pictures (snapshots, screenshots, ui.render, the viewport's offscreen tests) are drawn on # the GPU. The runner has none: Mesa's lavapipe (software Vulkan) draws them, and a test that @@ -300,8 +302,8 @@ jobs: steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install a software Vulkan driver (lavapipe) - # Preinstalled on our self-hosted runners, which have no sudo. - if: ${{ !(startsWith(runner.name, 'minisforum-') || startsWith(runner.name, 'ci-box-')) }} + # Preinstalled on the self-hosted runner, which has no sudo. + if: runner.environment == 'github-hosted' run: | sudo apt-get update sudo apt-get install -y --no-install-recommends mesa-vulkan-drivers libvulkan1 @@ -315,6 +317,7 @@ jobs: env: EVENT_NAME: ${{ github.event_name }} SHARD: ${{ matrix.shard }} + SHARDS: ${{ github.event_name == 'pull_request' && 2 || 4 }} run: | # Pull requests skip the heavy tests (default-filter in .config/nextest.toml). all=() @@ -326,17 +329,7 @@ jobs: # Extract into ./target: tests that run a built binary (env!("CARGO_BIN_EXE_*")) have # the build job's path, which is the same checkout path here. cargo nextest run --archive-file tests.tar.zst --workspace-remap . --extract-to . --extract-overwrite \ - --profile ci --partition "slice:$SHARD/4" --no-tests=pass "${all[@]}" - - name: Robustness goldens sample (pull requests that touch the kernel) - # Every 8th seed of tests/robustness/goldens.json (each seed is a test), a quarter per - # shard; pushes to main and the nightly run every seed in the step above. - if: github.event_name == 'pull_request' && needs.changes.outputs.kernel == 'true' - env: - SHARD: ${{ matrix.shard }} - run: | - cargo nextest run --archive-file tests.tar.zst --workspace-remap . --extract-to . --extract-overwrite \ - --profile ci --ignore-default-filter --partition "slice:$SHARD/4" --no-tests=pass \ - -E 'package(solidcraft-engine) & test(/^tests::robustness_goldens::seed_(00|08|16|24|32|40|48|56|64|72|80|88)$/)' + --profile ci --partition "slice:$SHARD/$SHARDS" --no-tests=pass "${all[@]}" - name: Upload test timings if: always() uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 @@ -353,7 +346,7 @@ jobs: name: Action matrix (${{ matrix.shard }}/16) needs: build-tests if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 55 strategy: fail-fast: false @@ -395,7 +388,7 @@ jobs: name: Action matrix determinism needs: build-tests if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 45 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -417,7 +410,7 @@ jobs: name: Property tests (many cases) needs: build-tests if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 60 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -441,7 +434,7 @@ jobs: name: Doc tests needs: changes if: needs.changes.outputs.native == 'true' - runs-on: ${{ needs.changes.outputs.local == 'true' && 'self-hosted-fast' || 'blacksmith-8vcpu-ubuntu-2404' }} + runs-on: ${{ needs.changes.outputs.local == 'true' && 'self-hosted-fast' || ((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) && 'self-hosted-untrusted' || 'ubuntu-24.04') }} timeout-minutes: 45 env: CARGO_INCREMENTAL: "0" @@ -451,11 +444,11 @@ jobs: steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Warm build directory (self-hosted runner) - if: startsWith(runner.name, 'minisforum-') || startsWith(runner.name, 'ci-box-') + if: runner.environment == 'self-hosted' && !(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) run: scripts/ci/warm-target.sh doc-tests - uses: dtolnay/rust-toolchain@stable - # Our self-hosted runners keep their build directory and Cargo home instead. - - if: ${{ !(startsWith(runner.name, 'minisforum-') || startsWith(runner.name, 'ci-box-')) }} + # The self-hosted runner keeps its build directory and Cargo home instead. + - if: runner.environment == 'github-hosted' uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: doc-tests @@ -491,7 +484,7 @@ jobs: name: Reference tests needs: changes if: needs.changes.outputs.oracle == 'true' - runs-on: ${{ needs.changes.outputs.local == 'true' && 'self-hosted-fast' || 'blacksmith-8vcpu-ubuntu-2404' }} + runs-on: ${{ needs.changes.outputs.local == 'true' && 'self-hosted-fast' || ((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) && 'self-hosted-untrusted' || 'ubuntu-24.04') }} timeout-minutes: 60 env: CARGO_INCREMENTAL: "0" @@ -501,11 +494,11 @@ jobs: steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Warm build directory (self-hosted runner) - if: startsWith(runner.name, 'minisforum-') || startsWith(runner.name, 'ci-box-') + if: runner.environment == 'self-hosted' && !(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) run: scripts/ci/warm-target.sh oracle - uses: dtolnay/rust-toolchain@stable - # Our self-hosted runners keep their build directory and Cargo home instead. - - if: ${{ !(startsWith(runner.name, 'minisforum-') || startsWith(runner.name, 'ci-box-')) }} + # The self-hosted runner keeps its build directory and Cargo home instead. + - if: runner.environment == 'github-hosted' uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: oracle @@ -586,7 +579,7 @@ jobs: ci: needs: [changes, checks, clippy, build-tests, tests, doc-tests, oracle, windows-fxc, windows-startup] if: always() - runs-on: ${{ needs.changes.outputs.local == 'true' && 'self-hosted-light' || 'blacksmith-2vcpu-ubuntu-2404' }} + runs-on: ${{ needs.changes.outputs.local == 'true' && 'self-hosted-light' || ((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) && 'self-hosted-untrusted' || 'ubuntu-24.04') }} steps: - name: Verify required checks env: @@ -622,7 +615,7 @@ jobs: wasm: name: Compile WebAssembly (manual) if: github.event_name == 'workflow_dispatch' && inputs.cross_compile - runs-on: blacksmith-8vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 30 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -638,7 +631,7 @@ jobs: riscv64-gates: name: Compile RISC-V (manual) if: github.event_name == 'workflow_dispatch' && inputs.cross_compile - runs-on: blacksmith-8vcpu-ubuntu-2404 + runs-on: ubuntu-24.04 timeout-minutes: 30 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1