Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/actions/setup-rust/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,19 @@ runs:
restore-cache: false
target-dir: ${{ inputs.target-dir }}

- name: Normalize Rust cache environment
if: inputs.restore-cache == 'true'
shell: bash
run: node "$SETUP_RUST_ACTION_PATH/prepare-cache.mjs"
env:
SETUP_RUST_ACTION_PATH: ${{ github.action_path }}

- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
if: inputs.restore-cache == 'true'
env:
# Spend a few more seconds when saving to reduce every later download.
# This also applies to the action's post step, which creates the archive.
ZSTD_CLEVEL: '9'
with:
# Existing entries are immutable and can lack dependencies removed
# by v2.9.1. Start a new namespace so the corrected action saves them.
Expand Down
45 changes: 45 additions & 0 deletions .github/actions/setup-rust/prepare-cache.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { execFileSync } from 'node:child_process';
import { appendFileSync } from 'node:fs';
import { homedir } from 'node:os';
import { join, resolve } from 'node:path';
import { pathToFileURL } from 'node:url';

export function prepareRustCache({
run = (args) => execFileSync('rustup', args, { encoding: 'utf8' }).trim(),
env = process.env,
home = homedir(),
} = {}) {
const active = run(['show', 'active-toolchain']).split(/\s+/)[0];
const installed = run(['toolchain', 'list', '--quiet']).split(/\s+/).filter(Boolean);
if (!active || !installed.includes(active)) {
throw new Error('The active Rust toolchain must be installed before cache setup');
}

// Cached jobs build with the workspace toolchain. rust-cache also hashes
// unused toolchains from the runner image, which vary across image updates.
// Keep the workspace compiler as the default before removing those extras.
run(['default', active]);
for (const toolchain of installed) {
if (toolchain !== active) {
run(['toolchain', 'uninstall', toolchain]);
}
}

// GitHub runners leave these defaults unset; Namespace sets them explicitly.
// rust-cache hashes nonempty environment variables, so use the same values.
// Preserve custom paths, including Windows Dev Drives.
return {
CARGO_HOME: env.CARGO_HOME || join(home, '.cargo'),
RUSTUP_HOME: env.RUSTUP_HOME || join(home, '.rustup'),
};
}

if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
const paths = prepareRustCache();
appendFileSync(
process.env.GITHUB_ENV,
Object.entries(paths)
.map(([key, value]) => `${key}=${value}\n`)
.join(''),
);
}
101 changes: 101 additions & 0 deletions .github/benchmark/rust-cache-compression/results.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
{
"run": "https://github.com/voidzero-dev/vite-plus/actions/runs/39453647412",
"benchmark_commit": "31b8c67f1",
"source_commit": "0cbfb6d6bf24ceb8b99b8645c613f4d27fadf359",
"scope": "Restored main cache payloads: Cargo registry, Cargo git, and target. Excludes Cargo bin and its installation metadata. Each level compresses the same tar stream; SHA-256 of the decompressed bytes must match. One timing sample per level and job.",
"samples": [
{
"name": "linux-lint",
"source_bytes": 1776875520,
"source_sha256": "fbb377c81a91bef220e723ec4483e273e1850ae997d395443f3a077a705e48a8",
"paths": [
"/home/runner/.cargo/registry",
"/home/runner/.cargo/git",
"/home/runner/work/vite-plus/vite-plus/target"
],
"zstd": "*** Zstandard CLI (64-bit) v1.5.7, by Yann Collet ***",
"samples": [
{
"level": 3,
"bytes": 513505284,
"compress_seconds": 2.6415996039999996,
"decompress_and_hash_seconds": 1.804909391999999
},
{
"level": 6,
"bytes": 493021878,
"compress_seconds": 6.507066184999999,
"decompress_and_hash_seconds": 1.7851912130000045
},
{
"level": 9,
"bytes": 457478458,
"compress_seconds": 9.765904976000002,
"decompress_and_hash_seconds": 1.7819855579999881
}
]
},
{
"name": "linux-test",
"source_bytes": 3391518720,
"source_sha256": "e8b067a35ef016642e388aaf3dfb4e30e94018ea6ebbd68a7a7f56f6d08f5b60",
"paths": [
"/home/runner/.cargo/registry",
"/home/runner/.cargo/git",
"/home/runner/work/vite-plus/vite-plus/target"
],
"zstd": "*** Zstandard CLI (64-bit) v1.5.7, by Yann Collet ***",
"samples": [
{
"level": 3,
"bytes": 845734789,
"compress_seconds": 6.381204795999992,
"decompress_and_hash_seconds": 4.233851232000006
},
{
"level": 6,
"bytes": 805789463,
"compress_seconds": 15.717300264999977,
"decompress_and_hash_seconds": 4.200105497999999
},
{
"level": 9,
"bytes": 705263026,
"compress_seconds": 22.005928431,
"decompress_and_hash_seconds": 4.200576061999982
}
]
},
{
"name": "mac-test",
"source_bytes": 4381358080,
"source_sha256": "40ff23bc23b03fc05171ba01b9ce4896e4821429c6807b7bebc8bcdddaf23abd",
"paths": [
"/Users/runner/.cargo/registry",
"/Users/runner/.cargo/git",
"/Users/runner/work/vite-plus/vite-plus/target"
],
"zstd": "*** Zstandard CLI (64-bit) v1.5.7, by Yann Collet ***",
"samples": [
{
"level": 3,
"bytes": 1127662872,
"compress_seconds": 1.3496105419999935,
"decompress_and_hash_seconds": 3.172481375000004
},
{
"level": 6,
"bytes": 1076874052,
"compress_seconds": 3.5355037500000037,
"decompress_and_hash_seconds": 3.1357934999999912
},
{
"level": 9,
"bytes": 926059853,
"compress_seconds": 5.343295082999987,
"decompress_and_hash_seconds": 2.978743083000012
}
]
}
]
}
71 changes: 71 additions & 0 deletions .github/scripts/__tests__/prepare-rust-cache.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import assert from 'node:assert/strict';
import { test } from 'node:test';

