Repository: denoland/deno
Pull request: ci: use file contents for test cache hash and separate build cache per test job

Previous PR (https://github.com/denoland/deno/pull/32214) was not exactly correct.

1. We need to store hash file contents instead of mtimes. It's about 2 seconds slower, but mtimes aren't reliable because the files are not necessarily covered by the mtime cache.
1. We need a separate build cache per test job because we're now going to potentially skip certain test jobs.

Tested on this PR to verify it works.

Changed files:
filename: .github/workflows/ci.generate.ts
patch: @@ -961,19 +961,14 @@ const buildJobs = buildItems.map((rawBuildItem) => {
         test_package: tc.package,
       })),
     });
+    const testCrateNameExpr = testMatrix.test_crate;
     const {
       restoreCacheStep,
       saveCacheStep,
     } = createCacheSteps({
       ...buildItem,
-      cachePrefix: "test-main",
+      cachePrefix: `test-${testCrateNameExpr}`,
     });
-    const testCrateNameExpr = testMatrix.test_crate;
-    // unit_node runs the fastest, so spend the time building
-    // the caches on that run
-    const shouldSaveCache = buildItem.save_cache.and(
-      testCrateNameExpr.equals("unit_node"),
-    );
     additionalJobs.push(job(
       jobIdForJob("test"),
       {
@@ -1034,28 +1029,13 @@ const buildJobs = buildItems.map((rawBuildItem) => {
             if: isRelease.and(testCrateNameExpr.equals("specs")),
             run: "cargo build --release -p test_ffi",
           },
-          {
-            name: "Build caches (debug)",
-            if: isDebug.and(shouldSaveCache),
-            run: `cargo test --no-run ${
-              testCrates.map((c) => `-p ${c.package}`).join(" ")
-            }`,
-            env: { CARGO_PROFILE_DEV_DEBUG: 0 },
-          },
           {
             name: "Test (debug)",
             if: isDebug,
             run:
               `cargo test -p ${testMatrix.test_package} --test ${testMatrix.test_crate}`,
             env: { CARGO_PROFILE_DEV_DEBUG: 0 },
           },
-          {
-            name: "Build caches (release)",
-            if: isRelease.and(shouldSaveCache),
-            run: `cargo test --no-run ${
-              testCrates.map((c) => `-p ${c.package}`).join(" ")
-            } --release`,
-          },
           {
             name: "Test (release)",
             if: isRelease.and(
@@ -1088,7 +1068,7 @@ const buildJobs = buildItems.map((rawBuildItem) => {
               path: `target/test_results_${testMatrix.test_crate}.json`,
             },
           }),
-          saveCacheStep.if(shouldSaveCache),
+          saveCacheStep.if(buildItem.save_cache),
         ),
       },
     ));

filename: .github/workflows/ci.yml
patch: @@ -404,7 +404,7 @@ jobs:
             ~/.cargo/registry/cache
             ~/.cargo/git/db
           key: never_saved
-          restore-keys: 96-cargo-home-macos-x86_64-test-main-
+          restore-keys: '96-cargo-home-macos-x86_64-test-${{ matrix.test_crate }}-'
       - name: Restore cache build output
         uses: cirruslabs/cache/restore@v4
         if: '!startsWith(github.ref, ''refs/tags/'') && github.ref != ''refs/heads/main'''
@@ -416,7 +416,7 @@ jobs:
             !./target/*/*.zip
             !./target/*/*.tar.gz
           key: never_saved
-          restore-keys: 96-cargo-target-macos-x86_64-debug-test-main-
+          restore-keys: '96-cargo-target-macos-x86_64-debug-test-${{ matrix.test_crate }}-'
       - name: Apply and update mtime cache
         uses: ./.github/mtime_cache
         if: '!startsWith(github.ref, ''refs/tags/'')'
@@ -470,11 +470,6 @@ jobs:
       - name: Build ffi (debug)
         if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''specs'''
         run: cargo build -p test_ffi
-      - name: Build caches (debug)
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'''
-        env:
-          CARGO_PROFILE_DEV_DEBUG: 0
-        run: cargo test --no-run -p integration_tests -p node_compat_tests -p specs_tests -p unit_tests -p unit_node_tests
       - name: Test (debug)
         if: '!startsWith(github.ref, ''refs/tags/'')'
         env:
@@ -491,7 +486,7 @@ jobs:
           path: 'target/test_results_${{ matrix.test_crate }}.json'
       - name: Cache cargo home
         uses: cirruslabs/cache/save@v4
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'' && github.ref == ''refs/heads/main'''
+        if: '!startsWith(github.ref, ''refs/tags/'') && github.ref == ''refs/heads/main'''
         with:
           path: |-
             ~/.cargo/.crates.toml
@@ -500,18 +495,18 @@ jobs:
             ~/.cargo/registry/index
             ~/.cargo/registry/cache
             ~/.cargo/git/db
-          key: '96-cargo-home-macos-x86_64-test-main-${{ github.sha }}'
+          key: '96-cargo-home-macos-x86_64-test-${{ matrix.test_crate }}-${{ github.sha }}'
       - name: Cache build output
         uses: cirruslabs/cache/save@v4
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'' && github.ref == ''refs/heads/main'''
+        if: '!startsWith(github.ref, ''refs/tags/'') && github.ref == ''refs/heads/main'''
         with:
           path: |-
             ./target
             !./target/*/gn_out
             !./target/*/gn_root
             !./target/*/*.zip
             !./target/*/*.tar.gz
-          key: '96-cargo-target-macos-x86_64-debug-test-main-${{ github.sha }}'
+          key: '96-cargo-target-macos-x86_64-debug-test-${{ matrix.test_crate }}-${{ github.sha }}'
   build-release-macos-x86_64:
     name: build release macos-x86_64
     needs:
@@ -801,7 +796,7 @@ jobs:
             ~/.cargo/registry/cache
             ~/.cargo/git/db
           key: never_saved
-          restore-keys: 96-cargo-home-macos-x86_64-test-main-
+          restore-keys: '96-cargo-home-macos-x86_64-test-${{ matrix.test_crate }}-'
       - name: Restore cache build output
         uses: cirruslabs/cache/restore@v4
         if: '!startsWith(github.ref, ''refs/tags/'') && !(!contains(github.event.pull_request.labels.*.name, ''ci-full'') && github.event_name == ''pull_request'') && github.ref != ''refs/heads/main'''
@@ -813,7 +808,7 @@ jobs:
             !./target/*/*.zip
             !./target/*/*.tar.gz
           key: never_saved
-          restore-keys: 96-cargo-target-macos-x86_64-release-test-main-
+          restore-keys: '96-cargo-target-macos-x86_64-release-test-${{ matrix.test_crate }}-'
       - name: Apply and update mtime cache
         uses: ./.github/mtime_cache
         if: '!startsWith(github.ref, ''refs/tags/'') && !(!contains(github.event.pull_request.labels.*.name, ''ci-full'') && github.event_name == ''pull_request'')'
@@ -1074,7 +1069,7 @@ jobs:
             ~/.cargo/registry/cache
             ~/.cargo/git/db
           key: never_saved
-          restore-keys: 96-cargo-home-macos-aarch64-test-main-
+          restore-keys: '96-cargo-home-macos-aarch64-test-${{ matrix.test_crate }}-'
       - name: Restore cache build output
         uses: cirruslabs/cache/restore@v4
         if: '!startsWith(github.ref, ''refs/tags/'') && github.ref != ''refs/heads/main'''
@@ -1086,7 +1081,7 @@ jobs:
             !./target/*/*.zip
             !./target/*/*.tar.gz
           key: never_saved
-          restore-keys: 96-cargo-target-macos-aarch64-debug-test-main-
+          restore-keys: '96-cargo-target-macos-aarch64-debug-test-${{ matrix.test_crate }}-'
       - name: Apply and update mtime cache
         uses: ./.github/mtime_cache
         if: '!startsWith(github.ref, ''refs/tags/'')'
@@ -1149,11 +1144,6 @@ jobs:
       - name: Build ffi (debug)
         if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''specs'''
         run: cargo build -p test_ffi
-      - name: Build caches (debug)
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'''
-        env:
-          CARGO_PROFILE_DEV_DEBUG: 0
-        run: cargo test --no-run -p integration_tests -p node_compat_tests -p specs_tests -p unit_tests -p unit_node_tests
       - name: Test (debug)
         if: '!startsWith(github.ref, ''refs/tags/'')'
         env:
@@ -1170,7 +1160,7 @@ jobs:
           path: 'target/test_results_${{ matrix.test_crate }}.json'
       - name: Cache cargo home
         uses: cirruslabs/cache/save@v4
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'' && github.ref == ''refs/heads/main'''
+        if: '!startsWith(github.ref, ''refs/tags/'') && github.ref == ''refs/heads/main'''
         with:
           path: |-
             ~/.cargo/.crates.toml
@@ -1179,18 +1169,18 @@ jobs:
             ~/.cargo/registry/index
             ~/.cargo/registry/cache
             ~/.cargo/git/db
-          key: '96-cargo-home-macos-aarch64-test-main-${{ github.sha }}'
+          key: '96-cargo-home-macos-aarch64-test-${{ matrix.test_crate }}-${{ github.sha }}'
       - name: Cache build output
         uses: cirruslabs/cache/save@v4
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'' && github.ref == ''refs/heads/main'''
+        if: '!startsWith(github.ref, ''refs/tags/'') && github.ref == ''refs/heads/main'''
         with:
           path: |-
             ./target
             !./target/*/gn_out
             !./target/*/gn_root
             !./target/*/*.zip
             !./target/*/*.tar.gz
-          key: '96-cargo-target-macos-aarch64-debug-test-main-${{ github.sha }}'
+          key: '96-cargo-target-macos-aarch64-debug-test-${{ matrix.test_crate }}-${{ github.sha }}'
   test-libs-debug-macos-aarch64:
     name: test libs debug macos-aarch64
     needs:
@@ -1603,7 +1593,7 @@ jobs:
             ~/.cargo/registry/cache
             ~/.cargo/git/db
           key: never_saved
-          restore-keys: 96-cargo-home-macos-aarch64-test-main-
+          restore-keys: '96-cargo-home-macos-aarch64-test-${{ matrix.test_crate }}-'
       - name: Restore cache build output
         uses: cirruslabs/cache/restore@v4
         if: '!startsWith(github.ref, ''refs/tags/'') && !(!contains(github.event.pull_request.labels.*.name, ''ci-full'') && github.event_name == ''pull_request'') && github.ref != ''refs/heads/main'''
@@ -1615,7 +1605,7 @@ jobs:
             !./target/*/*.zip
             !./target/*/*.tar.gz
           key: never_saved
-          restore-keys: 96-cargo-target-macos-aarch64-release-test-main-
+          restore-keys: '96-cargo-target-macos-aarch64-release-test-${{ matrix.test_crate }}-'
       - name: Apply and update mtime cache
         uses: ./.github/mtime_cache
         if: '!startsWith(github.ref, ''refs/tags/'') && !(!contains(github.event.pull_request.labels.*.name, ''ci-full'') && github.event_name == ''pull_request'')'
@@ -1868,7 +1858,7 @@ jobs:
             ~/.cargo/registry/cache
             ~/.cargo/git/db
           key: never_saved
-          restore-keys: 96-cargo-home-windows-x86_64-test-main-
+          restore-keys: '96-cargo-home-windows-x86_64-test-${{ matrix.test_crate }}-'
       - name: Restore cache build output
         uses: cirruslabs/cache/restore@v4
         if: '!startsWith(github.ref, ''refs/tags/'') && github.ref != ''refs/heads/main'''
@@ -1880,7 +1870,7 @@ jobs:
             !./target/*/*.zip
             !./target/*/*.tar.gz
           key: never_saved
-          restore-keys: 96-cargo-target-windows-x86_64-debug-test-main-
+          restore-keys: '96-cargo-target-windows-x86_64-debug-test-${{ matrix.test_crate }}-'
       - name: Apply and update mtime cache
         uses: ./.github/mtime_cache
         if: '!startsWith(github.ref, ''refs/tags/'')'
@@ -1925,11 +1915,6 @@ jobs:
       - name: Build ffi (debug)
         if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''specs'''
         run: cargo build -p test_ffi
-      - name: Build caches (debug)
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'''
-        env:
-          CARGO_PROFILE_DEV_DEBUG: 0
-        run: cargo test --no-run -p integration_tests -p node_compat_tests -p specs_tests -p unit_tests -p unit_node_tests
       - name: Test (debug)
         if: '!startsWith(github.ref, ''refs/tags/'')'
         env:
@@ -1946,7 +1931,7 @@ jobs:
           path: 'target/test_results_${{ matrix.test_crate }}.json'
       - name: Cache cargo home
         uses: cirruslabs/cache/save@v4
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'' && github.ref == ''refs/heads/main'''
+        if: '!startsWith(github.ref, ''refs/tags/'') && github.ref == ''refs/heads/main'''
         with:
           path: |-
             ~/.cargo/.crates.toml
@@ -1955,18 +1940,18 @@ jobs:
             ~/.cargo/registry/index
             ~/.cargo/registry/cache
             ~/.cargo/git/db
-          key: '96-cargo-home-windows-x86_64-test-main-${{ github.sha }}'
+          key: '96-cargo-home-windows-x86_64-test-${{ matrix.test_crate }}-${{ github.sha }}'
       - name: Cache build output
         uses: cirruslabs/cache/save@v4
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'' && github.ref == ''refs/heads/main'''
+        if: '!startsWith(github.ref, ''refs/tags/'') && github.ref == ''refs/heads/main'''
         with:
           path: |-
             ./target
             !./target/*/gn_out
             !./target/*/gn_root
             !./target/*/*.zip
             !./target/*/*.tar.gz
-          key: '96-cargo-target-windows-x86_64-debug-test-main-${{ github.sha }}'
+          key: '96-cargo-target-windows-x86_64-debug-test-${{ matrix.test_crate }}-${{ github.sha }}'
   test-libs-debug-windows-x86_64:
     name: test libs debug windows-x86_64
     needs:
@@ -2374,7 +2359,7 @@ jobs:
             ~/.cargo/registry/cache
             ~/.cargo/git/db
           key: never_saved
-          restore-keys: 96-cargo-home-windows-x86_64-test-main-
+          restore-keys: '96-cargo-home-windows-x86_64-test-${{ matrix.test_crate }}-'
       - name: Restore cache build output
         uses: cirruslabs/cache/restore@v4
         if: '!startsWith(github.ref, ''refs/tags/'') && !(!contains(github.event.pull_request.labels.*.name, ''ci-full'') && github.event_name == ''pull_request'') && github.ref != ''refs/heads/main'''
@@ -2386,7 +2371,7 @@ jobs:
             !./target/*/*.zip
             !./target/*/*.tar.gz
           key: never_saved
-          restore-keys: 96-cargo-target-windows-x86_64-release-test-main-
+          restore-keys: '96-cargo-target-windows-x86_64-release-test-${{ matrix.test_crate }}-'
       - name: Apply and update mtime cache
         uses: ./.github/mtime_cache
         if: '!startsWith(github.ref, ''refs/tags/'') && !(!contains(github.event.pull_request.labels.*.name, ''ci-full'') && github.event_name == ''pull_request'')'
@@ -2621,7 +2606,7 @@ jobs:
             ~/.cargo/registry/cache
             ~/.cargo/git/db
           key: never_saved
-          restore-keys: 96-cargo-home-windows-aarch64-test-main-
+          restore-keys: '96-cargo-home-windows-aarch64-test-${{ matrix.test_crate }}-'
       - name: Restore cache build output
         uses: cirruslabs/cache/restore@v4
         if: '!startsWith(github.ref, ''refs/tags/'') && github.ref != ''refs/heads/main'''
@@ -2633,7 +2618,7 @@ jobs:
             !./target/*/*.zip
             !./target/*/*.tar.gz
           key: never_saved
-          restore-keys: 96-cargo-target-windows-aarch64-debug-test-main-
+          restore-keys: '96-cargo-target-windows-aarch64-debug-test-${{ matrix.test_crate }}-'
       - name: Apply and update mtime cache
         uses: ./.github/mtime_cache
         if: '!startsWith(github.ref, ''refs/tags/'')'
@@ -2678,11 +2663,6 @@ jobs:
       - name: Build ffi (debug)
         if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''specs'''
         run: cargo build -p test_ffi
-      - name: Build caches (debug)
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'''
-        env:
-          CARGO_PROFILE_DEV_DEBUG: 0
-        run: cargo test --no-run -p integration_tests -p node_compat_tests -p specs_tests -p unit_tests -p unit_node_tests
       - name: Test (debug)
         if: '!startsWith(github.ref, ''refs/tags/'')'
         env:
@@ -2699,7 +2679,7 @@ jobs:
           path: 'target/test_results_${{ matrix.test_crate }}.json'
       - name: Cache cargo home
         uses: cirruslabs/cache/save@v4
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'' && github.ref == ''refs/heads/main'''
+        if: '!startsWith(github.ref, ''refs/tags/'') && github.ref == ''refs/heads/main'''
         with:
           path: |-
             ~/.cargo/.crates.toml
@@ -2708,18 +2688,18 @@ jobs:
             ~/.cargo/registry/index
             ~/.cargo/registry/cache
             ~/.cargo/git/db
-          key: '96-cargo-home-windows-aarch64-test-main-${{ github.sha }}'
+          key: '96-cargo-home-windows-aarch64-test-${{ matrix.test_crate }}-${{ github.sha }}'
       - name: Cache build output
         uses: cirruslabs/cache/save@v4
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'' && github.ref == ''refs/heads/main'''
+        if: '!startsWith(github.ref, ''refs/tags/'') && github.ref == ''refs/heads/main'''
         with:
           path: |-
             ./target
             !./target/*/gn_out
             !./target/*/gn_root
             !./target/*/*.zip
             !./target/*/*.tar.gz
-          key: '96-cargo-target-windows-aarch64-debug-test-main-${{ github.sha }}'
+          key: '96-cargo-target-windows-aarch64-debug-test-${{ matrix.test_crate }}-${{ github.sha }}'
   build-release-windows-aarch64:
     name: build release windows-aarch64
     needs:
@@ -3032,7 +3012,7 @@ jobs:
             ~/.cargo/registry/cache
             ~/.cargo/git/db
           key: never_saved
-          restore-keys: 96-cargo-home-windows-aarch64-test-main-
+          restore-keys: '96-cargo-home-windows-aarch64-test-${{ matrix.test_crate }}-'
       - name: Restore cache build output
         uses: cirruslabs/cache/restore@v4
         if: '!startsWith(github.ref, ''refs/tags/'') && !(!contains(github.event.pull_request.labels.*.name, ''ci-full'') && github.event_name == ''pull_request'') && github.ref != ''refs/heads/main'''
@@ -3044,7 +3024,7 @@ jobs:
             !./target/*/*.zip
             !./target/*/*.tar.gz
           key: never_saved
-          restore-keys: 96-cargo-target-windows-aarch64-release-test-main-
+          restore-keys: '96-cargo-target-windows-aarch64-release-test-${{ matrix.test_crate }}-'
       - name: Apply and update mtime cache
         uses: ./.github/mtime_cache
         if: '!startsWith(github.ref, ''refs/tags/'') && !(!contains(github.event.pull_request.labels.*.name, ''ci-full'') && github.event_name == ''pull_request'')'
@@ -3463,7 +3443,7 @@ jobs:
             ~/.cargo/registry/cache
             ~/.cargo/git/db
           key: never_saved
-          restore-keys: 96-cargo-home-linux-x86_64-test-main-
+          restore-keys: '96-cargo-home-linux-x86_64-test-${{ matrix.test_crate }}-'
       - name: Restore cache build output
         uses: cirruslabs/cache/restore@v4
         if: '!startsWith(github.ref, ''refs/tags/'') && github.ref != ''refs/heads/main'''
@@ -3475,7 +3455,7 @@ jobs:
             !./target/*/*.zip
             !./target/*/*.tar.gz
           key: never_saved
-          restore-keys: 96-cargo-target-linux-x86_64-release-test-main-
+          restore-keys: '96-cargo-target-linux-x86_64-release-test-${{ matrix.test_crate }}-'
       - name: Apply and update mtime cache
         uses: ./.github/mtime_cache
         if: '!startsWith(github.ref, ''refs/tags/'')'
@@ -3610,9 +3590,6 @@ jobs:
       - name: Build ffi (release)
         if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''specs'''
         run: cargo build --release -p test_ffi
-      - name: Build caches (release)
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'''
-        run: cargo test --no-run -p integration_tests -p node_compat_tests -p specs_tests -p unit_tests -p unit_node_tests --release
       - name: Test (release)
         if: '!startsWith(github.ref, ''refs/tags/'')'
         run: 'cargo test -p ${{ matrix.test_package }} --test ${{ matrix.test_crate }} --release'
@@ -3627,7 +3604,7 @@ jobs:
           path: 'target/test_results_${{ matrix.test_crate }}.json'
       - name: Cache cargo home
         uses: cirruslabs/cache/save@v4
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'' && github.ref == ''refs/heads/main'''
+        if: '!startsWith(github.ref, ''refs/tags/'') && github.ref == ''refs/heads/main'''
         with:
           path: |-
             ~/.cargo/.crates.toml
@@ -3636,18 +3613,18 @@ jobs:
             ~/.cargo/registry/index
             ~/.cargo/registry/cache
             ~/.cargo/git/db
-          key: '96-cargo-home-linux-x86_64-test-main-${{ github.sha }}'
+          key: '96-cargo-home-linux-x86_64-test-${{ matrix.test_crate }}-${{ github.sha }}'
       - name: Cache build output
         uses: cirruslabs/cache/save@v4
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'' && github.ref == ''refs/heads/main'''
+        if: '!startsWith(github.ref, ''refs/tags/'') && github.ref == ''refs/heads/main'''
         with:
           path: |-
             ./target
             !./target/*/gn_out
             !./target/*/gn_root
             !./target/*/*.zip
             !./target/*/*.tar.gz
-          key: '96-cargo-target-linux-x86_64-release-test-main-${{ github.sha }}'
+          key: '96-cargo-target-linux-x86_64-release-test-${{ matrix.test_crate }}-${{ github.sha }}'
   wpt-release-linux-x86_64:
     name: wpt release linux-x86_64
     needs:
@@ -4006,7 +3983,7 @@ jobs:
             ~/.cargo/registry/cache
             ~/.cargo/git/db
           key: never_saved
-          restore-keys: 96-cargo-home-linux-x86_64-test-main-
+          restore-keys: '96-cargo-home-linux-x86_64-test-${{ matrix.test_crate }}-'
       - name: Restore cache build output
         uses: cirruslabs/cache/restore@v4
         if: '!startsWith(github.ref, ''refs/tags/'') && github.ref != ''refs/heads/main'''
@@ -4018,7 +3995,7 @@ jobs:
             !./target/*/*.zip
             !./target/*/*.tar.gz
           key: never_saved
-          restore-keys: 96-cargo-target-linux-x86_64-debug-test-main-
+          restore-keys: '96-cargo-target-linux-x86_64-debug-test-${{ matrix.test_crate }}-'
       - name: Apply and update mtime cache
         uses: ./.github/mtime_cache
         if: '!startsWith(github.ref, ''refs/tags/'')'
@@ -4153,11 +4130,6 @@ jobs:
       - name: Build ffi (debug)
         if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''specs'''
         run: cargo build -p test_ffi
-      - name: Build caches (debug)
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'''
-        env:
-          CARGO_PROFILE_DEV_DEBUG: 0
-        run: cargo test --no-run -p integration_tests -p node_compat_tests -p specs_tests -p unit_tests -p unit_node_tests
       - name: Test (debug)
         if: '!startsWith(github.ref, ''refs/tags/'')'
         env:
@@ -4174,7 +4146,7 @@ jobs:
           path: 'target/test_results_${{ matrix.test_crate }}.json'
       - name: Cache cargo home
         uses: cirruslabs/cache/save@v4
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'' && github.ref == ''refs/heads/main'''
+        if: '!startsWith(github.ref, ''refs/tags/'') && github.ref == ''refs/heads/main'''
         with:
           path: |-
             ~/.cargo/.crates.toml
@@ -4183,18 +4155,18 @@ jobs:
             ~/.cargo/registry/index
             ~/.cargo/registry/cache
             ~/.cargo/git/db
-          key: '96-cargo-home-linux-x86_64-test-main-${{ github.sha }}'
+          key: '96-cargo-home-linux-x86_64-test-${{ matrix.test_crate }}-${{ github.sha }}'
       - name: Cache build output
         uses: cirruslabs/cache/save@v4
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'' && github.ref == ''refs/heads/main'''
+        if: '!startsWith(github.ref, ''refs/tags/'') && github.ref == ''refs/heads/main'''
         with:
           path: |-
             ./target
             !./target/*/gn_out
             !./target/*/gn_root
             !./target/*/*.zip
             !./target/*/*.tar.gz
-          key: '96-cargo-target-linux-x86_64-debug-test-main-${{ github.sha }}'
+          key: '96-cargo-target-linux-x86_64-debug-test-${{ matrix.test_crate }}-${{ github.sha }}'
   build-libs-debug-linux-x86_64:
     name: build libs debug linux-x86_64
     needs:
@@ -4465,7 +4437,7 @@ jobs:
             ~/.cargo/registry/cache
             ~/.cargo/git/db
           key: never_saved
-          restore-keys: 96-cargo-home-linux-aarch64-test-main-
+          restore-keys: '96-cargo-home-linux-aarch64-test-${{ matrix.test_crate }}-'
       - name: Restore cache build output
         uses: cirruslabs/cache/restore@v4
         if: '!startsWith(github.ref, ''refs/tags/'') && github.ref != ''refs/heads/main'''
@@ -4477,7 +4449,7 @@ jobs:
             !./target/*/*.zip
             !./target/*/*.tar.gz
           key: never_saved
-          restore-keys: 96-cargo-target-linux-aarch64-debug-test-main-
+          restore-keys: '96-cargo-target-linux-aarch64-debug-test-${{ matrix.test_crate }}-'
       - name: Apply and update mtime cache
         uses: ./.github/mtime_cache
         if: '!startsWith(github.ref, ''refs/tags/'')'
@@ -4534,11 +4506,6 @@ jobs:
       - name: Build ffi (debug)
         if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''specs'''
         run: cargo build -p test_ffi
-      - name: Build caches (debug)
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'''
-        env:
-          CARGO_PROFILE_DEV_DEBUG: 0
-        run: cargo test --no-run -p integration_tests -p node_compat_tests -p specs_tests -p unit_tests -p unit_node_tests
       - name: Test (debug)
         if: '!startsWith(github.ref, ''refs/tags/'')'
         env:
@@ -4555,7 +4522,7 @@ jobs:
           path: 'target/test_results_${{ matrix.test_crate }}.json'
       - name: Cache cargo home
         uses: cirruslabs/cache/save@v4
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'' && github.ref == ''refs/heads/main'''
+        if: '!startsWith(github.ref, ''refs/tags/'') && github.ref == ''refs/heads/main'''
         with:
           path: |-
             ~/.cargo/.crates.toml
@@ -4564,18 +4531,18 @@ jobs:
             ~/.cargo/registry/index
             ~/.cargo/registry/cache
             ~/.cargo/git/db
-          key: '96-cargo-home-linux-aarch64-test-main-${{ github.sha }}'
+          key: '96-cargo-home-linux-aarch64-test-${{ matrix.test_crate }}-${{ github.sha }}'
       - name: Cache build output
         uses: cirruslabs/cache/save@v4
-        if: '!startsWith(github.ref, ''refs/tags/'') && matrix.test_crate == ''unit_node'' && github.ref == ''refs/heads/main'''
+        if: '!startsWith(github.ref, ''refs/tags/'') && github.ref == ''refs/heads/main'''
         with:
           path: |-
             ./target
             !./target/*/gn_out
             !./target/*/gn_root
             !./target/*/*.zip
             !./target/*/*.tar.gz
-          key: '96-cargo-target-linux-aarch64-debug-test-main-${{ github.sha }}'
+          key: '96-cargo-target-linux-aarch64-debug-test-${{ matrix.test_crate }}-${{ github.sha }}'
   test-libs-debug-linux-aarch64:
     name: test libs debug linux-aarch64
     needs:
@@ -5025,7 +4992,7 @@ jobs:
             ~/.cargo/registry/cache
             ~/.cargo/git/db
           key: never_saved
-          restore-keys: 96-cargo-home-linux-aarch64-test-main-
+          restore-keys: '96-cargo-home-linux-aarch64-test-${{ matrix.test_crate }}-'
       - name: Restore cache build output
         uses: cirruslabs/cache/restore@v4
         if: '!startsWith(github.ref, ''refs/tags/'') && !(!contains(github.event.pull_request.labels.*.name, ''ci-full'') && github.event_name == ''pull_request'') && github.ref != ''refs/heads/main'''
@@ -5037,7 +5004,7 @@ jobs:
             !./target/*/*.zip
             !./target/*/*.tar.gz
           key: never_saved
-          restore-keys: 96-cargo-target-linux-aarch64-release-test-main-
+          restore-keys: '96-cargo-target-linux-aarch64-release-test-${{ matrix.test_crate }}-'
       - name: Apply and update mtime cache
         uses: ./.github/mtime_cache
         if: '!startsWith(github.ref, ''refs/tags/'') && !(!contains(github.event.pull_request.labels.*.name, ''ci-full'') && github.event_name == ''pull_request'')'

filename: tests/util/lib/hash.rs
patch: @@ -1,13 +1,13 @@
 // Copyright 2018-2026 the Deno authors. MIT license.
 
 use std::hash::Hasher;
+use std::io::Read;
 use std::path::Path;
 use std::path::PathBuf;
-use std::time::SystemTime;
 
 use crate::eprintln;
 
-/// A fast hasher for computing a combined hash of files and directory mtimes.
+/// A fast hasher for computing a combined hash of file contents.
 /// Uses xxhash64 for speed.
 pub struct InputHasher(twox_hash::XxHash64);
 
@@ -20,32 +20,39 @@ impl InputHasher {
     hasher
   }
 
-  /// Hash a single file's mtime. Skips if file doesn't exist.
+  /// Hash a single file's contents. Skips if file doesn't exist.
   pub fn hash_file(&mut self, path: impl AsRef<Path>) -> &mut Self {
-    if let Ok(meta) = std::fs::metadata(path.as_ref()) {
-      self.hash_mtime(meta.modified().ok());
+    if let Ok(mut file) = std::fs::File::open(path.as_ref()) {
+      self.hash_reader(&mut file);
     }
     self
   }
 
-  /// Recursively hash all file mtimes in a directory (sorted for determinism).
-  /// Skips if directory doesn't exist.
+  /// Recursively hash all file contents in a directory (sorted for
+  /// determinism). Skips if directory doesn't exist.
   pub fn hash_dir(&mut self, path: impl AsRef<Path>) -> &mut Self {
     let path = path.as_ref();
     let mut entries = Vec::new();
     collect_entries_recursive(path, &mut entries);
-    entries.sort_by(|(a, _), (b, _)| a.cmp(b));
-    for (_, mtime) in &entries {
-      self.hash_mtime(*mtime);
+    entries.sort();
+    for entry_path in &entries {
+      if let Ok(rel) = entry_path.strip_prefix(path) {
+        self.0.write(rel.as_os_str().as_encoded_bytes());
+      }
+      if let Ok(mut file) = std::fs::File::open(entry_path) {
+        self.hash_reader(&mut file);
+      }
     }
     self
   }
 
-  fn hash_mtime(&mut self, mtime: Option<SystemTime>) {
-    if let Some(mtime) = mtime
-      && let Ok(d) = mtime.duration_since(SystemTime::UNIX_EPOCH)
-    {
-      self.0.write_u64(d.as_secs());
+  fn hash_reader(&mut self, reader: &mut impl Read) {
+    let mut buf = [0u8; 8192];
+    loop {
+      match reader.read(&mut buf) {
+        Ok(0) | Err(_) => break,
+        Ok(n) => self.0.write(&buf[..n]),
+      }
     }
   }
 
@@ -54,10 +61,7 @@ impl InputHasher {
   }
 }
 
-fn collect_entries_recursive(
-  dir: &Path,
-  out: &mut Vec<(PathBuf, Option<SystemTime>)>,
-) {
+fn collect_entries_recursive(dir: &Path, out: &mut Vec<PathBuf>) {
   let entries = match std::fs::read_dir(dir) {
     Ok(entries) => entries,
     Err(_) => return,
@@ -70,8 +74,7 @@ fn collect_entries_recursive(
     if file_type.is_dir() {
       collect_entries_recursive(&entry.path(), out);
     } else {
-      let mtime = entry.metadata().ok().and_then(|m| m.modified().ok());
-      out.push((entry.path(), mtime));
+      out.push(entry.path());
     }
   }
 }
@@ -111,14 +114,16 @@ pub fn should_skip_on_ci(
 
   eprintln!("ci hash took {}ms", start.elapsed().as_millis());
 
-  if let Ok(old_hash) = std::fs::read_to_string(&hash_path)
-    && old_hash.trim() == new_hash
-  {
+  let maybe_old_hash = std::fs::read_to_string(&hash_path).ok();
+  let maybe_old_hash = maybe_old_hash.as_ref().map(|h| h.trim());
+  if maybe_old_hash == Some(&new_hash) {
     eprintln!("{name} input hash unchanged ({new_hash}), skipping");
     return true;
   }
 
-  eprintln!("{name} input hash changed, writing new hash ({new_hash})");
+  eprintln!(
+    "{name} input hash changed from {maybe_old_hash:?}, writing new hash ({new_hash})"
+  );
   std::fs::write(&hash_path, &new_hash).ok();
   false
 }