Consider all installed toolchains in cache key

This commit is contained in:
Tamir Duberstein 2025-12-09 11:01:11 -05:00
parent 230365fb7a
commit b13636f54b
No known key found for this signature in database
4 changed files with 121 additions and 35 deletions

View File

@ -143,7 +143,8 @@ This cache is automatically keyed by:
- the github [`job_id`](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_id) - the github [`job_id`](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_id)
(if `add-job-id-key` is `"true"`), (if `add-job-id-key` is `"true"`),
- the rustc release / host / hash, - the rustc release / host / hash (for all installed toolchains when
available),
- the following values, if `add-rust-environment-hash-key` is `"true"`: - the following values, if `add-rust-environment-hash-key` is `"true"`:
- the value of some compiler-specific environment variables (eg. RUSTFLAGS, etc), and - the value of some compiler-specific environment variables (eg. RUSTFLAGS, etc), and
- a hash of all `Cargo.lock` / `Cargo.toml` files found anywhere in the repository (if present). - a hash of all `Cargo.lock` / `Cargo.toml` files found anywhere in the repository (if present).

50
dist/restore/index.js vendored
View File

@ -150809,7 +150809,7 @@ class CacheConfig {
/** The prefix portion of the cache key */ /** The prefix portion of the cache key */
this.keyPrefix = ""; this.keyPrefix = "";
/** The rust version considered for the cache key */ /** The rust version considered for the cache key */
this.keyRust = ""; this.keyRust = [];
/** The environment variables considered for the cache key */ /** The environment variables considered for the cache key */
this.keyEnvs = []; this.keyEnvs = [];
/** The files considered for the cache key */ /** The files considered for the cache key */
@ -150863,12 +150863,15 @@ class CacheConfig {
// The env vars are sorted, matched by prefix and hashed into the // The env vars are sorted, matched by prefix and hashed into the
// resulting environment hash. // resulting environment hash.
let hasher = external_crypto_default().createHash("sha1"); let hasher = external_crypto_default().createHash("sha1");
const rustVersion = await getRustVersion(cmdFormat); const rustVersions = Array.from(await getRustVersions(cmdFormat));
let keyRust = `${rustVersion.release} ${rustVersion.host}`; // Doesn't matter how they're sorted, just as long as it's deterministic.
hasher.update(keyRust); rustVersions.sort();
hasher.update(rustVersion["commit-hash"]); for (const rustVersion of rustVersions) {
keyRust += ` (${rustVersion["commit-hash"]})`; const { release, host, "commit-hash": commitHash } = rustVersion;
self.keyRust = keyRust; const keyRust = `${release} ${host} ${commitHash}`;
hasher.update(keyRust);
self.keyRust.push(keyRust);
}
// these prefixes should cover most of the compiler / rust / cargo keys // these prefixes should cover most of the compiler / rust / cargo keys
const envPrefixes = ["CARGO", "CC", "CFLAGS", "CXX", "CMAKE", "RUST"]; const envPrefixes = ["CARGO", "CC", "CFLAGS", "CXX", "CMAKE", "RUST"];
envPrefixes.push(...lib_core.getInput("env-vars").split(/\s+/).filter(Boolean)); envPrefixes.push(...lib_core.getInput("env-vars").split(/\s+/).filter(Boolean));
@ -151052,7 +151055,10 @@ class CacheConfig {
lib_core.info(`.. Prefix:`); lib_core.info(`.. Prefix:`);
lib_core.info(` - ${this.keyPrefix}`); lib_core.info(` - ${this.keyPrefix}`);
lib_core.info(`.. Environment considered:`); lib_core.info(`.. Environment considered:`);
lib_core.info(` - Rust Version: ${this.keyRust}`); lib_core.info(` - Rust Versions:`);
for (const rust of this.keyRust) {
lib_core.info(` - ${rust}`);
}
for (const env of this.keyEnvs) { for (const env of this.keyEnvs) {
lib_core.info(` - ${env}`); lib_core.info(` - ${env}`);
} }
@ -151087,9 +151093,31 @@ function isCacheUpToDate() {
function digest(hasher) { function digest(hasher) {
return hasher.digest("hex").substring(0, HASH_LENGTH); return hasher.digest("hex").substring(0, HASH_LENGTH);
} }
async function getRustVersion(cmdFormat) { async function getRustVersions(cmdFormat) {
const stdout = await getCmdOutput(cmdFormat, "rustc -vV"); const versions = new Set();
let splits = stdout versions.add(parseRustVersion(await getCmdOutput(cmdFormat, "rustc -vV")));
const stdout = await (async () => {
try {
return await getCmdOutput(cmdFormat, "rustup toolchain list --quiet");
}
catch (e) {
lib_core.warning(`Error running rustup toolchain list, falling back to default toolchain only: ${e}`);
return undefined;
}
})();
if (stdout !== undefined) {
for (const toolchain of stdout.split(/[\n\r]+/)) {
const trimmed = toolchain.trim();
if (!trimmed) {
continue;
}
versions.add(parseRustVersion(await getCmdOutput(cmdFormat, `rustup run ${toolchain} rustc -vV`)));
}
}
return versions;
}
function parseRustVersion(stdout) {
const splits = stdout
.split(/[\n\r]+/) .split(/[\n\r]+/)
.filter(Boolean) .filter(Boolean)
.map((s) => s.split(":").map((s) => s.trim())) .map((s) => s.split(":").map((s) => s.trim()))

50
dist/save/index.js vendored
View File

@ -150809,7 +150809,7 @@ class CacheConfig {
/** The prefix portion of the cache key */ /** The prefix portion of the cache key */
this.keyPrefix = ""; this.keyPrefix = "";
/** The rust version considered for the cache key */ /** The rust version considered for the cache key */
this.keyRust = ""; this.keyRust = [];
/** The environment variables considered for the cache key */ /** The environment variables considered for the cache key */
this.keyEnvs = []; this.keyEnvs = [];
/** The files considered for the cache key */ /** The files considered for the cache key */
@ -150863,12 +150863,15 @@ class CacheConfig {
// The env vars are sorted, matched by prefix and hashed into the // The env vars are sorted, matched by prefix and hashed into the
// resulting environment hash. // resulting environment hash.
let hasher = external_crypto_default().createHash("sha1"); let hasher = external_crypto_default().createHash("sha1");
const rustVersion = await getRustVersion(cmdFormat); const rustVersions = Array.from(await getRustVersions(cmdFormat));
let keyRust = `${rustVersion.release} ${rustVersion.host}`; // Doesn't matter how they're sorted, just as long as it's deterministic.
hasher.update(keyRust); rustVersions.sort();
hasher.update(rustVersion["commit-hash"]); for (const rustVersion of rustVersions) {
keyRust += ` (${rustVersion["commit-hash"]})`; const { release, host, "commit-hash": commitHash } = rustVersion;
self.keyRust = keyRust; const keyRust = `${release} ${host} ${commitHash}`;
hasher.update(keyRust);
self.keyRust.push(keyRust);
}
// these prefixes should cover most of the compiler / rust / cargo keys // these prefixes should cover most of the compiler / rust / cargo keys
const envPrefixes = ["CARGO", "CC", "CFLAGS", "CXX", "CMAKE", "RUST"]; const envPrefixes = ["CARGO", "CC", "CFLAGS", "CXX", "CMAKE", "RUST"];
envPrefixes.push(...core.getInput("env-vars").split(/\s+/).filter(Boolean)); envPrefixes.push(...core.getInput("env-vars").split(/\s+/).filter(Boolean));
@ -151052,7 +151055,10 @@ class CacheConfig {
core.info(`.. Prefix:`); core.info(`.. Prefix:`);
core.info(` - ${this.keyPrefix}`); core.info(` - ${this.keyPrefix}`);
core.info(`.. Environment considered:`); core.info(`.. Environment considered:`);
core.info(` - Rust Version: ${this.keyRust}`); core.info(` - Rust Versions:`);
for (const rust of this.keyRust) {
core.info(` - ${rust}`);
}
for (const env of this.keyEnvs) { for (const env of this.keyEnvs) {
core.info(` - ${env}`); core.info(` - ${env}`);
} }
@ -151087,9 +151093,31 @@ function isCacheUpToDate() {
function digest(hasher) { function digest(hasher) {
return hasher.digest("hex").substring(0, HASH_LENGTH); return hasher.digest("hex").substring(0, HASH_LENGTH);
} }
async function getRustVersion(cmdFormat) { async function getRustVersions(cmdFormat) {
const stdout = await getCmdOutput(cmdFormat, "rustc -vV"); const versions = new Set();
let splits = stdout versions.add(parseRustVersion(await getCmdOutput(cmdFormat, "rustc -vV")));
const stdout = await (async () => {
try {
return await getCmdOutput(cmdFormat, "rustup toolchain list --quiet");
}
catch (e) {
core.warning(`Error running rustup toolchain list, falling back to default toolchain only: ${e}`);
return undefined;
}
})();
if (stdout !== undefined) {
for (const toolchain of stdout.split(/[\n\r]+/)) {
const trimmed = toolchain.trim();
if (!trimmed) {
continue;
}
versions.add(parseRustVersion(await getCmdOutput(cmdFormat, `rustup run ${toolchain} rustc -vV`)));
}
}
return versions;
}
function parseRustVersion(stdout) {
const splits = stdout
.split(/[\n\r]+/) .split(/[\n\r]+/)
.filter(Boolean) .filter(Boolean)
.map((s) => s.split(":").map((s) => s.trim())) .map((s) => s.split(":").map((s) => s.trim()))

View File

@ -41,7 +41,7 @@ export class CacheConfig {
/** The prefix portion of the cache key */ /** The prefix portion of the cache key */
private keyPrefix = ""; private keyPrefix = "";
/** The rust version considered for the cache key */ /** The rust version considered for the cache key */
private keyRust = ""; private keyRust: Array<string> = [];
/** The environment variables considered for the cache key */ /** The environment variables considered for the cache key */
private keyEnvs: Array<string> = []; private keyEnvs: Array<string> = [];
/** The files considered for the cache key */ /** The files considered for the cache key */
@ -104,14 +104,16 @@ export class CacheConfig {
// resulting environment hash. // resulting environment hash.
let hasher = crypto.createHash("sha1"); let hasher = crypto.createHash("sha1");
const rustVersion = await getRustVersion(cmdFormat); const rustVersions = Array.from(await getRustVersions(cmdFormat));
// Doesn't matter how they're sorted, just as long as it's deterministic.
rustVersions.sort();
let keyRust = `${rustVersion.release} ${rustVersion.host}`; for (const rustVersion of rustVersions) {
hasher.update(keyRust); const { release, host, "commit-hash": commitHash } = rustVersion;
hasher.update(rustVersion["commit-hash"]); const keyRust = `${release} ${host} ${commitHash}`;
hasher.update(keyRust);
keyRust += ` (${rustVersion["commit-hash"]})`; self.keyRust.push(keyRust);
self.keyRust = keyRust; }
// these prefixes should cover most of the compiler / rust / cargo keys // these prefixes should cover most of the compiler / rust / cargo keys
const envPrefixes = ["CARGO", "CC", "CFLAGS", "CXX", "CMAKE", "RUST"]; const envPrefixes = ["CARGO", "CC", "CFLAGS", "CXX", "CMAKE", "RUST"];
@ -334,7 +336,10 @@ export class CacheConfig {
core.info(`.. Prefix:`); core.info(`.. Prefix:`);
core.info(` - ${this.keyPrefix}`); core.info(` - ${this.keyPrefix}`);
core.info(`.. Environment considered:`); core.info(`.. Environment considered:`);
core.info(` - Rust Version: ${this.keyRust}`); core.info(` - Rust Versions:`);
for (const rust of this.keyRust) {
core.info(` - ${rust}`);
}
for (const env of this.keyEnvs) { for (const env of this.keyEnvs) {
core.info(` - ${env}`); core.info(` - ${env}`);
} }
@ -379,9 +384,33 @@ interface RustVersion {
"commit-hash": string; "commit-hash": string;
} }
async function getRustVersion(cmdFormat: string): Promise<RustVersion> { async function getRustVersions(cmdFormat: string): Promise<Set<RustVersion>> {
const stdout = await getCmdOutput(cmdFormat, "rustc -vV"); const versions = new Set<RustVersion>();
let splits = stdout
versions.add(parseRustVersion(await getCmdOutput(cmdFormat, "rustc -vV")));
const stdout = await (async () => {
try {
return await getCmdOutput(cmdFormat, "rustup toolchain list --quiet");
} catch (e) {
core.warning(`Error running rustup toolchain list, falling back to default toolchain only: ${e}`);
return undefined;
}
})();
if (stdout !== undefined) {
for (const toolchain of stdout.split(/[\n\r]+/)) {
const trimmed = toolchain.trim();
if (!trimmed) {
continue;
}
versions.add(parseRustVersion(await getCmdOutput(cmdFormat, `rustup run ${toolchain} rustc -vV`)));
}
}
return versions;
}
function parseRustVersion(stdout: string): RustVersion {
const splits = stdout
.split(/[\n\r]+/) .split(/[\n\r]+/)
.filter(Boolean) .filter(Boolean)
.map((s) => s.split(":").map((s) => s.trim())) .map((s) => s.split(":").map((s) => s.trim()))