import { prepareRustCache } from '../../actions/setup-rust/prepare-cache.mjs';

const active = 'nightly-2026-08-02-x86_64-unknown-linux-gnu';

function fixture(installed, env = {}) {
const commands = [];
const paths = prepareRustCache({
env,
home: '/home/runner',
run(args) {
commands.push(args);
if (args[0] === 'show') {
return `${active} (overridden by '/workspace/rust-toolchain.toml')`;
}
if (args[1] === 'list') {
return installed.join('\n');
}
return '';
},
});
return { commands, paths };
}

test('keeps the pinned compiler and removes unused runner toolchains', () => {
const extra = ['stable-x86_64-unknown-linux-gnu', '1.99.0-x86_64-unknown-linux-gnu'];
const { commands } = fixture([...extra, active]);
assert.deepEqual(commands.slice(2), [
['default', active],
...extra.map((toolchain) => ['toolchain', 'uninstall', toolchain]),
]);
});

test('does not uninstall a toolchain when only the active one is installed', () => {
const { commands } = fixture([active]);
assert.deepEqual(commands.slice(2), [['default', active]]);
});

test('unset and explicit default paths produce the same cache environment', () => {
const implicit = fixture([active]);
const explicit = fixture([active], {
CARGO_HOME: '/home/runner/.cargo',
RUSTUP_HOME: '/home/runner/.rustup',
});
assert.deepEqual(implicit.paths, explicit.paths);
});

test('preserves custom Cargo and Rustup paths', () => {
const paths = {
CARGO_HOME: 'D:\\Dev Drive\\.cargo',
RUSTUP_HOME: 'D:\\Dev Drive\\.rustup',
};
assert.deepEqual(fixture([active], paths).paths, paths);
});

test('fails before changing toolchains when the active compiler is missing', () => {
const commands = [];
assert.throws(
() =>
prepareRustCache({
run(args) {
commands.push(args);
return args[0] === 'show' ? active : 'stable-x86_64-unknown-linux-gnu';
},
}),
/must be installed/,
);
assert.equal(commands.length, 2);
});
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,9 @@ jobs:
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
- uses: ./.github/actions/clone

- name: Test Rust cache helpers
run: node --test .github/scripts/__tests__/*rust-cache*.mjs

- uses: ./.github/actions/setup-ci-node

- uses: ./.github/actions/setup-rust
Expand Down
Loading