99# CI builds in debug (dev) for faster signal.
1010
1111jobs :
12- # --- Detect what changed (always runs) -------------------------------------
12+ # --- Detect what changed to detect which tests to run (always runs) -------------------------------------
1313 changed :
1414 name : Detect changed areas
1515 runs-on : ubuntu-24.04
8484 run : cargo shear
8585
8686 # --- CI to validate on different os/targets --------------------------------
87- lint_build_test :
88- name : ${{ matrix.runner }} - ${{ matrix.target }}${{ matrix.profile == 'release' && ' (release)' || '' }}
87+ lint_build :
88+ name : Lint/Build — ${{ matrix.runner }} - ${{ matrix.target }}${{ matrix.profile == 'release' && ' (release)' || '' }}
8989 runs-on : ${{ matrix.runner }}
9090 timeout-minutes : 30
9191 needs : changed
9494 defaults :
9595 run :
9696 working-directory : codex-rs
97+ env :
98+ # Speed up repeated builds across CI runs by caching compiled objects.
99+ RUSTC_WRAPPER : sccache
100+ CARGO_INCREMENTAL : " 0"
101+ SCCACHE_CACHE_SIZE : 10G
97102
98103 strategy :
99104 fail-fast : false
@@ -159,20 +164,83 @@ jobs:
159164 ~/.cargo/registry/index/
160165 ~/.cargo/registry/cache/
161166 ~/.cargo/git/db/
162- key : cargo-home-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ hashFiles('**/Cargo.lock') }}
167+ key : cargo-home-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ hashFiles('**/Cargo.lock') }}-${{ hashFiles('codex-rs/rust-toolchain.toml') }}
168+ restore-keys : |
169+ cargo-home-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-
163170
164- - name : Restore target cache (except gnu-dev)
165- id : cache_target_restore
166- if : ${{ !(matrix.target == 'x86_64-unknown-linux-gnu' && matrix.profile != 'release') }}
171+ # Install and restore sccache cache
172+ - name : Install sccache
173+ uses : taiki-e/install-action@0c5db7f7f897c03b771660e91d065338615679f4 # v2
174+ with :
175+ tool : sccache
176+ version : 0.7.5
177+
178+ - name : Configure sccache backend
179+ shell : bash
180+ run : |
181+ set -euo pipefail
182+ if [[ -n "${ACTIONS_CACHE_URL:-}" && -n "${ACTIONS_RUNTIME_TOKEN:-}" ]]; then
183+ echo "SCCACHE_GHA_ENABLED=true" >> "$GITHUB_ENV"
184+ echo "Using sccache GitHub backend"
185+ else
186+ echo "SCCACHE_GHA_ENABLED=false" >> "$GITHUB_ENV"
187+ echo "SCCACHE_DIR=${{ github.workspace }}/.sccache" >> "$GITHUB_ENV"
188+ echo "Using sccache local disk + actions/cache fallback"
189+ fi
190+
191+ - name : Restore sccache cache (fallback)
192+ if : ${{ env.SCCACHE_GHA_ENABLED != 'true' }}
193+ id : cache_sccache_restore
167194 uses : actions/cache/restore@v4
168195 with :
169- path : ${{ github.workspace }}/codex-rs/target/
170- key : cargo-target-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ hashFiles('**/Cargo.lock') }}
196+ path : ${{ github.workspace }}/.sccache/
197+ key : sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ hashFiles('**/Cargo.lock') }}-${{ github.run_id }}
198+ restore-keys : |
199+ sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ hashFiles('**/Cargo.lock') }}-
200+ sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-
201+
202+ - if : ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}}
203+ name : Prepare APT cache directories (musl)
204+ shell : bash
205+ run : |
206+ set -euo pipefail
207+ sudo mkdir -p /var/cache/apt/archives /var/lib/apt/lists
208+ sudo chown -R "$USER:$USER" /var/cache/apt /var/lib/apt/lists
209+
210+ - if : ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}}
211+ name : Restore APT cache (musl)
212+ id : cache_apt_restore
213+ uses : actions/cache/restore@v4
214+ with :
215+ path : |
216+ /var/cache/apt
217+ key : apt-${{ matrix.runner }}-${{ matrix.target }}-v1
171218
172219 - if : ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}}
173220 name : Install musl build tools
221+ env :
222+ DEBIAN_FRONTEND : noninteractive
223+ shell : bash
224+ run : |
225+ set -euo pipefail
226+ sudo apt-get -y update -o Acquire::Retries=3
227+ sudo apt-get -y install --no-install-recommends musl-tools pkg-config
228+
229+ - name : Install cargo-chef
230+ if : ${{ matrix.profile == 'release' }}
231+ uses : taiki-e/install-action@0c5db7f7f897c03b771660e91d065338615679f4 # v2
232+ with :
233+ tool : cargo-chef
234+ version : 0.1.71
235+
236+ - name : Pre-warm dependency cache (cargo-chef)
237+ if : ${{ matrix.profile == 'release' }}
238+ shell : bash
174239 run : |
175- sudo apt install -y musl-tools pkg-config && sudo rm -rf /var/lib/apt/lists/*
240+ set -euo pipefail
241+ RECIPE="${RUNNER_TEMP}/chef-recipe.json"
242+ cargo chef prepare --recipe-path "$RECIPE"
243+ cargo chef cook --recipe-path "$RECIPE" --target ${{ matrix.target }} --release --all-features
176244
177245 - name : cargo clippy
178246 id : clippy
@@ -191,22 +259,158 @@ jobs:
191259 find . -name Cargo.toml -mindepth 2 -maxdepth 2 -print0 \
192260 | xargs -0 -n1 -I{} bash -c 'cd "$(dirname "{}")" && cargo check --profile ${{ matrix.profile }}'
193261
262+ # Save caches explicitly; make non-fatal so cache packaging
263+ # never fails the overall job. Only save when key wasn't hit.
264+ - name : Save cargo home cache
265+ if : always() && !cancelled() && steps.cache_cargo_home_restore.outputs.cache-hit != 'true'
266+ continue-on-error : true
267+ uses : actions/cache/save@v4
268+ with :
269+ path : |
270+ ~/.cargo/bin/
271+ ~/.cargo/registry/index/
272+ ~/.cargo/registry/cache/
273+ ~/.cargo/git/db/
274+ key : cargo-home-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ hashFiles('**/Cargo.lock') }}-${{ hashFiles('codex-rs/rust-toolchain.toml') }}
275+
276+ - name : Save sccache cache (fallback)
277+ if : always() && !cancelled() && env.SCCACHE_GHA_ENABLED != 'true'
278+ continue-on-error : true
279+ uses : actions/cache/save@v4
280+ with :
281+ path : ${{ github.workspace }}/.sccache/
282+ key : sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ hashFiles('**/Cargo.lock') }}-${{ github.run_id }}
283+
284+ - name : sccache stats
285+ if : always()
286+ continue-on-error : true
287+ run : sccache --show-stats || true
288+
289+ - name : sccache summary
290+ if : always()
291+ shell : bash
292+ run : |
293+ {
294+ echo "### sccache stats — ${{ matrix.target }} (${{ matrix.profile }})";
295+ echo;
296+ echo '```';
297+ sccache --show-stats || true;
298+ echo '```';
299+ } >> "$GITHUB_STEP_SUMMARY"
300+
301+ - name : Save APT cache (musl)
302+ if : always() && !cancelled() && (matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl') && steps.cache_apt_restore.outputs.cache-hit != 'true'
303+ continue-on-error : true
304+ uses : actions/cache/save@v4
305+ with :
306+ path : |
307+ /var/cache/apt
308+ key : apt-${{ matrix.runner }}-${{ matrix.target }}-v1
309+
310+ # Fail the job if any of the previous steps failed.
311+ - name : verify all steps passed
312+ if : |
313+ steps.clippy.outcome == 'failure' ||
314+ steps.cargo_check_all_crates.outcome == 'failure'
315+ run : |
316+ echo "One or more checks failed (clippy or cargo_check_all_crates). See logs for details."
317+ exit 1
318+
319+ tests :
320+ name : Tests — ${{ matrix.runner }} - ${{ matrix.target }}
321+ runs-on : ${{ matrix.runner }}
322+ timeout-minutes : 30
323+ needs : changed
324+ if : ${{ needs.changed.outputs.codex == 'true' || needs.changed.outputs.workflows == 'true' || github.event_name == 'push' }}
325+ defaults :
326+ run :
327+ working-directory : codex-rs
328+ env :
329+ RUSTC_WRAPPER : sccache
330+ CARGO_INCREMENTAL : " 0"
331+ SCCACHE_CACHE_SIZE : 10G
332+
333+ strategy :
334+ fail-fast : false
335+ matrix :
336+ include :
337+ - runner : macos-14
338+ target : aarch64-apple-darwin
339+ profile : dev
340+ - runner : ubuntu-24.04
341+ target : x86_64-unknown-linux-gnu
342+ profile : dev
343+ - runner : ubuntu-24.04-arm
344+ target : aarch64-unknown-linux-gnu
345+ profile : dev
346+ - runner : windows-latest
347+ target : x86_64-pc-windows-msvc
348+ profile : dev
349+ - runner : windows-11-arm
350+ target : aarch64-pc-windows-msvc
351+ profile : dev
352+
353+ steps :
354+ - uses : actions/checkout@v5
355+ 356+ with :
357+ targets : ${{ matrix.target }}
358+
359+ - name : Restore cargo home cache
360+ id : cache_cargo_home_restore
361+ uses : actions/cache/restore@v4
362+ with :
363+ path : |
364+ ~/.cargo/bin/
365+ ~/.cargo/registry/index/
366+ ~/.cargo/registry/cache/
367+ ~/.cargo/git/db/
368+ key : cargo-home-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ hashFiles('**/Cargo.lock') }}-${{ hashFiles('codex-rs/rust-toolchain.toml') }}
369+ restore-keys : |
370+ cargo-home-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-
371+
372+ - name : Install sccache
373+ uses : taiki-e/install-action@0c5db7f7f897c03b771660e91d065338615679f4 # v2
374+ with :
375+ tool : sccache
376+ version : 0.7.5
377+
378+ - name : Configure sccache backend
379+ shell : bash
380+ run : |
381+ set -euo pipefail
382+ if [[ -n "${ACTIONS_CACHE_URL:-}" && -n "${ACTIONS_RUNTIME_TOKEN:-}" ]]; then
383+ echo "SCCACHE_GHA_ENABLED=true" >> "$GITHUB_ENV"
384+ echo "Using sccache GitHub backend"
385+ else
386+ echo "SCCACHE_GHA_ENABLED=false" >> "$GITHUB_ENV"
387+ echo "SCCACHE_DIR=${{ github.workspace }}/.sccache" >> "$GITHUB_ENV"
388+ echo "Using sccache local disk + actions/cache fallback"
389+ fi
390+
391+ - name : Restore sccache cache (fallback)
392+ if : ${{ env.SCCACHE_GHA_ENABLED != 'true' }}
393+ id : cache_sccache_restore
394+ uses : actions/cache/restore@v4
395+ with :
396+ path : ${{ github.workspace }}/.sccache/
397+ key : sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ hashFiles('**/Cargo.lock') }}-${{ github.run_id }}
398+ restore-keys : |
399+ sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ hashFiles('**/Cargo.lock') }}-
400+ sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-
401+
194402 - uses : taiki-e/install-action@0c5db7f7f897c03b771660e91d065338615679f4 # v2
195403 with :
196404 tool : nextest
197405 version : 0.9.103
198406
199407 - name : tests
200408 id : test
201- # Tests take too long for release builds to run them on every PR.
202- if : ${{ matrix.profile != 'release' }}
203409 continue-on-error : true
204410 run : cargo nextest run --all-features --no-fail-fast --target ${{ matrix.target }} --cargo-profile ci-test
205411 env :
206412 RUST_BACKTRACE : 1
207413
208- # Save caches explicitly; make non-fatal so cache packaging
209- # never fails the overall job. Only save when key wasn't hit.
210414 - name : Save cargo home cache
211415 if : always() && !cancelled() && steps.cache_cargo_home_restore.outputs.cache-hit != 'true'
212416 continue-on-error : true
@@ -217,33 +421,43 @@ jobs:
217421 ~/.cargo/registry/index/
218422 ~/.cargo/registry/cache/
219423 ~/.cargo/git/db/
220- key : cargo-home-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ hashFiles('**/Cargo.lock') }}
424+ key : cargo-home-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ hashFiles('**/Cargo.lock') }}-${{ hashFiles('codex-rs/rust-toolchain.toml') }}
221425
222- - name : Save target cache (except gnu-dev)
223- if : >-
224- always() && !cancelled() &&
225- (steps.cache_target_restore.outputs.cache-hit != 'true') &&
226- !(matrix.target == 'x86_64-unknown-linux-gnu' && matrix.profile != 'release')
426+ - name : Save sccache cache (fallback)
427+ if : always() && !cancelled() && env.SCCACHE_GHA_ENABLED != 'true'
227428 continue-on-error : true
228429 uses : actions/cache/save@v4
229430 with :
230- path : ${{ github.workspace }}/codex-rs/target /
231- key : cargo-target- ${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ hashFiles('**/Cargo.lock') }}
431+ path : ${{ github.workspace }}/.sccache /
432+ key : sccache- ${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ hashFiles('**/Cargo.lock') }}-${{ github.run_id }}
232433
233- # Fail the job if any of the previous steps failed.
234- - name : verify all steps passed
235- if : |
236- steps.clippy.outcome == 'failure' ||
237- steps.cargo_check_all_crates.outcome == 'failure' ||
238- steps.test.outcome == 'failure'
434+ - name : sccache stats
435+ if : always()
436+ continue-on-error : true
437+ run : sccache --show-stats || true
438+
439+ - name : sccache summary
440+ if : always()
441+ shell : bash
239442 run : |
240- echo "One or more checks failed (clippy, cargo_check_all_crates, or test). See logs for details."
443+ {
444+ echo "### sccache stats — ${{ matrix.target }} (tests)";
445+ echo;
446+ echo '```';
447+ sccache --show-stats || true;
448+ echo '```';
449+ } >> "$GITHUB_STEP_SUMMARY"
450+
451+ - name : verify tests passed
452+ if : steps.test.outcome == 'failure'
453+ run : |
454+ echo "Tests failed. See logs for details."
241455 exit 1
242456
243457 # --- Gatherer job that you mark as the ONLY required status -----------------
244458 results :
245459 name : CI results (required)
246- needs : [changed, general, cargo_shear, lint_build_test ]
460+ needs : [changed, general, cargo_shear, lint_build, tests ]
247461 if : always()
248462 runs-on : ubuntu-24.04
249463 steps :
@@ -252,7 +466,8 @@ jobs:
252466 run : |
253467 echo "general: ${{ needs.general.result }}"
254468 echo "shear : ${{ needs.cargo_shear.result }}"
255- echo "matrix : ${{ needs.lint_build_test.result }}"
469+ echo "lint : ${{ needs.lint_build.result }}"
470+ echo "tests : ${{ needs.tests.result }}"
256471
257472 # If nothing relevant changed (PR touching only root README, etc.),
258473 # declare success regardless of other jobs.
@@ -264,4 +479,10 @@ jobs:
264479 # Otherwise require the jobs to have succeeded
265480 [[ '${{ needs.general.result }}' == 'success' ]] || { echo 'general failed'; exit 1; }
266481 [[ '${{ needs.cargo_shear.result }}' == 'success' ]] || { echo 'cargo_shear failed'; exit 1; }
267- [[ '${{ needs.lint_build_test.result }}' == 'success' ]] || { echo 'matrix failed'; exit 1; }
482+ [[ '${{ needs.lint_build.result }}' == 'success' ]] || { echo 'lint_build failed'; exit 1; }
483+ [[ '${{ needs.tests.result }}' == 'success' ]] || { echo 'tests failed'; exit 1; }
484+
485+ - name : sccache summary note
486+ if : always()
487+ run : |
488+ echo "Per-job sccache stats are attached to each matrix job's Step Summary."
0 commit comments