Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
33 changes: 33 additions & 0 deletions .github/workflows/nix.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: nix

on: [push, pull_request]

permissions: {}

jobs:
nix:
if: github.repository == 'Swatinem/rust-cache'
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]

name: Test Nix on ${{ matrix.os }}
runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false

- uses: cachix/install-nix-action@0b0e072294b088b73964f1d72dfdac0951439dbd # v31.8.4

- uses: ./
with:
workspaces: tests
cmd-format: nix develop ./tests -c {0}

- run: |
nix develop -c cargo check --color always
nix develop -c cargo test --color always
working-directory: tests
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ sensible defaults.
# Determines whether to cache the ~/.cargo/bin directory.
# default: "true"
cache-bin: ""

# A format string used to format commands to be run, i.e. `rustc` and `cargo`.
# Must contain exactly one occurance of `{0}`, which is the formatting fragment
# that will be replaced with the `rustc` or `cargo` command. This is necessary
# when using Nix or other setup that requires running these commands within a
# specific shell, otherwise the system `rustc` and `cargo` will be run.
# default: "{0}"
cmd-format: ""
# To run within a Nix shell (using the default dev shell of a flake in the repo root):
cmd-format: nix develop -c {0}
```

Further examples are available in the [.github/workflows](./.github/workflows/) directory.
Expand Down
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ inputs:
description: "Check if a cache entry exists without downloading the cache"
required: false
default: "false"
cmd-format:
description: "A format string used to format commands to be run, i.e. `rustc` and `cargo`."
required: false
default: "{0}"
outputs:
cache-hit:
description: "A boolean value that indicates an exact match was found."
Expand Down
41 changes: 28 additions & 13 deletions dist/restore/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -150675,11 +150675,12 @@ function reportError(e) {
lib_core.error(`${e.stack}`);
}
}
async function getCmdOutput(cmd, args = [], options = {}) {
async function getCmdOutput(cmdFormat, cmd, options = {}) {
cmd = cmdFormat.replace("{0}", cmd);
let stdout = "";
let stderr = "";
try {
await exec.exec(cmd, args, {
await exec.exec(cmd, [], {
silent: true,
listeners: {
stdout(data) {
Expand All @@ -150694,7 +150695,7 @@ async function getCmdOutput(cmd, args = [], options = {}) {
}
catch (e) {
e.commandFailed = {
command: `${cmd} ${args.join(" ")}`,
command: cmd,
stderr,
};
throw e;
Expand Down Expand Up @@ -150742,11 +150743,12 @@ class Workspace {
this.root = root;
this.target = target;
}
async getPackages(filter, ...extraArgs) {
async getPackages(cmdFormat, filter, extraArgs) {
const cmd = "cargo metadata --all-features --format-version 1" + (extraArgs ? ` ${extraArgs}` : "");
let packages = [];
try {
lib_core.debug(`collecting metadata for "${this.root}"`);
const meta = JSON.parse(await getCmdOutput("cargo", ["metadata", "--all-features", "--format-version", "1", ...extraArgs], {
const meta = JSON.parse(await getCmdOutput(cmdFormat, cmd, {
cwd: this.root,
env: { ...process.env, "CARGO_ENCODED_RUSTFLAGS": "" },
}));
Expand All @@ -150761,11 +150763,11 @@ class Workspace {
}
return packages;
}
async getPackagesOutsideWorkspaceRoot() {
return await this.getPackages((pkg) => !pkg.manifest_path.startsWith(this.root));
async getPackagesOutsideWorkspaceRoot(cmdFormat) {
return await this.getPackages(cmdFormat, (pkg) => !pkg.manifest_path.startsWith(this.root));
}
async getWorkspaceMembers() {
return await this.getPackages((_) => true, "--no-deps");
async getWorkspaceMembers(cmdFormat) {
return await this.getPackages(cmdFormat, (_) => true, "--no-deps");
}
}

Expand All @@ -150787,6 +150789,8 @@ const STATE_CONFIG = "RUST_CACHE_CONFIG";
const HASH_LENGTH = 8;
class CacheConfig {
constructor() {
/** A format string for running commands */
this.cmdFormat = "";
/** All the paths we want to cache */
this.cachePaths = [];
/** The primary cache key */
Expand Down Expand Up @@ -150815,6 +150819,17 @@ class CacheConfig {
*/
static async new() {
const self = new CacheConfig();
let cmdFormat = lib_core.getInput("cmd-format");
if (cmdFormat) {
const placeholderMatches = cmdFormat.match(/\{0\}/g);
if (!placeholderMatches || placeholderMatches.length !== 1) {
cmdFormat = "{0}";
}
}
else {
cmdFormat = "{0}";
}
self.cmdFormat = cmdFormat;
// Construct key prefix:
// This uses either the `shared-key` input,
// or the `key` input combined with the `job` key.
Expand Down Expand Up @@ -150845,7 +150860,7 @@ class CacheConfig {
// The env vars are sorted, matched by prefix and hashed into the
// resulting environment hash.
let hasher = external_crypto_default().createHash("sha1");
const rustVersion = await getRustVersion();
const rustVersion = await getRustVersion(cmdFormat);
let keyRust = `${rustVersion.release} ${rustVersion.host}`;
hasher.update(keyRust);
hasher.update(rustVersion["commit-hash"]);
Expand Down Expand Up @@ -150895,7 +150910,7 @@ class CacheConfig {
for (const workspace of workspaces) {
const root = workspace.root;
keyFiles.push(...(await globFiles(`${root}/**/.cargo/config.toml\n${root}/**/rust-toolchain\n${root}/**/rust-toolchain.toml`)));
const workspaceMembers = await workspace.getWorkspaceMembers();
const workspaceMembers = await workspace.getWorkspaceMembers(cmdFormat);
const cargo_manifests = sort_and_uniq(workspaceMembers.map((member) => external_path_default().join(member.path, "Cargo.toml")));
for (const cargo_manifest of cargo_manifests) {
try {
Expand Down Expand Up @@ -151071,8 +151086,8 @@ function isCacheUpToDate() {
function digest(hasher) {
return hasher.digest("hex").substring(0, HASH_LENGTH);
}
async function getRustVersion() {
const stdout = await getCmdOutput("rustc", ["-vV"]);
async function getRustVersion(cmdFormat) {
const stdout = await getCmdOutput(cmdFormat, "rustc -vV");
let splits = stdout
.split(/[\n\r]+/)
.filter(Boolean)
Expand Down
45 changes: 30 additions & 15 deletions dist/save/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -150675,11 +150675,12 @@ function reportError(e) {
core.error(`${e.stack}`);
}
}
async function getCmdOutput(cmd, args = [], options = {}) {
async function getCmdOutput(cmdFormat, cmd, options = {}) {
cmd = cmdFormat.replace("{0}", cmd);
let stdout = "";
let stderr = "";
try {
await exec.exec(cmd, args, {
await exec.exec(cmd, [], {
silent: true,
listeners: {
stdout(data) {
Expand All @@ -150694,7 +150695,7 @@ async function getCmdOutput(cmd, args = [], options = {}) {
}
catch (e) {
e.commandFailed = {
command: `${cmd} ${args.join(" ")}`,
command: cmd,
stderr,
};
throw e;
Expand Down Expand Up @@ -150742,11 +150743,12 @@ class Workspace {
this.root = root;
this.target = target;
}
async getPackages(filter, ...extraArgs) {
async getPackages(cmdFormat, filter, extraArgs) {
const cmd = "cargo metadata --all-features --format-version 1" + (extraArgs ? ` ${extraArgs}` : "");
let packages = [];
try {
core.debug(`collecting metadata for "${this.root}"`);
const meta = JSON.parse(await getCmdOutput("cargo", ["metadata", "--all-features", "--format-version", "1", ...extraArgs], {
const meta = JSON.parse(await getCmdOutput(cmdFormat, cmd, {
cwd: this.root,
env: { ...process.env, "CARGO_ENCODED_RUSTFLAGS": "" },
}));
Expand All @@ -150761,11 +150763,11 @@ class Workspace {
}
return packages;
}
async getPackagesOutsideWorkspaceRoot() {
return await this.getPackages((pkg) => !pkg.manifest_path.startsWith(this.root));
async getPackagesOutsideWorkspaceRoot(cmdFormat) {
return await this.getPackages(cmdFormat, (pkg) => !pkg.manifest_path.startsWith(this.root));
}
async getWorkspaceMembers() {
return await this.getPackages((_) => true, "--no-deps");
async getWorkspaceMembers(cmdFormat) {
return await this.getPackages(cmdFormat, (_) => true, "--no-deps");
}
}

Expand All @@ -150787,6 +150789,8 @@ const STATE_CONFIG = "RUST_CACHE_CONFIG";
const HASH_LENGTH = 8;
class CacheConfig {
constructor() {
/** A format string for running commands */
this.cmdFormat = "";
/** All the paths we want to cache */
this.cachePaths = [];
/** The primary cache key */
Expand Down Expand Up @@ -150815,6 +150819,17 @@ class CacheConfig {
*/
static async new() {
const self = new CacheConfig();
let cmdFormat = core.getInput("cmd-format");
if (cmdFormat) {
const placeholderMatches = cmdFormat.match(/\{0\}/g);
if (!placeholderMatches || placeholderMatches.length !== 1) {
cmdFormat = "{0}";
}
}
else {
cmdFormat = "{0}";
}
self.cmdFormat = cmdFormat;
// Construct key prefix:
// This uses either the `shared-key` input,
// or the `key` input combined with the `job` key.
Expand Down Expand Up @@ -150845,7 +150860,7 @@ class CacheConfig {
// The env vars are sorted, matched by prefix and hashed into the
// resulting environment hash.
let hasher = external_crypto_default().createHash("sha1");
const rustVersion = await getRustVersion();
const rustVersion = await getRustVersion(cmdFormat);
let keyRust = `${rustVersion.release} ${rustVersion.host}`;
hasher.update(keyRust);
hasher.update(rustVersion["commit-hash"]);
Expand Down Expand Up @@ -150895,7 +150910,7 @@ class CacheConfig {
for (const workspace of workspaces) {
const root = workspace.root;
keyFiles.push(...(await globFiles(`${root}/**/.cargo/config.toml\n${root}/**/rust-toolchain\n${root}/**/rust-toolchain.toml`)));
const workspaceMembers = await workspace.getWorkspaceMembers();
const workspaceMembers = await workspace.getWorkspaceMembers(cmdFormat);
const cargo_manifests = sort_and_uniq(workspaceMembers.map((member) => external_path_default().join(member.path, "Cargo.toml")));
for (const cargo_manifest of cargo_manifests) {
try {
Expand Down Expand Up @@ -151071,8 +151086,8 @@ function isCacheUpToDate() {
function digest(hasher) {
return hasher.digest("hex").substring(0, HASH_LENGTH);
}
async function getRustVersion() {
const stdout = await getCmdOutput("rustc", ["-vV"]);
async function getRustVersion(cmdFormat) {
const stdout = await getCmdOutput(cmdFormat, "rustc -vV");
let splits = stdout
.split(/[\n\r]+/)
.filter(Boolean)
Expand Down Expand Up @@ -151428,9 +151443,9 @@ async function run() {
const workspaceCrates = core.getInput("cache-workspace-crates").toLowerCase() || "false";
const allPackages = [];
for (const workspace of config.workspaces) {
const packages = await workspace.getPackagesOutsideWorkspaceRoot();
const packages = await workspace.getPackagesOutsideWorkspaceRoot(config.cmdFormat);
if (workspaceCrates === "true") {
const wsMembers = await workspace.getWorkspaceMembers();
const wsMembers = await workspace.getWorkspaceMembers(config.cmdFormat);
packages.push(...wsMembers);
}
allPackages.push(...packages);
Expand Down
22 changes: 18 additions & 4 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ const STATE_CONFIG = "RUST_CACHE_CONFIG";
const HASH_LENGTH = 8;

export class CacheConfig {
/** A format string for running commands */
public cmdFormat: string = "";

/** All the paths we want to cache */
public cachePaths: Array<string> = [];
/** The primary cache key */
Expand Down Expand Up @@ -53,6 +56,17 @@ export class CacheConfig {
static async new(): Promise<CacheConfig> {
const self = new CacheConfig();

let cmdFormat = core.getInput("cmd-format");
if (cmdFormat) {
const placeholderMatches = cmdFormat.match(/\{0\}/g);
if (!placeholderMatches || placeholderMatches.length !== 1) {
cmdFormat = "{0}";
}
} else {
cmdFormat = "{0}";
}
self.cmdFormat = cmdFormat;

// Construct key prefix:
// This uses either the `shared-key` input,
// or the `key` input combined with the `job` key.
Expand Down Expand Up @@ -89,7 +103,7 @@ export class CacheConfig {
// resulting environment hash.

let hasher = crypto.createHash("sha1");
const rustVersion = await getRustVersion();
const rustVersion = await getRustVersion(cmdFormat);

let keyRust = `${rustVersion.release} ${rustVersion.host}`;
hasher.update(keyRust);
Expand Down Expand Up @@ -158,7 +172,7 @@ export class CacheConfig {
)),
);

const workspaceMembers = await workspace.getWorkspaceMembers();
const workspaceMembers = await workspace.getWorkspaceMembers(cmdFormat);

const cargo_manifests = sort_and_uniq(workspaceMembers.map((member) => path.join(member.path, "Cargo.toml")));

Expand Down Expand Up @@ -366,8 +380,8 @@ interface RustVersion {
"commit-hash": string;
}

async function getRustVersion(): Promise<RustVersion> {
const stdout = await getCmdOutput("rustc", ["-vV"]);
async function getRustVersion(cmdFormat: string): Promise<RustVersion> {
const stdout = await getCmdOutput(cmdFormat, "rustc -vV");
let splits = stdout
.split(/[\n\r]+/)
.filter(Boolean)
Expand Down
4 changes: 2 additions & 2 deletions src/save.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ async function run() {
const workspaceCrates = core.getInput("cache-workspace-crates").toLowerCase() || "false";
const allPackages = [];
for (const workspace of config.workspaces) {
const packages = await workspace.getPackagesOutsideWorkspaceRoot();
const packages = await workspace.getPackagesOutsideWorkspaceRoot(config.cmdFormat);
if (workspaceCrates === "true") {
const wsMembers = await workspace.getWorkspaceMembers();
const wsMembers = await workspace.getWorkspaceMembers(config.cmdFormat);
packages.push(...wsMembers);
}
allPackages.push(...packages);
Expand Down
7 changes: 4 additions & 3 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ export function reportError(e: any) {
}

export async function getCmdOutput(
cmdFormat: string,
cmd: string,
args: Array<string> = [],
options: exec.ExecOptions = {},
): Promise<string> {
cmd = cmdFormat.replace("{0}", cmd);
let stdout = "";
let stderr = "";
try {
await exec.exec(cmd, args, {
await exec.exec(cmd, [], {
silent: true,
listeners: {
stdout(data) {
Expand All @@ -37,7 +38,7 @@ export async function getCmdOutput(
});
} catch (e) {
(e as any).commandFailed = {
command: `${cmd} ${args.join(" ")}`,
command: cmd,
stderr,
};
throw e;
Expand Down
Loading
Loading