mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-03 02:25:55 +00:00
CI: approved fork PRs run heavy jobs on self-hosted-fast in private directories
An approved-for-ci label on a fork pull request sends Clippy, Build tests, the test shards and Doc tests to the trusted runners, with private copies of the build directory, Cargo home and rustup home that are deleted after the job. Only the labeling event qualifies; later pushes use the old fork routing. The skipped run of an unrelated label names its ci job differently. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -102,6 +102,11 @@ jobs:
|
||||
full: ${{ steps.paths.outputs.full }}
|
||||
# Code changed on a pull request that has no approved-for-ci label yet: only Quick compile.
|
||||
quick: ${{ steps.paths.outputs.quick }}
|
||||
# An approved fork pull request whose approval is this very run: its heavy jobs run on the
|
||||
# trusted self-hosted-fast runners, in private copies of the warm directories (fork-scratch.sh).
|
||||
# Only the `labeled` event qualifies, so a later push to the fork's branch (unreviewed code)
|
||||
# falls back to the fork routing above until a maintainer labels it again. `local` stays false.
|
||||
fork_heavy: ${{ github.event_name == 'pull_request' && github.event.action == 'labeled' && github.event.label.name == 'approved-for-ci' && github.event.pull_request.head.repo.full_name != github.repository }}
|
||||
packages: ${{ steps.paths.outputs.packages }}
|
||||
oracle: ${{ steps.paths.outputs.oracle }}
|
||||
# Whether the other Linux jobs use the self-hosted runners too.
|
||||
@@ -282,10 +287,13 @@ jobs:
|
||||
name: Native Linux Clippy
|
||||
needs: changes
|
||||
if: needs.changes.outputs.native == 'true'
|
||||
runs-on: ${{ needs.changes.outputs.local == 'true' && 'self-hosted-fast' || 'ubuntu-24.04' }}
|
||||
runs-on: ${{ needs.changes.outputs.fork_heavy == 'true' && 'self-hosted-fast' || needs.changes.outputs.local == 'true' && 'self-hosted-fast' || 'ubuntu-24.04' }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Private build, Cargo and rustup directories (approved fork pull request)
|
||||
if: needs.changes.outputs.fork_heavy == 'true'
|
||||
run: scripts/ci/fork-scratch.sh clippy
|
||||
- name: Warm build directory (self-hosted runner)
|
||||
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
|
||||
@@ -308,12 +316,15 @@ jobs:
|
||||
scope=(--workspace)
|
||||
if [ "$FULL" != true ]; then scope=(); for p in $PACKAGES; do scope+=(-p "$p"); done; fi
|
||||
cargo clippy "${scope[@]}" --all-targets --profile ci --locked -- -D warnings
|
||||
- name: Delete the private directories
|
||||
if: always() && needs.changes.outputs.fork_heavy == 'true'
|
||||
run: scripts/ci/fork-scratch.sh --clean
|
||||
|
||||
build-tests:
|
||||
name: Build tests
|
||||
needs: changes
|
||||
if: needs.changes.outputs.native == 'true'
|
||||
runs-on: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && (endsWith(format('{0}', github.event.pull_request.number), '7') || endsWith(format('{0}', github.event.pull_request.number), '8') || endsWith(format('{0}', github.event.pull_request.number), '9'))) && 'self-hosted-untrusted' || 'ubuntu-24.04' }}
|
||||
runs-on: ${{ needs.changes.outputs.fork_heavy == 'true' && 'self-hosted-fast' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && (endsWith(format('{0}', github.event.pull_request.number), '7') || endsWith(format('{0}', github.event.pull_request.number), '8') || endsWith(format('{0}', github.event.pull_request.number), '9'))) && 'self-hosted-untrusted' || 'ubuntu-24.04' }}
|
||||
# Fork builds compile inside gVisor on shared boxes; give them room to finish and upload.
|
||||
timeout-minutes: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && (endsWith(format('{0}', github.event.pull_request.number), '7') || endsWith(format('{0}', github.event.pull_request.number), '8') || endsWith(format('{0}', github.event.pull_request.number), '9'))) && 90 || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) && 60 || 45 }}
|
||||
env:
|
||||
@@ -323,6 +334,9 @@ jobs:
|
||||
SCCACHE_IGNORE_SERVER_IO_ERROR: "1"
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Private build, Cargo and rustup directories (approved fork pull request)
|
||||
if: needs.changes.outputs.fork_heavy == 'true'
|
||||
run: scripts/ci/fork-scratch.sh
|
||||
- name: Size parallel compiles to the job's memory
|
||||
run: scripts/ci/build-jobs.sh
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
@@ -355,11 +369,14 @@ jobs:
|
||||
- name: Compiler cache statistics
|
||||
if: always()
|
||||
run: sccache --show-stats
|
||||
- name: Delete the private directories
|
||||
if: always() && needs.changes.outputs.fork_heavy == 'true'
|
||||
run: scripts/ci/fork-scratch.sh --clean
|
||||
|
||||
tests:
|
||||
name: Native Linux tests (${{ matrix.shard }}/4)
|
||||
needs: [changes, build-tests]
|
||||
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 && (endsWith(format('{0}', github.event.pull_request.number), '7') || endsWith(format('{0}', github.event.pull_request.number), '8') || endsWith(format('{0}', github.event.pull_request.number), '9'))) && 'self-hosted-untrusted' || 'ubuntu-24.04') }}
|
||||
runs-on: ${{ needs.changes.outputs.fork_heavy == 'true' && 'self-hosted-fast' || needs.changes.outputs.local == 'true' && 'self-hosted-fast' || ((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && (endsWith(format('{0}', github.event.pull_request.number), '7') || endsWith(format('{0}', github.event.pull_request.number), '8') || endsWith(format('{0}', github.event.pull_request.number), '9'))) && 'self-hosted-untrusted' || 'ubuntu-24.04') }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -374,6 +391,9 @@ jobs:
|
||||
SOLIDCRAFT_REQUIRE_GPU: "1"
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Private build, Cargo and rustup directories (approved fork pull request)
|
||||
if: needs.changes.outputs.fork_heavy == 'true'
|
||||
run: scripts/ci/fork-scratch.sh
|
||||
- name: Install a software Vulkan driver (lavapipe)
|
||||
# Preinstalled on the self-hosted runner, which has no sudo.
|
||||
if: runner.environment == 'github-hosted'
|
||||
@@ -425,6 +445,9 @@ jobs:
|
||||
name: junit-${{ matrix.shard }}
|
||||
path: target/nextest/ci/junit.xml
|
||||
retention-days: 7
|
||||
- name: Delete the private directories
|
||||
if: always() && needs.changes.outputs.fork_heavy == 'true'
|
||||
run: scripts/ci/fork-scratch.sh --clean
|
||||
|
||||
action-matrix:
|
||||
# Every ordinary action on every face, edge, vertex and body of the design corpus, against
|
||||
@@ -522,7 +545,7 @@ jobs:
|
||||
name: Doc tests
|
||||
needs: changes
|
||||
if: needs.changes.outputs.native == 'true'
|
||||
runs-on: ${{ needs.changes.outputs.local == 'true' && 'self-hosted-fast' || 'ubuntu-24.04' }}
|
||||
runs-on: ${{ needs.changes.outputs.fork_heavy == 'true' && 'self-hosted-fast' || needs.changes.outputs.local == 'true' && 'self-hosted-fast' || 'ubuntu-24.04' }}
|
||||
timeout-minutes: 45
|
||||
env:
|
||||
CARGO_INCREMENTAL: "0"
|
||||
@@ -531,6 +554,9 @@ jobs:
|
||||
SCCACHE_IGNORE_SERVER_IO_ERROR: "1"
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Private build, Cargo and rustup directories (approved fork pull request)
|
||||
if: needs.changes.outputs.fork_heavy == 'true'
|
||||
run: scripts/ci/fork-scratch.sh doc-tests
|
||||
- name: Size parallel compiles to the job's memory
|
||||
run: scripts/ci/build-jobs.sh
|
||||
- name: Warm build directory (self-hosted runner)
|
||||
@@ -570,6 +596,9 @@ jobs:
|
||||
exit 0
|
||||
fi
|
||||
cargo test "${scope[@]}" --profile ci --locked --doc
|
||||
- name: Delete the private directories
|
||||
if: always() && needs.changes.outputs.fork_heavy == 'true'
|
||||
run: scripts/ci/fork-scratch.sh --clean
|
||||
|
||||
oracle:
|
||||
name: Reference tests
|
||||
@@ -671,6 +700,9 @@ jobs:
|
||||
|
||||
# Preserve the existing check name for branch protection, including docs-only PRs.
|
||||
ci:
|
||||
# On the skipped run another label starts, this job is named differently, so that skipped job
|
||||
# can never stand in for the required `ci` check of the pull request's real run.
|
||||
name: ${{ github.event.action == 'labeled' && github.event.label.name != 'approved-for-ci' && 'ci (ignored label)' || 'ci' }}
|
||||
needs: [changes, checks, quick-compile, clippy, build-tests, tests, doc-tests, oracle, windows-fxc, windows-startup]
|
||||
if: always() && (github.event_name != 'pull_request' || !github.event.pull_request.draft) && (github.event.action != 'labeled' || github.event.label.name == 'approved-for-ci')
|
||||
runs-on: ${{ needs.changes.outputs.local == 'true' && 'self-hosted-light' || 'ubuntu-24.04' }}
|
||||
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
# Self-hosted runner, approved fork pull requests only: give the job private copies of the build
|
||||
# directory, Cargo home and rustup home, so the job never writes to the shared warm directories
|
||||
# that main and merge-queue runs reuse (a build script or test from a fork could otherwise leave
|
||||
# files there). The copies start as the warm state (reflinks where the filesystem has them) and
|
||||
# `fork-scratch.sh --clean` deletes them at the end of the job.
|
||||
# Usage: fork-scratch.sh [NAME] NAME = the warm-target.sh directory to start the build from
|
||||
# fork-scratch.sh --clean
|
||||
# This keeps shared state out of reach of ordinary writes. It is not a sandbox: fork code still
|
||||
# runs as the runner's user, which is why the workflow starts it only from a `labeled` event a
|
||||
# maintainer triggered, never from a push.
|
||||
set -euo pipefail
|
||||
base=${RUNNER_TEMP:?}/fork-scratch
|
||||
if [ "${1:-}" = --clean ]; then
|
||||
rm -rf "$base"
|
||||
exit 0
|
||||
fi
|
||||
if [ "${GITHUB_EVENT_NAME:-}" != pull_request ]; then
|
||||
echo "fork-scratch: only for pull request runs" >&2
|
||||
exit 1
|
||||
fi
|
||||
name=${1:-}
|
||||
rm -rf "$base"
|
||||
mkdir -p "$base"
|
||||
if [ -n "$name" ]; then
|
||||
warm=/home/runner/work/cargo-target/$name
|
||||
if [ -d "$warm" ]; then
|
||||
cp -a --reflink=auto "$warm" "$base/target"
|
||||
else
|
||||
mkdir -p "$base/target"
|
||||
fi
|
||||
echo "CARGO_TARGET_DIR=$base/target" >> "$GITHUB_ENV"
|
||||
fi
|
||||
cargo_home=${CARGO_HOME:-$HOME/.cargo}
|
||||
rustup_home=${RUSTUP_HOME:-$HOME/.rustup}
|
||||
mkdir -p "$base/cargo-home" "$base/rustup-home"
|
||||
[ -d "$cargo_home" ] && cp -a --reflink=auto "$cargo_home/." "$base/cargo-home/"
|
||||
[ -d "$rustup_home" ] && cp -a --reflink=auto "$rustup_home/." "$base/rustup-home/"
|
||||
{
|
||||
echo "CARGO_HOME=$base/cargo-home"
|
||||
echo "RUSTUP_HOME=$base/rustup-home"
|
||||
} >> "$GITHUB_ENV"
|
||||
echo "$base/cargo-home/bin" >> "$GITHUB_PATH"
|
||||
echo "fork-scratch: private copies in $base ($(du -sh "$base" | cut -f1))"
|
||||
Reference in New Issue
Block a user