Skip to content

Commit 5e4a767

Browse files
authored
Consider all installed toolchains in cache key (#293)
1 parent 0aa729b commit 5e4a767

File tree

4 files changed

+163
-55
lines changed

4 files changed

+163
-55
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,8 @@ This cache is automatically keyed by:
143143

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

dist/restore/index.js

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -149504,6 +149504,8 @@ var external_crypto_default = /*#__PURE__*/__nccwpck_require__.n(external_crypto
149504149504
// EXTERNAL MODULE: external "fs/promises"
149505149505
var promises_ = __nccwpck_require__(91943);
149506149506
var promises_default = /*#__PURE__*/__nccwpck_require__.n(promises_);
149507+
;// CONCATENATED MODULE: external "stream/promises"
149508+
const external_stream_promises_namespaceObject = require("stream/promises");
149507149509
// EXTERNAL MODULE: external "os"
149508149510
var external_os_ = __nccwpck_require__(70857);
149509149511
var external_os_default = /*#__PURE__*/__nccwpck_require__.n(external_os_);
@@ -150783,6 +150785,7 @@ class Workspace {
150783150785

150784150786

150785150787

150788+
150786150789
const HOME = external_os_default().homedir();
150787150790
const config_CARGO_HOME = process.env.CARGO_HOME || external_path_default().join(HOME, ".cargo");
150788150791
const STATE_CONFIG = "RUST_CACHE_CONFIG";
@@ -150806,7 +150809,7 @@ class CacheConfig {
150806150809
/** The prefix portion of the cache key */
150807150810
this.keyPrefix = "";
150808150811
/** The rust version considered for the cache key */
150809-
this.keyRust = "";
150812+
this.keyRust = [];
150810150813
/** The environment variables considered for the cache key */
150811150814
this.keyEnvs = [];
150812150815
/** The files considered for the cache key */
@@ -150860,12 +150863,15 @@ class CacheConfig {
150860150863
// The env vars are sorted, matched by prefix and hashed into the
150861150864
// resulting environment hash.
150862150865
let hasher = external_crypto_default().createHash("sha1");
150863-
const rustVersion = await getRustVersion(cmdFormat);
150864-
let keyRust = `${rustVersion.release} ${rustVersion.host}`;
150865-
hasher.update(keyRust);
150866-
hasher.update(rustVersion["commit-hash"]);
150867-
keyRust += ` (${rustVersion["commit-hash"]})`;
150868-
self.keyRust = keyRust;
150866+
const rustVersions = Array.from(await getRustVersions(cmdFormat));
150867+
// Doesn't matter how they're sorted, just as long as it's deterministic.
150868+
rustVersions.sort();
150869+
for (const rustVersion of rustVersions) {
150870+
const { release, host, "commit-hash": commitHash } = rustVersion;
150871+
const keyRust = `${release} ${host} ${commitHash}`;
150872+
hasher.update(keyRust);
150873+
self.keyRust.push(keyRust);
150874+
}
150869150875
// these prefixes should cover most of the compiler / rust / cargo keys
150870150876
const envPrefixes = ["CARGO", "CC", "CFLAGS", "CXX", "CMAKE", "RUST"];
150871150877
envPrefixes.push(...lib_core.getInput("env-vars").split(/\s+/).filter(Boolean));
@@ -150980,9 +150986,7 @@ class CacheConfig {
150980150986
}
150981150987
keyFiles = sort_and_uniq(keyFiles);
150982150988
for (const file of keyFiles) {
150983-
for await (const chunk of external_fs_default().createReadStream(file)) {
150984-
hasher.update(chunk);
150985-
}
150989+
await (0,external_stream_promises_namespaceObject.pipeline)((0,external_fs_.createReadStream)(file), hasher);
150986150990
}
150987150991
keyFiles.push(...parsedKeyFiles);
150988150992
self.keyFiles = sort_and_uniq(keyFiles);
@@ -151051,7 +151055,10 @@ class CacheConfig {
151051151055
lib_core.info(`.. Prefix:`);
151052151056
lib_core.info(` - ${this.keyPrefix}`);
151053151057
lib_core.info(`.. Environment considered:`);
151054-
lib_core.info(` - Rust Version: ${this.keyRust}`);
151058+
lib_core.info(` - Rust Versions:`);
151059+
for (const rust of this.keyRust) {
151060+
lib_core.info(` - ${rust}`);
151061+
}
151055151062
for (const env of this.keyEnvs) {
151056151063
lib_core.info(` - ${env}`);
151057151064
}
@@ -151086,9 +151093,31 @@ function isCacheUpToDate() {
151086151093
function digest(hasher) {
151087151094
return hasher.digest("hex").substring(0, HASH_LENGTH);
151088151095
}
151089-
async function getRustVersion(cmdFormat) {
151090-
const stdout = await getCmdOutput(cmdFormat, "rustc -vV");
151091-
let splits = stdout
151096+
async function getRustVersions(cmdFormat) {
151097+
const versions = new Set();
151098+
versions.add(parseRustVersion(await getCmdOutput(cmdFormat, "rustc -vV")));
151099+
const stdout = await (async () => {
151100+
try {
151101+
return await getCmdOutput(cmdFormat, "rustup toolchain list --quiet");
151102+
}
151103+
catch (e) {
151104+
lib_core.warning(`Error running rustup toolchain list, falling back to default toolchain only: ${e}`);
151105+
return undefined;
151106+
}
151107+
})();
151108+
if (stdout !== undefined) {
151109+
for (const toolchain of stdout.split(/[\n\r]+/)) {
151110+
const trimmed = toolchain.trim();
151111+
if (!trimmed) {
151112+
continue;
151113+
}
151114+
versions.add(parseRustVersion(await getCmdOutput(cmdFormat, `rustup run ${toolchain} rustc -vV`)));
151115+
}
151116+
}
151117+
return versions;
151118+
}
151119+
function parseRustVersion(stdout) {
151120+
const splits = stdout
151092151121
.split(/[\n\r]+/)
151093151122
.filter(Boolean)
151094151123
.map((s) => s.split(":").map((s) => s.trim()))
@@ -151099,10 +151128,17 @@ async function globFiles(pattern) {
151099151128
const globber = await glob.create(pattern, {
151100151129
followSymbolicLinks: false,
151101151130
});
151102-
// fs.statSync resolve the symbolic link and returns stat for the
151131+
// fs.stat resolve the symbolic link and returns stat for the
151103151132
// file it pointed to, so isFile would make sure the resolved
151104151133
// file is actually a regular file.
151105-
return (await globber.glob()).filter((file) => external_fs_default().statSync(file).isFile());
151134+
const files = [];
151135+
for (const file of await globber.glob()) {
151136+
const stats = await promises_default().stat(file);
151137+
if (stats.isFile()) {
151138+
files.push(file);
151139+
}
151140+
}
151141+
return files;
151106151142
}
151107151143
function sort_and_uniq(a) {
151108151144
return a

dist/save/index.js

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -149506,6 +149506,8 @@ var external_crypto_default = /*#__PURE__*/__nccwpck_require__.n(external_crypto
149506149506
// EXTERNAL MODULE: external "fs/promises"
149507149507
var promises_ = __nccwpck_require__(91943);
149508149508
var promises_default = /*#__PURE__*/__nccwpck_require__.n(promises_);
149509+
;// CONCATENATED MODULE: external "stream/promises"
149510+
const external_stream_promises_namespaceObject = require("stream/promises");
149509149511
// EXTERNAL MODULE: external "os"
149510149512
var external_os_ = __nccwpck_require__(70857);
149511149513
var external_os_default = /*#__PURE__*/__nccwpck_require__.n(external_os_);
@@ -150783,6 +150785,7 @@ class Workspace {
150783150785

150784150786

150785150787

150788+
150786150789
const HOME = external_os_default().homedir();
150787150790
const CARGO_HOME = process.env.CARGO_HOME || external_path_default().join(HOME, ".cargo");
150788150791
const STATE_CONFIG = "RUST_CACHE_CONFIG";
@@ -150806,7 +150809,7 @@ class CacheConfig {
150806150809
/** The prefix portion of the cache key */
150807150810
this.keyPrefix = "";
150808150811
/** The rust version considered for the cache key */
150809-
this.keyRust = "";
150812+
this.keyRust = [];
150810150813
/** The environment variables considered for the cache key */
150811150814
this.keyEnvs = [];
150812150815
/** The files considered for the cache key */
@@ -150860,12 +150863,15 @@ class CacheConfig {
150860150863
// The env vars are sorted, matched by prefix and hashed into the
150861150864
// resulting environment hash.
150862150865
let hasher = external_crypto_default().createHash("sha1");
150863-
const rustVersion = await getRustVersion(cmdFormat);
150864-
let keyRust = `${rustVersion.release} ${rustVersion.host}`;
150865-
hasher.update(keyRust);
150866-
hasher.update(rustVersion["commit-hash"]);
150867-
keyRust += ` (${rustVersion["commit-hash"]})`;
150868-
self.keyRust = keyRust;
150866+
const rustVersions = Array.from(await getRustVersions(cmdFormat));
150867+
// Doesn't matter how they're sorted, just as long as it's deterministic.
150868+
rustVersions.sort();
150869+
for (const rustVersion of rustVersions) {
150870+
const { release, host, "commit-hash": commitHash } = rustVersion;
150871+
const keyRust = `${release} ${host} ${commitHash}`;
150872+
hasher.update(keyRust);
150873+
self.keyRust.push(keyRust);
150874+
}
150869150875
// these prefixes should cover most of the compiler / rust / cargo keys
150870150876
const envPrefixes = ["CARGO", "CC", "CFLAGS", "CXX", "CMAKE", "RUST"];
150871150877
envPrefixes.push(...core.getInput("env-vars").split(/\s+/).filter(Boolean));
@@ -150980,9 +150986,7 @@ class CacheConfig {
150980150986
}
150981150987
keyFiles = sort_and_uniq(keyFiles);
150982150988
for (const file of keyFiles) {
150983-
for await (const chunk of external_fs_default().createReadStream(file)) {
150984-
hasher.update(chunk);
150985-
}
150989+
await (0,external_stream_promises_namespaceObject.pipeline)((0,external_fs_.createReadStream)(file), hasher);
150986150990
}
150987150991
keyFiles.push(...parsedKeyFiles);
150988150992
self.keyFiles = sort_and_uniq(keyFiles);
@@ -151051,7 +151055,10 @@ class CacheConfig {
151051151055
core.info(`.. Prefix:`);
151052151056
core.info(` - ${this.keyPrefix}`);
151053151057
core.info(`.. Environment considered:`);
151054-
core.info(` - Rust Version: ${this.keyRust}`);
151058+
core.info(` - Rust Versions:`);
151059+
for (const rust of this.keyRust) {
151060+
core.info(` - ${rust}`);
151061+
}
151055151062
for (const env of this.keyEnvs) {
151056151063
core.info(` - ${env}`);
151057151064
}
@@ -151086,9 +151093,31 @@ function isCacheUpToDate() {
151086151093
function digest(hasher) {
151087151094
return hasher.digest("hex").substring(0, HASH_LENGTH);
151088151095
}
151089-
async function getRustVersion(cmdFormat) {
151090-
const stdout = await getCmdOutput(cmdFormat, "rustc -vV");
151091-
let splits = stdout
151096+
async function getRustVersions(cmdFormat) {
151097+
const versions = new Set();
151098+
versions.add(parseRustVersion(await getCmdOutput(cmdFormat, "rustc -vV")));
151099+
const stdout = await (async () => {
151100+
try {
151101+
return await getCmdOutput(cmdFormat, "rustup toolchain list --quiet");
151102+
}
151103+
catch (e) {
151104+
core.warning(`Error running rustup toolchain list, falling back to default toolchain only: ${e}`);
151105+
return undefined;
151106+
}
151107+
})();
151108+
if (stdout !== undefined) {
151109+
for (const toolchain of stdout.split(/[\n\r]+/)) {
151110+
const trimmed = toolchain.trim();
151111+
if (!trimmed) {
151112+
continue;
151113+
}
151114+
versions.add(parseRustVersion(await getCmdOutput(cmdFormat, `rustup run ${toolchain} rustc -vV`)));
151115+
}
151116+
}
151117+
return versions;
151118+
}
151119+
function parseRustVersion(stdout) {
151120+
const splits = stdout
151092151121
.split(/[\n\r]+/)
151093151122
.filter(Boolean)
151094151123
.map((s) => s.split(":").map((s) => s.trim()))
@@ -151099,10 +151128,17 @@ async function globFiles(pattern) {
151099151128
const globber = await glob.create(pattern, {
151100151129
followSymbolicLinks: false,
151101151130
});
151102-
// fs.statSync resolve the symbolic link and returns stat for the
151131+
// fs.stat resolve the symbolic link and returns stat for the
151103151132
// file it pointed to, so isFile would make sure the resolved
151104151133
// file is actually a regular file.
151105-
return (await globber.glob()).filter((file) => external_fs_default().statSync(file).isFile());
151134+
const files = [];
151135+
for (const file of await globber.glob()) {
151136+
const stats = await promises_default().stat(file);
151137+
if (stats.isFile()) {
151138+
files.push(file);
151139+
}
151140+
}
151141+
return files;
151106151142
}
151107151143
function sort_and_uniq(a) {
151108151144
return a

0 commit comments

Comments
 (0)