fix(ci): preserve complete Rust caches across main and fork builds

This commit is contained in:
t8y2
2026-10-08 14:13:16 +08:00
parent f84137cdd9
commit ba6ca64e5d
5 changed files with 194 additions and 80 deletions
+24
View File
@@ -86,6 +86,30 @@ and Java rather than Docker; those matrix entries explicitly retain Java 21.
| Cassandra | 3.11.19, 5.0.6 |
| RabbitMQ | 3.13, 4.3 |
## Rust caches and build timings
Linux package, clippy, Rust test and native Agent jobs use the same pinned sccache
compiler wrappers on main and fork PRs. Main uses the existing S3 backend; jobs
without repository secrets use sccache's local disk backend. Only backend settings
are conditional: changing `CC` or `CXX` invalidates native build-script fingerprints
even if a target archive was restored. The cache key retains the real compiler
environment; only the CI selection variables are excluded. Full/fast features and
test-group selection remain unchanged and can still require additional builds.
All Rust target caches use the `v1-rust-complete` namespace and save only after a
successful job, from main. This bypasses old partial snapshots without deleting
caches or changing the S3 namespace. A cancelled or failed first build must not
publish a shared snapshot: rust-cache does not update an exact cache hit, so later
successful builds would otherwise keep restoring the unfinished snapshot.
The first successful main run must populate the new namespace before fork PRs can
reuse it. Target caching is not a per-commit snapshot of workspace artifacts.
Clippy, nextest and native Agent nextest builds emit Cargo HTML timing reports.
Their `DBX-*-cargo-timings` artifacts are retained for three days, including after
failures when a report exists, but uploads do not delay cancelled runs. Inspect
these reports alongside sccache statistics: its hit rate excludes unsupported
crate types and does not measure the time spent compiling and linking test binaries.
## Validation
Run these from the repository root:
+5 -2
View File
@@ -277,8 +277,11 @@ test("nextest, doctests and coverage select identical packages and features in e
const nextest = rustCommand("test", group, mode);
const doctest = rustCommand("doctest", group, mode);
assert.deepEqual(nextest.slice(0, 3), ["nextest", "run", "--no-fail-fast"]);
assert.deepEqual(doctest, ["test", "--doc", ...nextest.slice(3)]);
assert.deepEqual(rustCommand("tree", group, mode), ["tree", ...nextest.slice(3)]);
const selection = nextest.slice(3).filter((argument) => argument !== "--timings");
assert.deepEqual(doctest, ["test", "--doc", ...selection]);
assert.deepEqual(rustCommand("tree", group, mode), ["tree", ...selection]);
assert.ok(nextest.includes("--timings"));
assert.ok(rustCommand("clippy", "workspace", mode).includes("--timings"));
assert.ok(nextest.includes("--no-default-features"));
assert.ok(nextest.includes("--locked"));
}
+1 -1
View File
@@ -22,7 +22,7 @@ export function rustCommand(action, group, mode) {
] : appFeatures;
const packages = group === "workspace" ? ["--workspace"] : rustGroups[group].flatMap((name) => ["--package", name]);
const command = action === "test" ? ["nextest", "run", "--no-fail-fast"] : action === "doctest" ? ["test", "--doc"] : [action];
return [...command, ...packages, "--locked", ...(action === "clippy" ? ["--all-targets"] : []),
return [...command, ...packages, "--locked", ...(["test", "clippy"].includes(action) ? ["--timings"] : []), ...(action === "clippy" ? ["--all-targets"] : []),
"--no-default-features", "--features", features.join(","), ...(action === "clippy" ? ["--", "-D", "warnings"] : [])];
}
+84 -7
View File
@@ -1,5 +1,8 @@
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { spawnSync } from "node:child_process";
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import test from "node:test";
const workflow = readFileSync(new URL("../workflows/ci.yml", import.meta.url), "utf8");
@@ -83,19 +86,93 @@ test("every old Agent stage has an independent owner and Java packaging remains
for (const name of ["agent-rust", "agent-go", "agent-integration", "agent-java"]) assert.doesNotMatch(job(name), /continue-on-error: true/);
});
test("native Rust driver caches exclude failed build artifacts", () => {
const content = job("agent-rust");
assert.ok(content.includes("shared-key: ci-agent-rust-v2-${{ matrix.driver }}"));
assert.ok(content.includes("cache-on-failure: false"));
test("shared Rust caches publish only complete builds outside the old cache namespace", () => {
for (const name of ["packages", "rust-fmt-clippy", "rust-test", "agent-rust", "agent-integration"]) {
const content = job(name);
assert.ok(content.includes("prefix-key: v1-rust-complete"), name);
assert.ok(content.includes("cache-on-failure: false"), name);
assert.doesNotMatch(content, /cache-on-failure: true/);
assert.ok(content.includes("save-if: ${{ github.ref == 'refs/heads/main'"), name);
}
});
test("main and fork Rust jobs use the same rust-cache fingerprint", () => {
const stableCacheEnvironment = /- name: Rust cache\s+env:\s+RUSTC_WRAPPER: ""\s+RUST_FEATURE_MODE: ""\s+RUST_TEST_GROUP: ""\s+CC: ""\s+CXX: ""\s+uses: swatinem\/rust-cache@v2/;
const stableCacheEnvironment = /- name: Rust cache\s+env:\s+RUST_FEATURE_MODE: ""\s+RUST_TEST_GROUP: ""\s+uses: swatinem\/rust-cache@v2/;
for (const name of ["packages", "rust-fmt-clippy", "rust-test", "agent-rust"]) {
assert.match(job(name), stableCacheEnvironment);
const content = job(name);
assert.match(content, stableCacheEnvironment);
assert.match(content, /^ RUSTC_WRAPPER: sccache$/m);
assert.ok(content.includes('version: "v0.16.0"'));
assert.doesNotMatch(content, /RUSTC_WRAPPER: ""|CC: ""|CXX: ""/);
}
});
test("S3 and secretless Rust jobs export identical compiler wrappers", (context) => {
const directory = mkdtempSync(path.join(tmpdir(), "dbx-ci-sccache-"));
context.after(() => rmSync(directory, { recursive: true, force: true }));
const compiler = "/opt/hostedtoolcache/sccache/0.16.0/x64/sccache";
const backend = {
SCCACHE_BUCKET: "test-bucket",
SCCACHE_ENDPOINT: "https://cache.example.test",
SCCACHE_REGION: "test-region",
SCCACHE_S3_KEY_PREFIX: "test-prefix",
SCCACHE_S3_USE_SSL: "true",
AWS_ACCESS_KEY_ID: "test-access-key",
AWS_SECRET_ACCESS_KEY: "test-secret-key",
};
for (const name of ["packages", "rust-fmt-clippy", "rust-test", "agent-rust"]) {
const setup = job(name).match(/- name: Configure sccache\n([\s\S]*?)(?=\n - name: Rust cache)/)?.[1];
assert.ok(setup, name);
assert.doesNotMatch(setup, /^\s+if:/m);
const script = setup.match(/ run: \|\n([\s\S]*)/)[1].split("\n").map((line) => line.slice(10)).join("\n");
for (const remote of [true, false]) {
const output = path.join(directory, `${name}-${remote}.env`);
const result = spawnSync("bash", ["-e", "-o", "pipefail", "-c", script], {
encoding: "utf8",
env: {
PATH: process.env.PATH,
GITHUB_ENV: output,
SCCACHE_PATH: compiler,
CACHE_BUCKET: remote ? backend.SCCACHE_BUCKET : "",
CACHE_ENDPOINT: remote ? backend.SCCACHE_ENDPOINT : "",
CACHE_REGION: remote ? backend.SCCACHE_REGION : "",
CACHE_KEY_PREFIX: remote ? backend.SCCACHE_S3_KEY_PREFIX : "",
CACHE_ACCESS_KEY_ID: remote ? backend.AWS_ACCESS_KEY_ID : "",
CACHE_SECRET_ACCESS_KEY: remote ? backend.AWS_SECRET_ACCESS_KEY : "",
},
});
assert.equal(result.status, 0, result.stderr);
assert.equal(result.stdout, "");
const exported = Object.fromEntries(readFileSync(output, "utf8").trim().split("\n").map((line) => {
const separator = line.indexOf("=");
return [line.slice(0, separator), line.slice(separator + 1)];
}));
assert.deepEqual(exported, {
...(remote ? backend : {}),
SCCACHE_IDLE_TIMEOUT: "0",
CC: `${compiler} cc`,
CXX: `${compiler} c++`,
}, `${name}: ${remote ? "S3" : "local"}`);
}
}
});
test("Rust build timings remain available after failures without waiting for cancelled runs", () => {
for (const [name, artifact, location] of [
["rust-fmt-clippy", "DBX-clippy-cargo-timings", "target/cargo-timings/"],
["rust-test", "DBX-rust-${{ matrix.group }}-cargo-timings", "target/cargo-timings/"],
["agent-rust", "DBX-agent-${{ matrix.driver }}-cargo-timings", "agents/drivers/${{ matrix.driver }}/target/cargo-timings/"],
]) {
const content = job(name);
assert.match(content, /name: Upload Rust Cargo timings\s+if: always\(\) && !cancelled\(\)\s+uses: actions\/upload-artifact@v6/);
assert.ok(content.includes(`name: ${artifact}`));
assert.ok(content.includes(`path: ${location}`));
assert.ok(content.includes("retention-days: 3"));
assert.ok(content.includes("if-no-files-found: ignore"));
}
assert.ok(job("agent-rust").includes('--manifest-path "drivers/$DRIVER/Cargo.toml" --locked --no-fail-fast --timings'));
});
test("Linux Rust dependency installs bound apt mirror stalls", () => {
for (const name of ["packages", "rust-fmt-clippy", "rust-test", "agent-rust"]) {
const content = job(name);
+80 -70
View File
@@ -171,9 +171,7 @@ jobs:
NPM_CONFIG_LOGLEVEL: error
# sccache cannot reuse Cargo incremental artifacts, so avoid generating them in CI.
CARGO_INCREMENTAL: "0"
# Fork PRs cannot read repository secrets, so they build without sccache
# (see rust-fmt-clippy) and lean on the rust-cache restore from main.
RUSTC_WRAPPER: ${{ secrets.SCCACHE_S3_BUCKET != '' && 'sccache' || '' }}
RUSTC_WRAPPER: sccache
steps:
- uses: actions/checkout@v7
@@ -228,8 +226,7 @@ jobs:
with:
version: "v0.16.0"
- name: Configure S3 sccache
if: env.RUSTC_WRAPPER == 'sccache'
- name: Configure sccache
shell: bash
env:
CACHE_BUCKET: ${{ secrets.SCCACHE_S3_BUCKET }}
@@ -240,13 +237,15 @@ jobs:
CACHE_SECRET_ACCESS_KEY: ${{ secrets.SCCACHE_S3_SECRET_ACCESS_KEY }}
run: |
{
echo "SCCACHE_BUCKET=${CACHE_BUCKET}"
echo "SCCACHE_ENDPOINT=${CACHE_ENDPOINT}"
echo "SCCACHE_REGION=${CACHE_REGION}"
echo "SCCACHE_S3_KEY_PREFIX=${CACHE_KEY_PREFIX}"
echo "SCCACHE_S3_USE_SSL=true"
echo "AWS_ACCESS_KEY_ID=${CACHE_ACCESS_KEY_ID}"
echo "AWS_SECRET_ACCESS_KEY=${CACHE_SECRET_ACCESS_KEY}"
if [[ -n "$CACHE_BUCKET" ]]; then
echo "SCCACHE_BUCKET=${CACHE_BUCKET}"
echo "SCCACHE_ENDPOINT=${CACHE_ENDPOINT}"
echo "SCCACHE_REGION=${CACHE_REGION}"
echo "SCCACHE_S3_KEY_PREFIX=${CACHE_KEY_PREFIX}"
echo "SCCACHE_S3_USE_SSL=true"
echo "AWS_ACCESS_KEY_ID=${CACHE_ACCESS_KEY_ID}"
echo "AWS_SECRET_ACCESS_KEY=${CACHE_SECRET_ACCESS_KEY}"
fi
# Keep the server alive through post-compile test/lint phases so
# "Show sccache stats" reflects the real counters.
echo "SCCACHE_IDLE_TIMEOUT=0"
@@ -258,20 +257,17 @@ jobs:
- name: Rust cache
env:
RUSTC_WRAPPER: ""
RUST_FEATURE_MODE: ""
RUST_TEST_GROUP: ""
CC: ""
CXX: ""
uses: swatinem/rust-cache@v2
with:
prefix-key: v1-rust-complete
workspaces: "./ -> target"
shared-key: ci-packages-x86_64-unknown-linux-gnu
# Release-linking (LTO) dominates this job and sccache cannot cache
# those crate types.
cache-workspace-crates: true
# Preserve completed dependency builds when a later test step fails.
cache-on-failure: true
cache-on-failure: false
# PR caches are large and branch-scoped; restore them from main without saving per-PR copies.
save-if: ${{ github.ref == 'refs/heads/main' }}
@@ -766,10 +762,7 @@ jobs:
env:
# sccache cannot reuse Cargo incremental artifacts, so avoid generating them in CI.
CARGO_INCREMENTAL: "0"
# Fork PRs cannot read repository secrets, and the GHA sccache backend can
# never hold entries for this repo because main only populates S3, so fork
# builds run without sccache and lean on the rust-cache restore from main.
RUSTC_WRAPPER: ${{ secrets.SCCACHE_S3_BUCKET != '' && 'sccache' || '' }}
RUSTC_WRAPPER: sccache
# The fast lane skips only system font discovery while retaining the other default capabilities.
RUST_FEATURE_MODE: ${{ github.event_name == 'pull_request' && needs.changes.outputs.rust_full != 'true' && 'fast' || 'full' }}
steps:
@@ -798,8 +791,7 @@ jobs:
with:
version: "v0.16.0"
- name: Configure S3 sccache
if: env.RUSTC_WRAPPER == 'sccache'
- name: Configure sccache
shell: bash
env:
CACHE_BUCKET: ${{ secrets.SCCACHE_S3_BUCKET }}
@@ -810,13 +802,15 @@ jobs:
CACHE_SECRET_ACCESS_KEY: ${{ secrets.SCCACHE_S3_SECRET_ACCESS_KEY }}
run: |
{
echo "SCCACHE_BUCKET=${CACHE_BUCKET}"
echo "SCCACHE_ENDPOINT=${CACHE_ENDPOINT}"
echo "SCCACHE_REGION=${CACHE_REGION}"
echo "SCCACHE_S3_KEY_PREFIX=${CACHE_KEY_PREFIX}"
echo "SCCACHE_S3_USE_SSL=true"
echo "AWS_ACCESS_KEY_ID=${CACHE_ACCESS_KEY_ID}"
echo "AWS_SECRET_ACCESS_KEY=${CACHE_SECRET_ACCESS_KEY}"
if [[ -n "$CACHE_BUCKET" ]]; then
echo "SCCACHE_BUCKET=${CACHE_BUCKET}"
echo "SCCACHE_ENDPOINT=${CACHE_ENDPOINT}"
echo "SCCACHE_REGION=${CACHE_REGION}"
echo "SCCACHE_S3_KEY_PREFIX=${CACHE_KEY_PREFIX}"
echo "SCCACHE_S3_USE_SSL=true"
echo "AWS_ACCESS_KEY_ID=${CACHE_ACCESS_KEY_ID}"
echo "AWS_SECRET_ACCESS_KEY=${CACHE_SECRET_ACCESS_KEY}"
fi
# Keep the server alive through post-compile test/lint phases so
# "Show sccache stats" reflects the real counters.
echo "SCCACHE_IDLE_TIMEOUT=0"
@@ -828,17 +822,14 @@ jobs:
- name: Rust cache
env:
RUSTC_WRAPPER: ""
RUST_FEATURE_MODE: ""
RUST_TEST_GROUP: ""
CC: ""
CXX: ""
uses: swatinem/rust-cache@v2
with:
prefix-key: v1-rust-complete
workspaces: "./ -> target"
shared-key: ci-rust-fmt-clippy-x86_64-unknown-linux-gnu
# Preserve completed dependency builds when a later lint step fails.
cache-on-failure: true
cache-on-failure: false
# PR caches are large and branch-scoped; restore them from main without saving per-PR copies.
save-if: ${{ github.ref == 'refs/heads/main' }}
@@ -846,6 +837,15 @@ jobs:
run: |-
node .github/scripts/ci-rust.mjs clippy workspace "$RUST_FEATURE_MODE"
- name: Upload Rust Cargo timings
if: always() && !cancelled()
uses: actions/upload-artifact@v6
with:
name: DBX-clippy-cargo-timings
path: target/cargo-timings/
if-no-files-found: ignore
retention-days: 3
- name: Show sccache stats
if: always()
continue-on-error: true
@@ -862,10 +862,7 @@ jobs:
CARGO_INCREMENTAL: "0"
# Deep async export tests exceed the Rust test harness's default thread stack on Linux.
RUST_MIN_STACK: 8388608
# Fork PRs cannot read repository secrets, and the GHA sccache backend can
# never hold entries for this repo because main only populates S3, so fork
# builds run without sccache and lean on the rust-cache restore from main.
RUSTC_WRAPPER: ${{ secrets.SCCACHE_S3_BUCKET != '' && 'sccache' || '' }}
RUSTC_WRAPPER: sccache
# The fast lane skips only system font discovery while retaining the other default capabilities.
RUST_FEATURE_MODE: ${{ github.event_name == 'pull_request' && needs.changes.outputs.rust_full != 'true' && 'fast' || 'full' }}
RUST_TEST_GROUP: ${{ matrix.group }}
@@ -902,8 +899,7 @@ jobs:
with:
version: "v0.16.0"
- name: Configure S3 sccache
if: env.RUSTC_WRAPPER == 'sccache'
- name: Configure sccache
shell: bash
env:
CACHE_BUCKET: ${{ secrets.SCCACHE_S3_BUCKET }}
@@ -914,13 +910,15 @@ jobs:
CACHE_SECRET_ACCESS_KEY: ${{ secrets.SCCACHE_S3_SECRET_ACCESS_KEY }}
run: |
{
echo "SCCACHE_BUCKET=${CACHE_BUCKET}"
echo "SCCACHE_ENDPOINT=${CACHE_ENDPOINT}"
echo "SCCACHE_REGION=${CACHE_REGION}"
echo "SCCACHE_S3_KEY_PREFIX=${CACHE_KEY_PREFIX}"
echo "SCCACHE_S3_USE_SSL=true"
echo "AWS_ACCESS_KEY_ID=${CACHE_ACCESS_KEY_ID}"
echo "AWS_SECRET_ACCESS_KEY=${CACHE_SECRET_ACCESS_KEY}"
if [[ -n "$CACHE_BUCKET" ]]; then
echo "SCCACHE_BUCKET=${CACHE_BUCKET}"
echo "SCCACHE_ENDPOINT=${CACHE_ENDPOINT}"
echo "SCCACHE_REGION=${CACHE_REGION}"
echo "SCCACHE_S3_KEY_PREFIX=${CACHE_KEY_PREFIX}"
echo "SCCACHE_S3_USE_SSL=true"
echo "AWS_ACCESS_KEY_ID=${CACHE_ACCESS_KEY_ID}"
echo "AWS_SECRET_ACCESS_KEY=${CACHE_SECRET_ACCESS_KEY}"
fi
# Keep the server alive through post-compile test/lint phases so
# "Show sccache stats" reflects the real counters.
echo "SCCACHE_IDLE_TIMEOUT=0"
@@ -932,19 +930,16 @@ jobs:
- name: Rust cache
env:
RUSTC_WRAPPER: ""
RUST_FEATURE_MODE: ""
RUST_TEST_GROUP: ""
CC: ""
CXX: ""
uses: swatinem/rust-cache@v2
with:
prefix-key: v1-rust-complete
workspaces: "./ -> target"
shared-key: ci-rust-test-v2-x86_64-unknown-linux-gnu
# Test linking dominates this job and sccache cannot cache those crate types.
cache-workspace-crates: true
# Preserve completed dependency builds when a later test step fails.
cache-on-failure: true
cache-on-failure: false
# PR caches are large and branch-scoped; restore them from main without saving per-PR copies.
save-if: ${{ github.ref == 'refs/heads/main' }}
@@ -963,6 +958,15 @@ jobs:
run: |-
mold -run node .github/scripts/ci-rust.mjs doctest "$RUST_TEST_GROUP" "$RUST_FEATURE_MODE"
- name: Upload Rust Cargo timings
if: always() && !cancelled()
uses: actions/upload-artifact@v6
with:
name: DBX-rust-${{ matrix.group }}-cargo-timings
path: target/cargo-timings/
if-no-files-found: ignore
retention-days: 3
- name: Show sccache stats
if: always()
continue-on-error: true
@@ -1361,9 +1365,7 @@ jobs:
env:
# sccache cannot reuse Cargo incremental artifacts, so avoid generating them in CI.
CARGO_INCREMENTAL: "0"
# Fork PRs cannot read repository secrets, so they build without sccache
# (see rust-fmt-clippy) and lean on the rust-cache restore from main.
RUSTC_WRAPPER: ${{ secrets.SCCACHE_S3_BUCKET != '' && 'sccache' || '' }}
RUSTC_WRAPPER: sccache
defaults:
run:
working-directory: agents
@@ -1395,8 +1397,7 @@ jobs:
uses: mozilla-actions/sccache-action@fc920bf0ec8de6ee65d409111f7ec508035751ba # v0.0.11
with:
version: "v0.16.0"
- name: Configure S3 sccache
if: env.RUSTC_WRAPPER == 'sccache'
- name: Configure sccache
shell: bash
env:
CACHE_BUCKET: ${{ secrets.SCCACHE_S3_BUCKET }}
@@ -1407,13 +1408,15 @@ jobs:
CACHE_SECRET_ACCESS_KEY: ${{ secrets.SCCACHE_S3_SECRET_ACCESS_KEY }}
run: |
{
echo "SCCACHE_BUCKET=${CACHE_BUCKET}"
echo "SCCACHE_ENDPOINT=${CACHE_ENDPOINT}"
echo "SCCACHE_REGION=${CACHE_REGION}"
echo "SCCACHE_S3_KEY_PREFIX=${CACHE_KEY_PREFIX}"
echo "SCCACHE_S3_USE_SSL=true"
echo "AWS_ACCESS_KEY_ID=${CACHE_ACCESS_KEY_ID}"
echo "AWS_SECRET_ACCESS_KEY=${CACHE_SECRET_ACCESS_KEY}"
if [[ -n "$CACHE_BUCKET" ]]; then
echo "SCCACHE_BUCKET=${CACHE_BUCKET}"
echo "SCCACHE_ENDPOINT=${CACHE_ENDPOINT}"
echo "SCCACHE_REGION=${CACHE_REGION}"
echo "SCCACHE_S3_KEY_PREFIX=${CACHE_KEY_PREFIX}"
echo "SCCACHE_S3_USE_SSL=true"
echo "AWS_ACCESS_KEY_ID=${CACHE_ACCESS_KEY_ID}"
echo "AWS_SECRET_ACCESS_KEY=${CACHE_SECRET_ACCESS_KEY}"
fi
# Keep the server alive through post-compile test/lint phases so
# "Show sccache stats" reflects the real counters.
echo "SCCACHE_IDLE_TIMEOUT=0"
@@ -1425,13 +1428,11 @@ jobs:
} >> "$GITHUB_ENV"
- name: Rust cache
env:
RUSTC_WRAPPER: ""
RUST_FEATURE_MODE: ""
RUST_TEST_GROUP: ""
CC: ""
CXX: ""
uses: swatinem/rust-cache@v2
with:
prefix-key: v1-rust-complete
workspaces: agents/drivers/${{ matrix.driver }} -> target
# A failed bundled native build can leave link-compatible but invalid artifacts.
shared-key: ci-agent-rust-v2-${{ matrix.driver }}
@@ -1447,11 +1448,19 @@ jobs:
env:
DRIVER: ${{ matrix.driver }}
run: |
mold -run cargo nextest run --manifest-path "drivers/$DRIVER/Cargo.toml" --locked --no-fail-fast
mold -run cargo nextest run --manifest-path "drivers/$DRIVER/Cargo.toml" --locked --no-fail-fast --timings
mold -run cargo test --doc --manifest-path "drivers/$DRIVER/Cargo.toml" --locked
- name: TDengine native agent build
if: matrix.driver == 'tdengine'
run: mold -run cargo build --manifest-path drivers/tdengine/Cargo.toml --locked --release --bin dbx-tdengine-driver
- name: Upload Rust Cargo timings
if: always() && !cancelled()
uses: actions/upload-artifact@v6
with:
name: DBX-agent-${{ matrix.driver }}-cargo-timings
path: agents/drivers/${{ matrix.driver }}/target/cargo-timings/
if-no-files-found: ignore
retention-days: 3
# Diagnostics only; agent jobs must not swallow build/test failures
# (ci-workflow.test.mjs), so keep this step best-effort at the command level.
- name: Show sccache stats
@@ -1518,8 +1527,9 @@ jobs:
if: matrix.driver == 'tdengine'
uses: swatinem/rust-cache@v2
with:
prefix-key: v1-rust-complete
workspaces: agents/drivers/tdengine -> target
cache-on-failure: true
cache-on-failure: false
save-if: ${{ github.ref == 'refs/heads/main' && matrix.version == '3.4.2.2' }}
- name: Run one live engine and version
env: