ci: restore source mtimes after checkout for stable cargo fingerprints

`actions/checkout@v4` stamps every file with the checkout time. Cargo's
freshness check is mtime-based, so workspace crates always look newer
than their cached fingerprints and recompile from scratch (~16min on a
Test Suite run with the cache otherwise warm).

git-restore-mtime walks git history and rewrites each file's mtime to
its last commit's timestamp. Identical commit ⇒ identical mtimes ⇒
cargo treats sources as fresh. Binary is pre-installed on the
self-hosted runner image; the `command -v` guard keeps the step a
no-op on hosted runners.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
John Detter
2026-05-05 03:51:26 -05:00
parent 3dc3b5271f
commit 4a172b8a21
2 changed files with 181 additions and 0 deletions
+168
View File
@@ -56,6 +56,20 @@ jobs:
with:
ref: ${{ env.GIT_REF }}
- name: Restore source mtimes from git history
# `actions/checkout@v4` stamps every file with the checkout time, but
# cargo's freshness check uses mtime. Without this, every workspace
# crate looks newer than its cached fingerprint and gets recompiled.
# git-restore-mtime sets each file's mtime to its last commit time,
# making mtimes deterministic across the cache builder and the runner.
# No-op on hosted runners (binary only exists on the self-hosted image).
if: runner.os == 'Linux'
shell: bash
run: |
if command -v git-restore-mtime >/dev/null 2>&1; then
git restore-mtime --quiet
fi
- name: Use cached cargo target if available
if: runner.os == 'Linux'
shell: bash
@@ -210,6 +224,20 @@ jobs:
with:
ref: ${{ env.GIT_REF }}
- name: Restore source mtimes from git history
# `actions/checkout@v4` stamps every file with the checkout time, but
# cargo's freshness check uses mtime. Without this, every workspace
# crate looks newer than its cached fingerprint and gets recompiled.
# git-restore-mtime sets each file's mtime to its last commit time,
# making mtimes deterministic across the cache builder and the runner.
# No-op on hosted runners (binary only exists on the self-hosted image).
if: runner.os == 'Linux'
shell: bash
run: |
if command -v git-restore-mtime >/dev/null 2>&1; then
git restore-mtime --quiet
fi
- name: Use cached cargo target if available
if: runner.os == 'Linux'
shell: bash
@@ -308,6 +336,20 @@ jobs:
- name: Checkout sources
uses: actions/checkout@v3
- name: Restore source mtimes from git history
# `actions/checkout@v4` stamps every file with the checkout time, but
# cargo's freshness check uses mtime. Without this, every workspace
# crate looks newer than its cached fingerprint and gets recompiled.
# git-restore-mtime sets each file's mtime to its last commit time,
# making mtimes deterministic across the cache builder and the runner.
# No-op on hosted runners (binary only exists on the self-hosted image).
if: runner.os == 'Linux'
shell: bash
run: |
if command -v git-restore-mtime >/dev/null 2>&1; then
git restore-mtime --quiet
fi
- name: Use cached cargo target if available
if: runner.os == 'Linux'
shell: bash
@@ -355,6 +397,20 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Restore source mtimes from git history
# `actions/checkout@v4` stamps every file with the checkout time, but
# cargo's freshness check uses mtime. Without this, every workspace
# crate looks newer than its cached fingerprint and gets recompiled.
# git-restore-mtime sets each file's mtime to its last commit time,
# making mtimes deterministic across the cache builder and the runner.
# No-op on hosted runners (binary only exists on the self-hosted image).
if: runner.os == 'Linux'
shell: bash
run: |
if command -v git-restore-mtime >/dev/null 2>&1; then
git restore-mtime --quiet
fi
- name: Use cached cargo target if available
if: runner.os == 'Linux'
shell: bash
@@ -387,6 +443,20 @@ jobs:
permissions: read-all
steps:
- uses: actions/checkout@v3
- name: Restore source mtimes from git history
# `actions/checkout@v4` stamps every file with the checkout time, but
# cargo's freshness check uses mtime. Without this, every workspace
# crate looks newer than its cached fingerprint and gets recompiled.
# git-restore-mtime sets each file's mtime to its last commit time,
# making mtimes deterministic across the cache builder and the runner.
# No-op on hosted runners (binary only exists on the self-hosted image).
if: runner.os == 'Linux'
shell: bash
run: |
if command -v git-restore-mtime >/dev/null 2>&1; then
git restore-mtime --quiet
fi
- name: Use cached cargo target if available
if: runner.os == 'Linux'
shell: bash
@@ -415,6 +485,20 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Restore source mtimes from git history
# `actions/checkout@v4` stamps every file with the checkout time, but
# cargo's freshness check uses mtime. Without this, every workspace
# crate looks newer than its cached fingerprint and gets recompiled.
# git-restore-mtime sets each file's mtime to its last commit time,
# making mtimes deterministic across the cache builder and the runner.
# No-op on hosted runners (binary only exists on the self-hosted image).
if: runner.os == 'Linux'
shell: bash
run: |
if command -v git-restore-mtime >/dev/null 2>&1; then
git restore-mtime --quiet
fi
- name: Use cached cargo target if available
if: runner.os == 'Linux'
shell: bash
@@ -554,6 +638,20 @@ jobs:
with:
ref: ${{ env.GIT_REF }}
- name: Restore source mtimes from git history
# `actions/checkout@v4` stamps every file with the checkout time, but
# cargo's freshness check uses mtime. Without this, every workspace
# crate looks newer than its cached fingerprint and gets recompiled.
# git-restore-mtime sets each file's mtime to its last commit time,
# making mtimes deterministic across the cache builder and the runner.
# No-op on hosted runners (binary only exists on the self-hosted image).
if: runner.os == 'Linux'
shell: bash
run: |
if command -v git-restore-mtime >/dev/null 2>&1; then
git restore-mtime --quiet
fi
- name: Use cached cargo target if available
if: runner.os == 'Linux'
shell: bash
@@ -594,6 +692,20 @@ jobs:
with:
ref: ${{ env.GIT_REF }}
- name: Restore source mtimes from git history
# `actions/checkout@v4` stamps every file with the checkout time, but
# cargo's freshness check uses mtime. Without this, every workspace
# crate looks newer than its cached fingerprint and gets recompiled.
# git-restore-mtime sets each file's mtime to its last commit time,
# making mtimes deterministic across the cache builder and the runner.
# No-op on hosted runners (binary only exists on the self-hosted image).
if: runner.os == 'Linux'
shell: bash
run: |
if command -v git-restore-mtime >/dev/null 2>&1; then
git restore-mtime --quiet
fi
- name: Use cached cargo target if available
if: runner.os == 'Linux'
shell: bash
@@ -692,6 +804,20 @@ jobs:
id: checkout-stdb
uses: actions/checkout@v4
- name: Restore source mtimes from git history
# `actions/checkout@v4` stamps every file with the checkout time, but
# cargo's freshness check uses mtime. Without this, every workspace
# crate looks newer than its cached fingerprint and gets recompiled.
# git-restore-mtime sets each file's mtime to its last commit time,
# making mtimes deterministic across the cache builder and the runner.
# No-op on hosted runners (binary only exists on the self-hosted image).
if: runner.os == 'Linux'
shell: bash
run: |
if command -v git-restore-mtime >/dev/null 2>&1; then
git restore-mtime --quiet
fi
- name: Use cached cargo target if available
if: runner.os == 'Linux'
shell: bash
@@ -847,6 +973,20 @@ jobs:
id: checkout-stdb
uses: actions/checkout@v4
- name: Restore source mtimes from git history
# `actions/checkout@v4` stamps every file with the checkout time, but
# cargo's freshness check uses mtime. Without this, every workspace
# crate looks newer than its cached fingerprint and gets recompiled.
# git-restore-mtime sets each file's mtime to its last commit time,
# making mtimes deterministic across the cache builder and the runner.
# No-op on hosted runners (binary only exists on the self-hosted image).
if: runner.os == 'Linux'
shell: bash
run: |
if command -v git-restore-mtime >/dev/null 2>&1; then
git restore-mtime --quiet
fi
- name: Use cached cargo target if available
if: runner.os == 'Linux'
shell: bash
@@ -1196,6 +1336,20 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v3
- name: Restore source mtimes from git history
# `actions/checkout@v4` stamps every file with the checkout time, but
# cargo's freshness check uses mtime. Without this, every workspace
# crate looks newer than its cached fingerprint and gets recompiled.
# git-restore-mtime sets each file's mtime to its last commit time,
# making mtimes deterministic across the cache builder and the runner.
# No-op on hosted runners (binary only exists on the self-hosted image).
if: runner.os == 'Linux'
shell: bash
run: |
if command -v git-restore-mtime >/dev/null 2>&1; then
git restore-mtime --quiet
fi
- name: Use cached cargo target if available
if: runner.os == 'Linux'
shell: bash
@@ -1241,6 +1395,20 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
- name: Restore source mtimes from git history
# `actions/checkout@v4` stamps every file with the checkout time, but
# cargo's freshness check uses mtime. Without this, every workspace
# crate looks newer than its cached fingerprint and gets recompiled.
# git-restore-mtime sets each file's mtime to its last commit time,
# making mtimes deterministic across the cache builder and the runner.
# No-op on hosted runners (binary only exists on the self-hosted image).
if: runner.os == 'Linux'
shell: bash
run: |
if command -v git-restore-mtime >/dev/null 2>&1; then
git restore-mtime --quiet
fi
- name: Use cached cargo target if available
if: runner.os == 'Linux'
shell: bash
@@ -12,6 +12,19 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Restore source mtimes from git history
# `actions/checkout@v4` stamps every file with the checkout time, but
# cargo's freshness check uses mtime. Without this, every workspace
# crate looks newer than its cached fingerprint and gets recompiled.
# git-restore-mtime sets each file's mtime to its last commit time,
# making mtimes deterministic across the cache builder and the runner.
# No-op on hosted runners (binary only exists on the self-hosted image).
if: runner.os == 'Linux'
shell: bash
run: |
if command -v git-restore-mtime >/dev/null 2>&1; then
git restore-mtime --quiet
fi
- name: Use cached cargo target if available
if: runner.os == 'Linux'
shell: bash