From cd5bf5508cdfc15d097e92d426943a9500bb270d Mon Sep 17 00:00:00 2001 From: Adam Hitchcock Date: Tue, 29 Sep 2026 18:21:09 -0700 Subject: [PATCH] ci: seed rust-cache from main, skip Rust jobs on docs-only PRs (#1022) * ci: seed rust-cache from main, skip Rust jobs on docs-only PRs Every PR branch saved its own ~2 GB rust-cache per target, readable only by that branch, so the repo sat over its 10 GB quota with nothing from main and every branch built cold. Save from main pushes and manual runs only, keep the cache when a test step fails, and build with line-tables-only debug info so the cached target dir is smaller. Docs-only PRs skip the Rust work: a changes job diffs the merge commit against its base, and build skips its steps rather than the job, so the required build & test checks still report instead of pending forever. Co-Authored-By: Claude Opus 5.5 * ci: count both sides of a rename in the docs-only check --------- Co-authored-by: Claude Opus 5.5 Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> --- .github/workflows/ci.yml | 54 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aad6539f..3b7c5121 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,6 +62,34 @@ jobs: - uses: actions/checkout@v4 - run: bash .github/scripts/check-host-boundary.sh + # Docs-only PRs skip the Rust jobs: no markdown or docs/ file is compiled in. + # Workflow-level `paths-ignore` would leave the required checks pending + # forever, and a matrix job skipped by a job-level `if` reports under an + # unexpanded name, so `build` runs and skips its steps instead. + changes: + name: changes + runs-on: ubuntu-latest + timeout-minutes: 5 + outputs: + code: ${{ steps.diff.outputs.code }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 2 + # A PR checkout is the merge commit, so its first parent is the base. + # `--no-renames` lists both sides of a move, or `src/x.rs` -> `docs/x.md` + # would show only the docs path. + - id: diff + run: | + files=$(git diff --name-only --no-renames HEAD^1 HEAD) + if [ "${{ github.event_name }}" != pull_request ] \ + || grep -qvE '^docs/|\.mdx?$' <<<"$files"; then + echo "code=true" >> "$GITHUB_OUTPUT" + else + echo "code=false" >> "$GITHUB_OUTPUT" + echo "::notice::docs-only change — Rust jobs skipped" + fi + build: name: build & test (${{ matrix.target }}) strategy: @@ -74,13 +102,18 @@ jobs: target: x86_64-pc-windows-msvc - runner: ubuntu-latest target: x86_64-unknown-linux-gnu + needs: changes runs-on: ${{ matrix.runner }} + # Line tables keep file:line in backtraces but shrink the cached target dir. + env: + CARGO_PROFILE_DEV_DEBUG: line-tables-only # Backstop under the per-step timeouts below. Without any timeout at all a # hung test runs to GitHub's six-hour job limit, which is how a 90-second # step turned into a six-hour one three times in a day. timeout-minutes: 60 steps: - name: Checkout tty7 + if: needs.changes.outputs.code == 'true' uses: actions/checkout@v4 # gpui-component is a git dependency (see Cargo.toml), so no sibling @@ -91,7 +124,7 @@ jobs: # build time (build scripts resolve them via pkg-config). Same set the # README documents for building from source on Linux. - name: Install Linux system dependencies - if: runner.os == 'Linux' + if: needs.changes.outputs.code == 'true' && runner.os == 'Linux' run: | sudo apt-get update sudo apt-get install -y pkg-config cmake clang libxkbcommon-dev \ @@ -101,10 +134,18 @@ jobs: echo "LIBGSSAPI_IMPL=mit" >> "$GITHUB_ENV" - uses: dtolnay/rust-toolchain@stable + if: needs.changes.outputs.code == 'true' with: targets: ${{ matrix.target }} + # Saved only from main (and manual runs): a cache saved on a PR ref is + # readable by that ref alone, while main's is readable by every branch, + # and per-branch saves of ~2 GB per target blow the 10 GB repo quota. - uses: Swatinem/rust-cache@v2 + if: needs.changes.outputs.code == 'true' + with: + save-if: ${{ github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch' }} + cache-on-failure: true # `--locked` on the build so a Cargo.lock that disagrees with Cargo.toml # fails here instead of being silently rewritten. Without it the drift is @@ -114,6 +155,7 @@ jobs: # build too; only nightly stays unlocked, because it stamps Cargo.toml's # version and relies on cargo refreshing the lock's own root entry. - name: Build + if: needs.changes.outputs.code == 'true' # Cold-cache builds have been observed at ~10 min; warm ones at ~90s. timeout-minutes: 30 run: cargo build --locked --target ${{ matrix.target }} @@ -133,7 +175,7 @@ jobs: # proc-macro artifacts under it are host units, which are built without # the target's rustflags and legitimately import the CRT dynamically. - name: Assert the Windows binaries need no VC++ redistributable - if: runner.os == 'Windows' + if: needs.changes.outputs.code == 'true' && runner.os == 'Windows' shell: pwsh run: | & ./.github/scripts/assert-no-vcruntime.ps1 ` @@ -154,10 +196,12 @@ jobs: # also has to compile the test targets, on every platform. 20 minutes is # pure headroom, so a trip means a hang, not a slow runner. - name: Test + if: needs.changes.outputs.code == 'true' timeout-minutes: 20 run: cargo test --locked --target ${{ matrix.target }} - name: Test desktop updater + if: needs.changes.outputs.code == 'true' timeout-minutes: 10 run: cargo test --locked --features updater --bin tty7-updater --target ${{ matrix.target }} @@ -190,6 +234,8 @@ jobs: # checks, and reshaping that matrix would wedge branch protection on every open # PR. Keep this job non-required until it has a few weeks of green. server-musl: + needs: changes + if: needs.changes.outputs.code == 'true' name: tty7-server musl (${{ matrix.target }}) runs-on: ubuntu-latest timeout-minutes: 45 @@ -237,6 +283,7 @@ jobs: - uses: Swatinem/rust-cache@v2 with: key: ${{ matrix.target }} + save-if: ${{ github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch' }} # The crate split lands separately; until `tty7-server` exists as a # workspace member this job has nothing to build. Skip cleanly rather than @@ -282,6 +329,8 @@ jobs: # same job with an upload step. Non-required until it has a few weeks of # green, for the branch-protection reason spelled out above. server-macos: + needs: changes + if: needs.changes.outputs.code == 'true' name: tty7-server macOS (${{ matrix.target }}) runs-on: macos-latest timeout-minutes: 45 @@ -305,6 +354,7 @@ jobs: - uses: Swatinem/rust-cache@v2 with: key: ${{ matrix.target }} + save-if: ${{ github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch' }} - name: Look for the tty7-server package id: probe