From f7343e9161bc6243cdb076d3b6c3594db97279ff Mon Sep 17 00:00:00 2001 From: Irakli Kourtis Date: Sat, 17 Oct 2026 10:21:08 -0400 Subject: [PATCH] CI: a main push the merge queue already tested runs only repository checks (#1860) The merge queue runs the full suite on exactly the commit it then puts on main, and main's push run then ran the full suite again on the same files. Select checks now asks the Actions API whether a passing merge_group CI run exists for the pushed commit; if so the push runs only the repository checks. A push that skipped the queue, or an API that cannot answer, still runs everything. The nightly still runs the whole suite. Pull requests also run less: the reference tests only when solidcraft-cli (or anything it depends on) is affected, and doc tests only for the affected packages that have a library. The ci check requires the reference tests only when they were selected. Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM Co-authored-by: jyviko <2501648+jyviko@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 --- .github/workflows/ci.yml | 62 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a9215b1..9448e79a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,10 @@ # and app startup) run on pull requests only when what they test changes (the GPU crate, the app, # the viewport's GPU glue, the graphics dependencies, their scripts or this file); main and # nightly always run them. Only main saves the build caches; pull requests restore them. +# The merge queue runs the full suite on exactly the commit it then puts on main, so a push to +# main that a passing merge-queue run already tested runs only the repository checks; a push +# 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. # Pushes to main and merge-queue groups use both pools: Clippy, the doc tests and test shards # 1-2 run on the self-hosted runner (`self-hosted-fast`, warm build directories via @@ -64,12 +68,17 @@ jobs: changes: name: Select checks runs-on: ubuntu-24.04 + permissions: + contents: read + # To ask whether the merge queue already tested a commit pushed to main. + actions: read outputs: native: ${{ steps.paths.outputs.native }} kernel: ${{ steps.paths.outputs.kernel }} windows: ${{ steps.paths.outputs.windows }} full: ${{ steps.paths.outputs.full }} packages: ${{ steps.paths.outputs.packages }} + oracle: ${{ steps.paths.outputs.oracle }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -80,13 +89,30 @@ jobs: EVENT_NAME: ${{ github.event_name }} BASE_SHA: ${{ github.event.pull_request.base.sha }} HEAD_SHA: ${{ github.event.pull_request.head.sha }} + PUSH_SHA: ${{ github.sha }} + REPO: ${{ github.repository }} + GH_TOKEN: ${{ github.token }} run: | native=false kernel=false windows=false full=true packages= - if [ "$EVENT_NAME" != pull_request ]; then + if [ "$EVENT_NAME" = push ]; then + # The queue lands the very commit its merge_group run tested. If that run passed, + # testing the push again proves nothing new; otherwise (a merge that skipped the + # queue, or the API cannot answer) test everything. + # curl and grep only: Select checks of a push runs on the self-hosted runner. + tested=$(curl -fsS -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \ + "https://api.github.com/repos/$REPO/actions/workflows/ci.yml/runs?event=merge_group&head_sha=$PUSH_SHA&status=success&per_page=1" \ + | grep -o '"total_count": *[0-9]*' | grep -o '[0-9]*$' || echo 0) + if [ "${tested:-0}" -gt 0 ]; then + echo "The merge queue already tested $PUSH_SHA: repository checks only." + else + native=true + windows=true + fi + elif [ "$EVENT_NAME" != pull_request ]; then native=true windows=true else @@ -121,10 +147,17 @@ jobs: # Code changed but nothing was selected: be safe and test everything. if [ "$native" = true ] && [ "$full" != true ] && [ -z "$packages" ]; then full=true; fi fi + # The reference tests replay recipes through solidcraft-cli: needed when it, or anything + # it depends on, is selected. + oracle=$native + if [ "$EVENT_NAME" = pull_request ] && [ "$full" != true ]; then + case " $packages " in *" solidcraft-cli "*) ;; *) oracle=false ;; esac + fi { echo "native=$native" echo "kernel=$kernel" echo "windows=$windows" + echo "oracle=$oracle" echo "full=$full" echo "packages=$packages" } >> "$GITHUB_OUTPUT" @@ -416,12 +449,32 @@ jobs: with: version: v0.16.0 # nextest does not run doc tests. - - run: cargo test --workspace --profile ci --locked --doc + - name: Doc tests + env: + FULL: ${{ needs.changes.outputs.full }} + PACKAGES: ${{ needs.changes.outputs.packages }} + run: | + # Pull requests test the affected packages that have a library (only libraries have doc + # tests); everything else, the whole workspace. + scope=(--workspace) + if [ "$FULL" != true ]; then + scope=() + libs=$(cargo metadata --no-deps --format-version 1 --locked \ + | python3 -I -c 'import json, sys; print(" ".join(p["name"] for p in json.load(sys.stdin)["packages"] if any("lib" in t["kind"] for t in p["targets"])))') + for p in $PACKAGES; do + case " $libs " in *" $p "*) scope+=(-p "$p") ;; esac + done + fi + if [ ${#scope[@]} -eq 0 ]; then + echo "No affected package has a library: no doc tests to run." + exit 0 + fi + cargo test "${scope[@]}" --profile ci --locked --doc oracle: name: Reference tests needs: changes - if: needs.changes.outputs.native == 'true' + if: needs.changes.outputs.oracle == 'true' runs-on: ubuntu-24.04 timeout-minutes: 60 env: @@ -520,6 +573,7 @@ jobs: CHECKS: ${{ needs.checks.result }} NATIVE: ${{ needs.changes.outputs.native }} WINDOWS: ${{ needs.changes.outputs.windows }} + ORACLE_RUN: ${{ needs.changes.outputs.oracle }} CLIPPY: ${{ needs.clippy.result }} BUILD: ${{ needs.build-tests.result }} TESTS: ${{ needs.tests.result }} @@ -535,6 +589,8 @@ jobs: test "$BUILD" = success test "$TESTS" = success test "$DOCS" = success + fi + if [ "$ORACLE_RUN" = true ]; then test "$ORACLE" = success fi if [ "$WINDOWS" = true ]; then