You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have been testing runs-on/snapshot@v1 as a way to preserve Rust/Cargo build state between ephemeral CI runners. The snapshot approach works very well for Cargo build artifacts, but there is another source of repeated overhead: normal setup actions often install tools outside the snapshot path.
Examples include actions that install or configure tools such as:
Rust toolchain / rustup components
Zig
cargo-lambda
Node / pnpm / other language toolchains
For the snapshot approach to be most useful, it would be helpful to have a more elegant way to keep using normal GitHub Actions while having the files those actions create land inside the restored snapshot automatically.
The goal is not to persist these tool installs through GitHub Actions Cache or RunsOn Magic Cache. The goal is to keep using the convenient setup actions that already exist, but make their side effects snapshot-backed.
Right now, the reliable workaround is to stop using some setup actions and replace them with manual install logic that writes into the snapshot root. That works, but it makes the workflow less idiomatic and more fragile.
Problem
The build-state snapshot root might look like this:
Those locations are outside the snapshot path, so the work is repeated on every fresh runner. Some actions may also use GitHub Actions Cache backed by Azure Storage or RunsOn Magic Cache backed by S3/R2 when configured that way, but that is still an archive/cache layer separate from the restored filesystem snapshot. For this use case, I want the tool installation itself to become part of the same block-level build-state snapshot.
In testing, the actual Cargo build became almost a no-op after restoring the snapshot, but setup actions still consumed meaningful time because they were doing work outside the snapshot.
It is possible to solve this manually by installing tools into the snapshot root, but that means losing the convenience and maintenance benefits of existing setup actions.
Current workaround
Instead of using normal setup actions for some tools, the workflow can manually install tools into the snapshot root:
env:
SNAPSHOT_ROOT: /mnt/build-snapshotSNAPSHOT_WORKSPACE: /mnt/build-snapshot/workspaceCARGO_HOME: /mnt/build-snapshot/cargo-homeCARGO_TARGET_DIR: /mnt/build-snapshot/workspace/app/targetZIG_GLOBAL_CACHE_DIR: /mnt/build-snapshot/zig-cache/globalZIG_LOCAL_CACHE_DIR: /mnt/build-snapshot/zig-cache/localsteps:
- uses: runs-on/snapshot@v1with:
path: ${{ env.SNAPSHOT_ROOT }}version: build-state-v1volume_size: 10
- name: Configure snapshot pathsrun: | mkdir -p "$SNAPSHOT_WORKSPACE" "$CARGO_HOME" "$SNAPSHOT_ROOT/tools" echo "$CARGO_HOME/bin" >> "$GITHUB_PATH" echo "$SNAPSHOT_ROOT/tools/zig" >> "$GITHUB_PATH" echo "$SNAPSHOT_ROOT/tools/cargo-lambda" >> "$GITHUB_PATH"
- name: Install Zig into snapshotrun: | if [ ! -x "$SNAPSHOT_ROOT/tools/zig/zig" ]; then # download and extract Zig into the snapshot pathtrue fi
- name: Install cargo-lambda into snapshotrun: | if [ ! -x "$SNAPSHOT_ROOT/tools/cargo-lambda/cargo-lambda" ]; then # download and extract cargo-lambda into the snapshot pathtrue fi
This works, but it replaces maintained setup actions with custom download/extract logic.
Desired workflow shape
Ideally, a workflow could still use normal setup actions:
And the RunsOn integration would make those actions write their installed tools and caches into snapshot-backed locations, or at least make the standard paths point into the snapshot. From the workflow author's perspective, the setup actions would stay normal and convenient; from the filesystem perspective, their outputs would be persisted by the snapshot rather than by GitHub Actions Cache on Azure Storage or RunsOn Magic Cache on S3/R2.
Possible approaches
Option 1: Snapshot-aware toolcache helper
A helper action could configure standard tool/cache environment variables before setup actions run:
RUNNER_TOOL_CACHE
CARGO_HOME
RUSTUP_HOME
ZIG_GLOBAL_CACHE_DIR
ZIG_LOCAL_CACHE_DIR
HOME-based cache directories where safe
This would let many setup actions continue using their normal logic while the resulting installs land in the snapshot instead of relying on a separate cache backend.
flowchart LR
snapshot[Restore snapshot]
helper[Configure snapshot-aware tool paths]
setup[Normal setup actions]
tools[Tools installed inside snapshot]
later[Later run restores tools]
snapshot --> helper --> setup --> tools --> later
Loading
Option 2: Mount or symlink common tool paths
RunsOn could provide a supported way to map standard runner paths into the snapshot volume:
Then explain which popular actions respect which environment variables, and which actions do not.
For example:
dtolnay/rust-toolchain: respects CARGO_HOME/RUSTUP_HOME behavior through rustup/cargo
setup-zig: supports Zig cache env vars but may still use tool-cache behavior
install-action: may install into ~/.install-action unless configured otherwise
Useful outputs or diagnostics
It would also be helpful if the helper could print a summary like:
Snapshot-aware tool paths:
RUNNER_TOOL_CACHE=/mnt/build-snapshot/tool-cache
CARGO_HOME=/mnt/build-snapshot/cargo-home
RUSTUP_HOME=/mnt/build-snapshot/rustup-home
ZIG_GLOBAL_CACHE_DIR=/mnt/build-snapshot/zig-cache/global
ZIG_LOCAL_CACHE_DIR=/mnt/build-snapshot/zig-cache/local
Detected tool installs:
zig: restored from snapshot
cargo-lambda: restored from snapshot
rust target aarch64-unknown-linux-gnu: restored from snapshot
This would make it obvious whether setup work is being reused or repeated.
Security considerations
This feature would need to avoid accidentally snapshotting secrets.
If CARGO_HOME is inside the snapshot, workflows need a clean way to remove credentials before save, or the snapshot action/helper could support excludes/scrubbing hooks.
This is not trying to replace actions/cache or Magic Cache.
The use case is specifically:
I already restored a block-level filesystem snapshot.
I want normal setup actions to populate that same filesystem snapshot.
I want later runs to skip repeated tool downloads/extractions.
Archive cache actions are still useful for many dependency caches, but for build-state reuse the goal is to preserve one coherent filesystem state.
Desired end state
The ideal result is that a workflow can keep using maintained setup actions while RunsOn handles the “make this setup state snapshot-backed” part:
Summary
I have been testing
runs-on/snapshot@v1as a way to preserve Rust/Cargo build state between ephemeral CI runners. The snapshot approach works very well for Cargo build artifacts, but there is another source of repeated overhead: normal setup actions often install tools outside the snapshot path.Examples include actions that install or configure tools such as:
For the snapshot approach to be most useful, it would be helpful to have a more elegant way to keep using normal GitHub Actions while having the files those actions create land inside the restored snapshot automatically.
The goal is not to persist these tool installs through GitHub Actions Cache or RunsOn Magic Cache. The goal is to keep using the convenient setup actions that already exist, but make their side effects snapshot-backed.
Right now, the reliable workaround is to stop using some setup actions and replace them with manual install logic that writes into the snapshot root. That works, but it makes the workflow less idiomatic and more fragile.
Problem
The build-state snapshot root might look like this:
But many standard setup actions install elsewhere, for example:
Those locations are outside the snapshot path, so the work is repeated on every fresh runner. Some actions may also use GitHub Actions Cache backed by Azure Storage or RunsOn Magic Cache backed by S3/R2 when configured that way, but that is still an archive/cache layer separate from the restored filesystem snapshot. For this use case, I want the tool installation itself to become part of the same block-level build-state snapshot.
In testing, the actual Cargo build became almost a no-op after restoring the snapshot, but setup actions still consumed meaningful time because they were doing work outside the snapshot.
flowchart TD start[Fresh ephemeral runner] snap[Restore build-state snapshot] cargo[Cargo build state restored] setup[Setup actions install tools] outside[Tools installed outside snapshot] repeat[Repeated work every run] build[Build is fast, setup remains slow] start --> snap --> cargo --> build start --> setup --> outside --> repeat --> buildWhy this matters
For Cargo/Rust workloads, block-level snapshots can preserve the expensive build state:
Once that is solved, the next visible bottleneck becomes setup work:
It is possible to solve this manually by installing tools into the snapshot root, but that means losing the convenience and maintenance benefits of existing setup actions.
Current workaround
Instead of using normal setup actions for some tools, the workflow can manually install tools into the snapshot root:
This works, but it replaces maintained setup actions with custom download/extract logic.
Desired workflow shape
Ideally, a workflow could still use normal setup actions:
And the RunsOn integration would make those actions write their installed tools and caches into snapshot-backed locations, or at least make the standard paths point into the snapshot. From the workflow author's perspective, the setup actions would stay normal and convenient; from the filesystem perspective, their outputs would be persisted by the snapshot rather than by GitHub Actions Cache on Azure Storage or RunsOn Magic Cache on S3/R2.
Possible approaches
Option 1: Snapshot-aware toolcache helper
A helper action could configure standard tool/cache environment variables before setup actions run:
It could set or prepare common paths such as:
This would let many setup actions continue using their normal logic while the resulting installs land in the snapshot instead of relying on a separate cache backend.
flowchart LR snapshot[Restore snapshot] helper[Configure snapshot-aware tool paths] setup[Normal setup actions] tools[Tools installed inside snapshot] later[Later run restores tools] snapshot --> helper --> setup --> tools --> laterOption 2: Mount or symlink common tool paths
RunsOn could provide a supported way to map standard runner paths into the snapshot volume:
This could be opt-in, because redirecting broad home directories may be risky. A narrowly scoped mapping for known tool directories would be safer.
Example:
Option 3: A documented recipe for standard setup actions
Even if this is not implemented as a new action, documentation could provide a blessed recipe:
Then explain which popular actions respect which environment variables, and which actions do not.
For example:
Useful outputs or diagnostics
It would also be helpful if the helper could print a summary like:
This would make it obvious whether setup work is being reused or repeated.
Security considerations
This feature would need to avoid accidentally snapshotting secrets.
For Cargo, credentials commonly live in:
If
CARGO_HOMEis inside the snapshot, workflows need a clean way to remove credentials before save, or the snapshot action/helper could support excludes/scrubbing hooks.Potential API:
Or:
Why this is separate from normal cache actions
This is not trying to replace
actions/cacheor Magic Cache.The use case is specifically:
Archive cache actions are still useful for many dependency caches, but for build-state reuse the goal is to preserve one coherent filesystem state.
Desired end state
The ideal result is that a workflow can keep using maintained setup actions while RunsOn handles the “make this setup state snapshot-backed” part:
That would preserve the main benefit of the snapshot approach without requiring custom install scripts for every tool.