Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cargo and rustup get deleted when saving cache #16

Open
Procrat opened this issue May 3, 2021 · 7 comments
Open

cargo and rustup get deleted when saving cache #16

Procrat opened this issue May 3, 2021 · 7 comments

Comments

@Procrat
Copy link

Procrat commented May 3, 2021

Since we switched to running on self-hosted runners, we noticed that some jobs failed because they couldn't find the cargo executable anymore. After some digging, we noticed that after a successful run with this action on the same machine, .cargo/bin was empty, which is normally where cargo and rustup are installed (when installing the rustup.rs way at least).

Looking through the code, it seems that .cargo/bin gets cleaned apart for the binaries it finds a matching crate for, which would end up removing cargo and rustup. Was this intentional? If so, should I be doing something differently?

@Swatinem
Copy link
Owner

Swatinem commented May 3, 2021

Yes that was intentional. Since .cargo/bin is saved in the cache as well, I cleared out all the not directly installed binaries from there.

Under the assumption that runners get a fresh snapshot every time they run, it was a safe thing to do.

@ErichDonGubler
Copy link

ErichDonGubler commented Sep 8, 2021

Under the assumption that runners get a fresh snapshot every time they run, it was a safe thing to do.

This is not a safe assumption in the case of self-hosted runners, I think? We at @NZXTCorp are interested in giving this action a try, but currently our self-hosted runners just call rustup show to force installation of overridden toolchain in our repos, This breaks on self-hosted runners because...well, rustup.exe is assumed to exist in the first place!

@Swatinem
Copy link
Owner

I think a reasonable workaround in that case is to move the files that are not supposed to be cached away, and back after saving the cache.
Or alternatively to use a dedicated folder just for the bin files that are supposed to be persisted in the cache, and move them to .cargo/bin on "startup".

@benjyw
Copy link
Contributor

benjyw commented Oct 12, 2022

@Swatinem thanks for this useful action! Would you be open to a PR that adds an option to not touch .cargo/bin? E.g., for the self-hosted runner case?

@fpoli
Copy link

fpoli commented Oct 31, 2022

Instead of an option to not touch .cargo/bin, I would consider modifying this action so that it temporarly moves the unwanted files away instead of removing them. The code is around here:

export async function cleanBin() {
const bins = await getCargoBins();
const oldBins = JSON.parse(core.getState(STATE_BINS));
for (const bin of oldBins) {
bins.delete(bin);
}
const dir = await fs.promises.opendir(path.join(CARGO_HOME, "bin"));
for await (const dirent of dir) {
if (dirent.isFile() && !bins.has(dirent.name)) {
await rm(dir.path, dirent);
}
}
}

@Swatinem
Copy link
Owner

I had the exact same idea:

  • temporarily move files out of the directory
  • persist the cache so it uploads only the currently existing files
  • move files back afterwards

I just never put in the effort to make that happen ;-) But feel free to contribute here. :-)

@stefnotch
Copy link

stefnotch commented Jan 9, 2024

Would it be possible to change the cache paths (

self.cachePaths = [CARGO_HOME];
) to be more granular, and to simply ignore the not relevant files inside the .cargo/bin folder?
With more granular paths, we should be able to get rid of all of those deletion commands

rust-cache/src/save.ts

Lines 49 to 69 in d30f114

try {
const crates = core.getInput("cache-all-crates").toLowerCase() || "false";
core.info(`... Cleaning cargo registry (cache-all-crates: ${crates}) ...`);
await cleanRegistry(allPackages, crates !== "true");
} catch (e) {
core.debug(`${(e as any).stack}`);
}
try {
core.info(`... Cleaning cargo/bin ...`);
await cleanBin(config.cargoBins);
} catch (e) {
core.debug(`${(e as any).stack}`);
}
try {
core.info(`... Cleaning cargo git cache ...`);
await cleanGit(allPackages);
} catch (e) {
core.debug(`${(e as any).stack}`);
}

Or is there anything I'm overlooking?

Okay, so looking at it a bit more, which this approach one would have to

  • Start by reading the files in .cargo/bin and note down their timestamps
  • Run the build
  • Read the files in .cargo/bin again, and only cache the new ones

And probably also deal with the registry and git folders.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants