From f882711702b90ef101430abbe9387442f6694f3a Mon Sep 17 00:00:00 2001 From: Sanjevi Rau Date: Thu, 12 Nov 2026 16:59:49 +0800 Subject: [PATCH 1/2] ci: cache Rust dependencies, split the oracle replays and shell journeys Seven CI jobs compiled every dependency from nothing. They now restore the dependencies (Swatinem/rust-cache, pinned): one cache for the jobs that build the debug engine, saved by the journeys' engine job, and one for the Rust quality gate. The packages and release builds are untouched and still compile clean. The oracle corpus replays run as two jobs of about equal length (Functions with Cloud Tasks, Auth with Pub/Sub), and the shell journeys as two: the typing journey over the Firestore pages, over 4 of the project's 10 minutes, and the rest. Co-Authored-By: Claude Fable 5.2 Claude-Session: https://claude.ai/code/session_01APfZAFCQzCmvhJqWKMT47g --- .github/workflows/ci.yml | 61 +++++++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 29998612..e1f7cf8a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,6 +82,11 @@ jobs: rustup default stable rustup component add rustfmt clippy rustc --version + # Dependencies only (the cache drops this workspace's crates): the + # compile of the tree itself still runs in full. + - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3 + with: + shared-key: rust-gate - name: Check formatting run: cargo fmt --all -- --check - name: Deny Clippy warnings @@ -144,6 +149,11 @@ jobs: rustup update stable --no-self-update rustup default stable rustc --version + # The dependencies of the debug engine, shared by every job that builds + # it; this job is the one that saves them when Cargo.lock or Rust moves. + - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3 + with: + shared-key: engine-debug - name: Build the engine the browser journeys run against run: cargo build --locked --bin firenook - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 @@ -158,7 +168,8 @@ jobs: # runner it would not fit one job's budget. Each Playwright project (one # engine profile) ran as a job of its own; the six short ones (3-6 # minutes) now run in pairs, so the run asks for three fewer runners and - # waits less for them, and shell (about 10) stays alone. + # waits less for them. Shell (about 10) is two jobs: the typing journey + # over the Firestore pages, which alone is over 4 minutes, and the rest. name: Console journeys (${{ matrix.name }}) needs: journey-engine runs-on: ubuntu-latest @@ -170,7 +181,8 @@ jobs: - {name: data and storage, key: data-storage, projects: --project data --project storage} - {name: auth and messaging, key: auth-messaging, projects: --project auth --project messaging} - {name: compute and observe, key: compute-observe, projects: --project compute --project observe} - - {name: shell, key: shell, projects: --project shell} + - {name: 'shell, typing on Firestore', key: shell-typing-firestore, projects: '--project shell --grep "Firestore.*: every field keeps"'} + - {name: 'shell, the rest', key: shell, projects: '--project shell --grep-invert "Firestore.*: every field keeps"'} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 @@ -314,6 +326,10 @@ jobs: rustup update stable --no-self-update rustup default stable rustc --version + - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3 + with: + shared-key: engine-debug + save-if: false - name: Run the npm package's tests on Node ${{ matrix.node }} run: '"$FUNCTIONS_NODE" --test packaging/*.test.mjs' - name: Run the Functions runtime's tests with the workers on Node ${{ matrix.node }} @@ -449,6 +465,10 @@ jobs: rustup update stable --no-self-update rustup default stable rustc --version + - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3 + with: + shared-key: engine-debug + save-if: false - name: Install pinned harness dependencies run: npm ci --prefix conformance - name: Type-check harness @@ -595,16 +615,24 @@ jobs: # The Functions, Cloud Tasks, Auth and Pub/Sub oracle corpus replays # (about 9 minutes) beside the harness rather than in it, where they were # its longest steps: they compare recorded answers and start no Java. + # Two jobs of about equal length: Functions with Cloud Tasks, and Auth + # with Pub/Sub. oracle-replays: - name: Oracle corpus replays + name: Oracle corpus replays (${{ matrix.name }}) needs: changes if: needs.changes.outputs.code == 'true' runs-on: ubuntu-latest timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + include: + - {name: Functions and Cloud Tasks, key: functions} + - {name: Auth and Pub/Sub, key: auth-pubsub} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Note the recorded cases each replay compares - run: echo "FIRENOOK_CONFORMANCE_LEDGER=$RUNNER_TEMP/conformance-ledger/oracle-replays" >> "$GITHUB_ENV" + run: echo "FIRENOOK_CONFORMANCE_LEDGER=$RUNNER_TEMP/conformance-ledger/oracle-replays-${{ matrix.key }}" >> "$GITHUB_ENV" - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: 24.20.0 @@ -617,13 +645,20 @@ jobs: rustup update stable --no-self-update rustup default stable rustc --version + - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3 + with: + shared-key: engine-debug + save-if: false - name: Build the engine the replays run against run: cargo build --locked --bin firenook - name: Install pinned harness dependencies and the Functions peers run: | npm ci --prefix conformance - npm install --prefix "$RUNNER_TEMP/firenook-devtools" --ignore-scripts --no-audit --no-fund firebase-functions@7.2.5 firebase-admin@13.10.0 + if [ "${{ matrix.key }}" = functions ]; then + npm install --prefix "$RUNNER_TEMP/firenook-devtools" --ignore-scripts --no-audit --no-fund firebase-functions@7.2.5 firebase-admin@13.10.0 + fi - name: Replay the Functions runtime and Extensions oracle corpus + if: matrix.key == 'functions' env: FIREBASE_FUNCTIONS_7_2_ROOT: ${{ runner.temp }}/firenook-devtools/node_modules/firebase-functions FIRENOOK_OFFLINE: "1" @@ -633,6 +668,7 @@ jobs: --profiles main,v1-blocking,inspect,ext-missing-param \ --output "$RUNNER_TEMP/firenook-functions-runtime-replay.json" - name: Replay the Cloud Tasks oracle corpus against the suite + if: matrix.key == 'functions' env: FIREBASE_FUNCTIONS_7_2_ROOT: ${{ runner.temp }}/firenook-devtools/node_modules/firebase-functions FIRENOOK_OFFLINE: "1" @@ -643,16 +679,19 @@ jobs: --fixture fixtures/tasks-v1/emulator-programs.json \ --output "$RUNNER_TEMP/firenook-tasks-replay.json" - name: Replay the Auth oracle corpus against the standalone Auth service + if: matrix.key == 'auth-pubsub' run: | npm run replay:auth --prefix conformance -- \ --binary ../target/debug/firenook \ --output "$RUNNER_TEMP/firenook-auth-replay.json" - name: Replay the Pub/Sub oracle corpus over gRPC and HTTP/JSON + if: matrix.key == 'auth-pubsub' run: | npm run replay:pubsub --prefix conformance -- \ --binary ../target/debug/firenook \ --output "$RUNNER_TEMP/firenook-pubsub-replay.json" - name: Verify the pinned Pub/Sub client library against Firenook + if: matrix.key == 'auth-pubsub' run: | npm run verify:pubsub:client --prefix conformance -- \ --binary ../target/debug/firenook \ @@ -660,7 +699,7 @@ jobs: - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 if: always() with: - name: oracle-replays + name: oracle-replays-${{ matrix.key }} path: | ${{ runner.temp }}/firenook-functions-runtime-replay.json ${{ runner.temp }}/firenook-tasks-replay.json @@ -670,7 +709,7 @@ jobs: if-no-files-found: ignore - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 with: - name: conformance-ledger-oracle-replays + name: conformance-ledger-oracle-replays-${{ matrix.key }} path: ${{ runner.temp }}/conformance-ledger retention-days: 7 if-no-files-found: error @@ -699,6 +738,10 @@ jobs: rustup update stable --no-self-update rustup default stable rustc --version + - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3 + with: + shared-key: engine-debug + save-if: false - name: Install pinned harness dependencies run: npm ci --prefix conformance - name: Replay kindless queries and recursiveDelete in memory and disk/WAL @@ -793,6 +836,10 @@ jobs: rustup update stable --no-self-update rustup default stable rustc --version + - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3 + with: + shared-key: engine-debug + save-if: false - name: Install Firenook conformance dependencies run: npm ci --prefix conformance - name: Install pinned Firebase JS SDK dependencies From e89ecfde2b748b79a5babca75fdea0957ab92278 Mon Sep 17 00:00:00 2001 From: Sanjevi Rau Date: Thu, 12 Nov 2026 17:01:40 +0800 Subject: [PATCH 2/2] ci: cache with actions/cache, which the repository allows The repository runs GitHub-owned and verified actions only, so the run with Swatinem/rust-cache did not start. The same two caches through actions/cache: the registry and target, keyed on the Rust version and Cargo.lock; the other jobs restore without saving. Co-Authored-By: Claude Fable 5.2 Claude-Session: https://claude.ai/code/session_01APfZAFCQzCmvhJqWKMT47g --- .github/workflows/ci.yml | 91 ++++++++++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e1f7cf8a..0a24a263 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,6 +61,9 @@ jobs: rust: name: Rust quality gate + env: + # Incremental data is large and useless to the next checkout. + CARGO_INCREMENTAL: 0 needs: changes if: needs.changes.outputs.code == 'true' runs-on: ubuntu-latest @@ -82,11 +85,18 @@ jobs: rustup default stable rustup component add rustfmt clippy rustc --version - # Dependencies only (the cache drops this workspace's crates): the - # compile of the tree itself still runs in full. - - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3 + echo "RUSTC_VERSION=$(rustc --version | cut -d' ' -f2)" >> "$GITHUB_ENV" + # What the last run with this Cargo.lock and Rust compiled. Cargo + # rebuilds this tree's own crates (a fresh checkout is newer than + # them) and takes the dependencies as they are. + - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: - shared-key: rust-gate + path: | + ~/.cargo/registry/index + ~/.cargo/registry/cache + ~/.cargo/git/db + target + key: rust-gate-${{ runner.os }}-rust${{ env.RUSTC_VERSION }}-${{ hashFiles('Cargo.lock') }} - name: Check formatting run: cargo fmt --all -- --check - name: Deny Clippy warnings @@ -138,6 +148,9 @@ jobs: # checkout's path at run time, which every journey job's checkout # shares; each builds the console itself. name: The engine the journeys run against + env: + # Incremental data is large and useless to the next checkout. + CARGO_INCREMENTAL: 0 needs: changes if: needs.changes.outputs.code == 'true' runs-on: ubuntu-latest @@ -149,11 +162,18 @@ jobs: rustup update stable --no-self-update rustup default stable rustc --version - # The dependencies of the debug engine, shared by every job that builds - # it; this job is the one that saves them when Cargo.lock or Rust moves. - - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3 + echo "RUSTC_VERSION=$(rustc --version | cut -d' ' -f2)" >> "$GITHUB_ENV" + # The debug engine's compiled dependencies, restored by every job that + # builds it; this job is the one that saves them, when Cargo.lock or + # Rust moves. Cargo rebuilds this tree's own crates each time. + - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: - shared-key: engine-debug + path: | + ~/.cargo/registry/index + ~/.cargo/registry/cache + ~/.cargo/git/db + target + key: engine-debug-${{ runner.os }}-rust${{ env.RUSTC_VERSION }}-${{ hashFiles('Cargo.lock') }} - name: Build the engine the browser journeys run against run: cargo build --locked --bin firenook - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 @@ -326,10 +346,15 @@ jobs: rustup update stable --no-self-update rustup default stable rustc --version - - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3 + echo "RUSTC_VERSION=$(rustc --version | cut -d' ' -f2)" >> "$GITHUB_ENV" + - uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: - shared-key: engine-debug - save-if: false + path: | + ~/.cargo/registry/index + ~/.cargo/registry/cache + ~/.cargo/git/db + target + key: engine-debug-${{ runner.os }}-rust${{ env.RUSTC_VERSION }}-${{ hashFiles('Cargo.lock') }} - name: Run the npm package's tests on Node ${{ matrix.node }} run: '"$FUNCTIONS_NODE" --test packaging/*.test.mjs' - name: Run the Functions runtime's tests with the workers on Node ${{ matrix.node }} @@ -465,10 +490,15 @@ jobs: rustup update stable --no-self-update rustup default stable rustc --version - - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3 + echo "RUSTC_VERSION=$(rustc --version | cut -d' ' -f2)" >> "$GITHUB_ENV" + - uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: - shared-key: engine-debug - save-if: false + path: | + ~/.cargo/registry/index + ~/.cargo/registry/cache + ~/.cargo/git/db + target + key: engine-debug-${{ runner.os }}-rust${{ env.RUSTC_VERSION }}-${{ hashFiles('Cargo.lock') }} - name: Install pinned harness dependencies run: npm ci --prefix conformance - name: Type-check harness @@ -645,10 +675,15 @@ jobs: rustup update stable --no-self-update rustup default stable rustc --version - - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3 + echo "RUSTC_VERSION=$(rustc --version | cut -d' ' -f2)" >> "$GITHUB_ENV" + - uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: - shared-key: engine-debug - save-if: false + path: | + ~/.cargo/registry/index + ~/.cargo/registry/cache + ~/.cargo/git/db + target + key: engine-debug-${{ runner.os }}-rust${{ env.RUSTC_VERSION }}-${{ hashFiles('Cargo.lock') }} - name: Build the engine the replays run against run: cargo build --locked --bin firenook - name: Install pinned harness dependencies and the Functions peers @@ -738,10 +773,15 @@ jobs: rustup update stable --no-self-update rustup default stable rustc --version - - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3 + echo "RUSTC_VERSION=$(rustc --version | cut -d' ' -f2)" >> "$GITHUB_ENV" + - uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: - shared-key: engine-debug - save-if: false + path: | + ~/.cargo/registry/index + ~/.cargo/registry/cache + ~/.cargo/git/db + target + key: engine-debug-${{ runner.os }}-rust${{ env.RUSTC_VERSION }}-${{ hashFiles('Cargo.lock') }} - name: Install pinned harness dependencies run: npm ci --prefix conformance - name: Replay kindless queries and recursiveDelete in memory and disk/WAL @@ -836,10 +876,15 @@ jobs: rustup update stable --no-self-update rustup default stable rustc --version - - uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3 + echo "RUSTC_VERSION=$(rustc --version | cut -d' ' -f2)" >> "$GITHUB_ENV" + - uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: - shared-key: engine-debug - save-if: false + path: | + ~/.cargo/registry/index + ~/.cargo/registry/cache + ~/.cargo/git/db + target + key: engine-debug-${{ runner.os }}-rust${{ env.RUSTC_VERSION }}-${{ hashFiles('Cargo.lock') }} - name: Install Firenook conformance dependencies run: npm ci --prefix conformance - name: Install pinned Firebase JS SDK dependencies