mirror of
https://github.com/Swatinem/rust-cache
synced 2025-04-05 05:04:07 +00:00
prepare v2
This commit is contained in:
parent
0497f9301f
commit
622616010e
2
.github/workflows/coverage.yml
vendored
2
.github/workflows/coverage.yml
vendored
|
@ -16,7 +16,7 @@ jobs:
|
|||
CARGO_TERM_COLOR: always
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- run: rustup toolchain install stable --profile minimal --component llvm-tools-preview
|
||||
|
||||
|
|
2
.github/workflows/install.yml
vendored
2
.github/workflows/install.yml
vendored
|
@ -16,7 +16,7 @@ jobs:
|
|||
CARGO_TERM_COLOR: always
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- run: rustup toolchain install stable --profile minimal
|
||||
|
||||
|
|
2
.github/workflows/simple.yml
vendored
2
.github/workflows/simple.yml
vendored
|
@ -16,7 +16,7 @@ jobs:
|
|||
CARGO_TERM_COLOR: always
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- run: rustup toolchain install stable --profile minimal
|
||||
|
||||
|
|
2
.github/workflows/sparse-registry.yml
vendored
2
.github/workflows/sparse-registry.yml
vendored
|
@ -17,7 +17,7 @@ jobs:
|
|||
CARGO_UNSTABLE_SPARSE_REGISTRY: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- run: |
|
||||
rustup toolchain install nightly --profile minimal
|
||||
|
|
2
.github/workflows/target-dir.yml
vendored
2
.github/workflows/target-dir.yml
vendored
|
@ -16,7 +16,7 @@ jobs:
|
|||
CARGO_TERM_COLOR: always
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- run: rustup toolchain install stable --profile minimal
|
||||
|
||||
|
|
2
.github/workflows/workspaces.yml
vendored
2
.github/workflows/workspaces.yml
vendored
|
@ -16,7 +16,7 @@ jobs:
|
|||
CARGO_TERM_COLOR: always
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- run: rustup toolchain install stable --profile minimal --target wasm32-unknown-unknown
|
||||
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
# Changelog
|
||||
|
||||
## 2.0.0
|
||||
|
||||
- The action code was refactored to allow for caching multiple workspaces and
|
||||
different `target` directory layouts.
|
||||
- The `working-directory` and `target-dir` input options were replaced by a
|
||||
single `workspaces` option that has the form of `$workspace -> $target`.
|
||||
- Support for considering `env-vars` as part of the cache key.
|
||||
- The `sharedKey` input option was renamed to `shared-key` for consistency.
|
||||
|
||||
## 1.4.0
|
||||
|
||||
- Clean both `debug` and `release` target directories.
|
||||
|
|
108
README.md
108
README.md
|
@ -6,43 +6,48 @@ sensible defaults.
|
|||
## Example usage
|
||||
|
||||
```yaml
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# selecting a toolchain either by action or manual `rustup` calls should happen
|
||||
# before the plugin, as it uses the current rustc version as its cache key
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
# before the plugin, as the cache uses the current rustc version as its cache key
|
||||
- run: rustup toolchain install stable --profile minimal
|
||||
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
# An explicit cache key that is used instead of the automatic `job`-based
|
||||
# cache key and is thus stable across jobs.
|
||||
# Default: empty
|
||||
shared-key: ""
|
||||
|
||||
# An additional cache key that is added alongside the automatic `job`-based
|
||||
# cache key and can be used to further differentiate jobs.
|
||||
# Default: empty
|
||||
key: ""
|
||||
|
||||
# A whitespace separated list of env-var *prefixes* who's value contributes
|
||||
# to the environment cache key.
|
||||
# The env-vars are matched by *prefix*, so the default `RUST` var will
|
||||
# match all of `RUSTC`, `RUSTUP_*`, `RUSTFLAGS`, `RUSTDOC_*`, etc.
|
||||
# Default: "CARGO CC CFLAGS CXX CMAKE RUST"
|
||||
env-vars: ""
|
||||
|
||||
# The cargo workspaces and target directory configuration.
|
||||
# These entries are separated by newlines and have the form
|
||||
# `$workspace -> $target`. The `$target` part is treated as a directory
|
||||
# relative to the `$workspace` and defaults to "target" if not explicitly given.
|
||||
# Default: ". -> target"
|
||||
workspaces: ""
|
||||
|
||||
# Determines if the cache should be saved even when the workflow has failed.
|
||||
# Default: "false"
|
||||
cache-on-failure: ""
|
||||
```
|
||||
|
||||
## Inputs
|
||||
|
||||
: `key`
|
||||
An optional key that is added to the automatic cache key.
|
||||
|
||||
: `sharedKey`
|
||||
An additional key that is stable over multiple jobs.
|
||||
|
||||
: `envVars`
|
||||
A space-separated list of regular expressions that define additional environment variable filters.
|
||||
These are added to an additional cache key that's generated from environment variable contents.
|
||||
|
||||
: `working-directory`
|
||||
The working directory the action operates in, is case the cargo project is not
|
||||
located in the repo root.
|
||||
|
||||
: `target-dir`
|
||||
The target directory that should be cleaned and persisted, defaults to `./target`.
|
||||
|
||||
: `cache-on-failure`
|
||||
Cache even if the build fails, defaults to false
|
||||
Further examples are available in the [.github/workflows][] directory.
|
||||
|
||||
## Outputs
|
||||
|
||||
: `cache-hit`
|
||||
**`cache-hit`**
|
||||
|
||||
This is a boolean flag that will be set to `true` when there was an exact cache hit.
|
||||
|
||||
|
@ -67,24 +72,21 @@ a more stable experience, please use a fixed revision or tag.
|
|||
|
||||
This action currently caches the following files/directories:
|
||||
|
||||
- `~/.cargo/bin`
|
||||
- `~/.cargo/registry/index`
|
||||
- `~/.cargo/registry/cache`
|
||||
- `~/.cargo/git`
|
||||
- `~/.cargo/.crates.toml`
|
||||
- `~/.cargo/.crates2.json`
|
||||
- `./target`
|
||||
- `~/.cargo` (installed binaries, the cargo registry, cache, and git dependencies)
|
||||
- `./target` (build artifacts of dependencies)
|
||||
|
||||
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 rustc release / host / hash, and
|
||||
- the rustc release / host / hash,
|
||||
- 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 `rust-toolchain` / `rust-toolchain.toml` files in the root of the repository (if present).
|
||||
|
||||
An additional input `key` can be provided if the builtin keys are not sufficient.
|
||||
|
||||
Before being persisted, the cache is cleaned of:
|
||||
|
||||
- Any files in `~/.cargo/bin` that were present before the action ran (for example `rustc`).
|
||||
- Dependencies that are no longer used.
|
||||
- Anything that is not a dependency.
|
||||
|
@ -103,13 +105,39 @@ to recreate it from the compressed crate archives in `~/.cargo/registry/cache`.
|
|||
The action will try to restore from a previous `Cargo.lock` version as well, so
|
||||
lockfile updates should only re-build changed dependencies.
|
||||
|
||||
The action invokes `cargo metadata` to determine the current set of dependencies.
|
||||
|
||||
Additionally, the action automatically works around
|
||||
[cargo#8603](https://github.com/rust-lang/cargo/issues/8603) /
|
||||
[actions/cache#403](https://github.com/actions/cache/issues/403) which would
|
||||
otherwise corrupt the cache on macOS builds.
|
||||
|
||||
## Cache Limits and Control
|
||||
|
||||
This specialized cache action is built on top of the upstream cache action
|
||||
maintained by GitHub. The same restrictions and limits apply, which are
|
||||
documented here:
|
||||
https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows
|
||||
|
||||
In particular, caches are currently limited to 10 GB in total and exceeding that
|
||||
limit will cause eviction of older caches.
|
||||
|
||||
Caches from base branches are available to PRs, but not across unrelated
|
||||
branches.
|
||||
|
||||
The caches can be controlled using the [Cache API](https://docs.github.com/en/rest/actions/cache)
|
||||
which allows listing existing caches and manually removing entries.
|
||||
|
||||
## Debugging
|
||||
|
||||
The action prints detailed information about which information it considers
|
||||
for its cache key, and it outputs more debug-only information about which
|
||||
cleanup steps it performs before persisting the cache.
|
||||
|
||||
You can read up on how to [enable debug logging](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/enabling-debug-logging)
|
||||
to see those details as well as further details related to caching operations.
|
||||
|
||||
## Known issues
|
||||
|
||||
- The cache cleaning process currently only runs against the build artifacts under
|
||||
`./target/debug/`, so projects using release or cross-compiled builds will experience
|
||||
larger cache sizes.
|
||||
- The cache cleaning process currently removes all the files from `~/.cargo/bin`
|
||||
that were present before the action ran (for example `rustc`).
|
||||
|
|
2
TODO.md
2
TODO.md
|
@ -1,4 +1,4 @@
|
|||
- Update readme with better docs ;-)
|
||||
- better .cargo/bin handling:
|
||||
- get a list of all the files on "pre"/"restore"
|
||||
- move the files out of the way on "post"/"save" and move them back afterwards
|
||||
- properly clean sparse registry
|
||||
|
|
10
action.yml
10
action.yml
|
@ -2,14 +2,14 @@ name: "Rust Cache"
|
|||
description: "A GitHub Action that implements smart caching for rust/cargo projects with sensible defaults."
|
||||
author: "Arpad Borsos <swatinem@swatinem.de>"
|
||||
inputs:
|
||||
shared-key:
|
||||
description: "An additional cache key that is stable over multiple jobs"
|
||||
required: false
|
||||
key:
|
||||
description: "An additional key for the cache"
|
||||
required: false
|
||||
sharedKey:
|
||||
description: "An additional cache key that is stable over multiple jobs"
|
||||
required: false
|
||||
envVars:
|
||||
description: "Additional environment variables to include in the cache key, separeted by spaces"
|
||||
env-vars:
|
||||
description: "Additional environment variables to include in the cache key, separated by spaces"
|
||||
required: false
|
||||
workspaces:
|
||||
description: "Paths to multiple Cargo workspaces and their target directories, separated by newlines"
|
||||
|
|
|
@ -31,8 +31,8 @@ export async function cleanTargetDir(targetDir: string, packages: Packages) {
|
|||
}
|
||||
|
||||
async function cleanProfileTarget(profileDir: string, packages: Packages) {
|
||||
await io.rmRF(path.join(profileDir, "examples"));
|
||||
await io.rmRF(path.join(profileDir, "incremental"));
|
||||
await rmRF(path.join(profileDir, "examples"));
|
||||
await rmRF(path.join(profileDir, "incremental"));
|
||||
|
||||
let dir: fs.Dir;
|
||||
// remove all *files* from the profile directory
|
||||
|
@ -94,8 +94,7 @@ export async function cleanBin() {
|
|||
export async function cleanRegistry(packages: Packages) {
|
||||
// `.cargo/registry/src`
|
||||
// we can remove this completely, as cargo will recreate this from `cache`
|
||||
const srcDir = path.join(CARGO_HOME, "registry", "src");
|
||||
await io.rmRF(srcDir);
|
||||
await rmRF(path.join(CARGO_HOME, "registry", "src"));
|
||||
|
||||
// `.cargo/registry/index`
|
||||
const indexDir = await fs.promises.opendir(path.join(CARGO_HOME, "registry", "index"));
|
||||
|
@ -107,7 +106,7 @@ export async function cleanRegistry(packages: Packages) {
|
|||
|
||||
// for a git registry, we can remove `.cache`, as cargo will recreate it from git
|
||||
if (await exists(path.join(dir.path, ".git"))) {
|
||||
await io.rmRF(path.join(dir.path, ".cache"));
|
||||
await rmRF(path.join(dir.path, ".cache"));
|
||||
}
|
||||
// TODO: else, clean `.cache` based on the `packages`
|
||||
}
|
||||
|
@ -183,7 +182,7 @@ export async function cleanGit(packages: Packages) {
|
|||
|
||||
const ONE_WEEK = 7 * 24 * 3600 * 1000;
|
||||
|
||||
export async function rmExcept(dirName: string, keepPrefix: Set<string>) {
|
||||
async function rmExcept(dirName: string, keepPrefix: Set<string>) {
|
||||
const dir = await fs.promises.opendir(dirName);
|
||||
for await (const dirent of dir) {
|
||||
let name = dirent.name;
|
||||
|
@ -200,7 +199,7 @@ export async function rmExcept(dirName: string, keepPrefix: Set<string>) {
|
|||
}
|
||||
}
|
||||
|
||||
export async function rm(parent: string, dirent: fs.Dirent) {
|
||||
async function rm(parent: string, dirent: fs.Dirent) {
|
||||
try {
|
||||
const fileName = path.join(parent, dirent.name);
|
||||
core.debug(`deleting "${fileName}"`);
|
||||
|
@ -212,6 +211,11 @@ export async function rm(parent: string, dirent: fs.Dirent) {
|
|||
} catch {}
|
||||
}
|
||||
|
||||
async function rmRF(dirName: string) {
|
||||
core.debug(`deleting "${dirName}"`);
|
||||
await io.rmRF(dirName);
|
||||
}
|
||||
|
||||
async function exists(path: string) {
|
||||
try {
|
||||
await fs.promises.access(path);
|
||||
|
|
|
@ -47,12 +47,12 @@ export class CacheConfig {
|
|||
const self = new CacheConfig();
|
||||
|
||||
// Construct key prefix:
|
||||
// This uses either the `sharedKey` input,
|
||||
// This uses either the `shared-key` input,
|
||||
// or the `key` input combined with the `job` key.
|
||||
|
||||
let key = `v0-rust`;
|
||||
|
||||
const sharedKey = core.getInput("sharedKey");
|
||||
const sharedKey = core.getInput("shared-key");
|
||||
if (sharedKey) {
|
||||
key += `-${sharedKey}`;
|
||||
} else {
|
||||
|
@ -72,7 +72,7 @@ export class CacheConfig {
|
|||
// Construct environment portion of the key:
|
||||
// This consists of a hash that considers the rust version
|
||||
// as well as all the environment variables as given by a default list
|
||||
// and the `envVars` input.
|
||||
// and the `env-vars` input.
|
||||
// The env vars are sorted, matched by prefix and hashed into the
|
||||
// resulting environment hash.
|
||||
|
||||
|
@ -87,8 +87,8 @@ export class CacheConfig {
|
|||
self.keyRust = keyRust;
|
||||
|
||||
// these prefixes should cover most of the compiler / rust / cargo keys
|
||||
const envPrefixes = ["CARGO", "CC", "CXX", "CMAKE", "RUST"];
|
||||
envPrefixes.push(...core.getInput("envVars").split(/\s+/).filter(Boolean));
|
||||
const envPrefixes = ["CARGO", "CC", "CFLAGS", "CXX", "CMAKE", "RUST"];
|
||||
envPrefixes.push(...core.getInput("env-vars").split(/\s+/).filter(Boolean));
|
||||
|
||||
// sort the available env vars so we have a more stable hash
|
||||
const keyEnvs = [];
|
||||
|
@ -147,7 +147,7 @@ export class CacheConfig {
|
|||
const workspaces: Array<Workspace> = [];
|
||||
const workspacesInput = core.getInput("workspaces") || ".";
|
||||
for (const workspace of workspacesInput.trim().split("\n")) {
|
||||
let [root, target = "target"] = workspace.split(" -> ");
|
||||
let [root, target = "target"] = workspace.split("->").map((s) => s.trim());
|
||||
root = path.resolve(root);
|
||||
target = path.join(root, target);
|
||||
workspaces.push(new Workspace(root, target));
|
||||
|
|
Loading…
Reference in a new issue