mirror of
https://github.com/obi1kenobi/cargo-semver-checks-action.git
synced 2024-11-21 23:49:33 +01:00
Include package
and manifest-path
in the cache key (#38)
* New caching strategy * Update README.md Co-authored-by: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> --------- Co-authored-by: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com>
This commit is contained in:
parent
f2825830a8
commit
670e9a45ae
6 changed files with 138 additions and 10 deletions
57
.github/workflows/test-cache.yml
vendored
57
.github/workflows/test-cache.yml
vendored
|
@ -10,8 +10,8 @@ env:
|
||||||
RUST_BACKTRACE: 1
|
RUST_BACKTRACE: 1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test-cache-exists:
|
test-cache-exists-shared:
|
||||||
name: Check if the cache exists after running the action
|
name: Check if the cache exists after running the action with shared-key
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the test repository and test with patch change and patch version bump
|
- name: Checkout the test repository and test with patch change and patch version bump
|
||||||
|
@ -27,8 +27,9 @@ jobs:
|
||||||
- name: Run the action
|
- name: Run the action
|
||||||
uses: ./action/
|
uses: ./action/
|
||||||
with:
|
with:
|
||||||
|
package: ref_slice
|
||||||
manifest-path: 'ref_slice/Cargo.toml'
|
manifest-path: 'ref_slice/Cargo.toml'
|
||||||
cache-key: testkey
|
shared-key: testkey
|
||||||
prefix-key: testprefix
|
prefix-key: testprefix
|
||||||
- name: Check if the cache directory exists
|
- name: Check if the cache directory exists
|
||||||
run: |
|
run: |
|
||||||
|
@ -59,3 +60,53 @@ jobs:
|
||||||
echo "Downloaded cache does not match the local version!"
|
echo "Downloaded cache does not match the local version!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
test-cache-exists-default:
|
||||||
|
name: Check if the cache exists after running the action without shared-key
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout the test repository and test with patch change and patch version bump
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
path: 'ref_slice'
|
||||||
|
repository: mgr0dzicki/cargo-semver-action-ref-slice
|
||||||
|
ref: patch_change
|
||||||
|
- name: Checkout the action
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
path: action
|
||||||
|
- name: Run the action
|
||||||
|
uses: ./action/
|
||||||
|
with:
|
||||||
|
package: ref_slice
|
||||||
|
manifest-path: 'ref_slice/Cargo.toml'
|
||||||
|
prefix-key: testprefix
|
||||||
|
- name: Check if the cache directory exists
|
||||||
|
run: |
|
||||||
|
if ! grep -q "ref_slice-1.2.1/src/lib.rs" "semver-checks/target/semver-checks/cache/registry-ref_slice-1_2_1.json"; then
|
||||||
|
echo "Non-existent or invalid cache file!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
- name: Move the cache created by the action
|
||||||
|
run: |
|
||||||
|
mv semver-checks/target/semver-checks/cache action-cache
|
||||||
|
- name: Generate primary cache key
|
||||||
|
id: generate_key
|
||||||
|
run: |
|
||||||
|
RUSTC=$(rustc --version | sed -e 's/\s\+/-/g')
|
||||||
|
SEMVER_CHECKS=$(cargo semver-checks --version | sed -e 's/\s\+/-/g')
|
||||||
|
echo "KEY=testprefix-test-cache-exists-default-ref_slice-8e11dadaa21a8bf3112b6c764012883b-linux-$RUSTC-$SEMVER_CHECKS-da39a3ee5e6b4b0d3255bfef95601890afd80709-semver-checks-rustdoc" >> $GITHUB_OUTPUT
|
||||||
|
- name: Download saved cache
|
||||||
|
uses: actions/cache/restore@v3
|
||||||
|
with:
|
||||||
|
path: ${{ github.workspace }}/semver-checks/target/semver-checks/cache
|
||||||
|
fail-on-cache-miss: true
|
||||||
|
key: not_a_prefix
|
||||||
|
restore-keys: |
|
||||||
|
${{ steps.generate_key.outputs.KEY }}
|
||||||
|
- name: Compare local and downloaded cache files
|
||||||
|
run: |
|
||||||
|
if ! diff -r "semver-checks/target/semver-checks/cache" "action-cache"; then
|
||||||
|
echo "Downloaded cache does not match the local version!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
61
README.md
61
README.md
|
@ -20,7 +20,7 @@ Every argument is optional.
|
||||||
| `manifest-path` | Path to Cargo.toml of crate or workspace to check. If not specified, the action assumes the manifest is under the default [`GITHUB_WORKSPACE`](https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables) path. | |
|
| `manifest-path` | Path to Cargo.toml of crate or workspace to check. If not specified, the action assumes the manifest is under the default [`GITHUB_WORKSPACE`](https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables) path. | |
|
||||||
| `verbose` | Enables verbose output of `cargo-semver-checks`. | `false` |
|
| `verbose` | Enables verbose output of `cargo-semver-checks`. | `false` |
|
||||||
| `rust-toolchain` | Rust toolchain name to use, e.g. `stable`, `nightly` or `1.68.0`. It will be installed if necessary and used regardless of local overrides and the `rust-toolchain.toml` file. However, if the input is set to be an empty string, the action assumes some Rust toolchain is already installed and uses the default one. | `stable` |
|
| `rust-toolchain` | Rust toolchain name to use, e.g. `stable`, `nightly` or `1.68.0`. It will be installed if necessary and used regardless of local overrides and the `rust-toolchain.toml` file. However, if the input is set to be an empty string, the action assumes some Rust toolchain is already installed and uses the default one. | `stable` |
|
||||||
| `cache-key` | Rustdoc baseline is cached separately for runs that differ in at least one of the following: runner OS, `rustc` version, `cargo-semver-checks` version, or any of the `Cargo.lock` files in the current workspace. This input might be used to further separate the caches by providing the unique key (by default the job name) for each of them. | `${{ github.job }}` |
|
| `shared-key` | A cache key that will be used instead of the automatic key based on the name of the GitHub job and values of the inputs `package` and `manifest-path`. Might be provided e.g. to share the cache between the jobs. | |
|
||||||
| `prefix-key` | Additional prefix of the cache key, can be set to start a new cache manually. | |
|
| `prefix-key` | Additional prefix of the cache key, can be set to start a new cache manually. | |
|
||||||
| `github-token` | The `GITHUB_TOKEN` secret used to download precompiled binaries from GitHub API. If not specified, the [automatic GitHub token](https://docs.github.com/en/actions/security-guides/automatic-token-authentication) provided to the workflow will be used. The token may be alternatively passed in an environment variable `GITHUB_TOKEN`. | `${{ github.token }}` |
|
| `github-token` | The `GITHUB_TOKEN` secret used to download precompiled binaries from GitHub API. If not specified, the [automatic GitHub token](https://docs.github.com/en/actions/security-guides/automatic-token-authentication) provided to the workflow will be used. The token may be alternatively passed in an environment variable `GITHUB_TOKEN`. | `${{ github.token }}` |
|
||||||
|
|
||||||
|
@ -70,3 +70,62 @@ The two above might be also used together:
|
||||||
- name: Publish my-crate to crates.io
|
- name: Publish my-crate to crates.io
|
||||||
run: # your `cargo publish` code here
|
run: # your `cargo publish` code here
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# Customizing baseline rustdoc caching strategy
|
||||||
|
|
||||||
|
The action caches the baseline rustdoc for each package in the workspace. The keys used to distinguish the caches consist of four components:
|
||||||
|
|
||||||
|
- `prefix-key` input, which defaults to an empty string,
|
||||||
|
- `shared-key` input if provided, otherwise a concatenation of the value of environmental variable `GITHUB_JOB`, the value of `package` and the hashed value of the `manifest-path` variable (not the file it points to),
|
||||||
|
- internal, unchangable component, being a concatenation of the runner OS, `rustc` version, `cargo-semver-checks` version and hash of all `Cargo.lock` files in the current workspace,
|
||||||
|
- constant suffix `"semver-checks-rustdoc"`.
|
||||||
|
|
||||||
|
Runs that differ in at least one of the above components will use separate caches. Inputs `shared-key` and `cache-key` might be therefore used to customize the caching strategy. For example, the two following jobs will share the key even despite using different `manifest-path`:
|
||||||
|
```yaml
|
||||||
|
semver:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Check semver
|
||||||
|
uses: obi1kenobi/cargo-semver-checks-action@v2
|
||||||
|
with:
|
||||||
|
shared-key: my-workspace-semver
|
||||||
|
|
||||||
|
semver2:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
path: semver
|
||||||
|
- name: Check semver
|
||||||
|
uses: obi1kenobi/cargo-semver-checks-action@v2
|
||||||
|
with:
|
||||||
|
manifest-path: semver/Cargo.toml
|
||||||
|
shared-key: my-workspace-semver
|
||||||
|
```
|
||||||
|
which is reasonable until they are checking the same packages. Runs with different targets must not share the cache! For example, the below job is doing well with default settings:
|
||||||
|
```yaml
|
||||||
|
semver:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
crate: ['api', 'core']
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Check semver
|
||||||
|
uses: obi1kenobi/cargo-semver-checks-action@v2
|
||||||
|
with:
|
||||||
|
package: ${{ matrix.crate }}
|
||||||
|
# Do not do this!
|
||||||
|
# shared-key: 'my-workspace-semver'
|
||||||
|
```
|
||||||
|
as both runs will use separate caches, but providing the shared key will lead to data race and significant drop of performance. On the other hand, if you want to further separate the caches that are shared by default, you can use the input `prefix-key`:
|
||||||
|
```yaml
|
||||||
|
- name: Check semver
|
||||||
|
uses: obi1kenobi/cargo-semver-checks-action@v2
|
||||||
|
with:
|
||||||
|
prefix-key: v1
|
||||||
|
```
|
||||||
|
|
|
@ -19,10 +19,10 @@ inputs:
|
||||||
description: 'Rust toolchain name to use, e.g. `stable`, `nightly` or `1.68.0`. It will be installed if necessary and used regardless of local overrides and the `rust-toolchain.toml` file. However, if the input is set to be an empty string, the action assumes some Rust toolchain is already installed and uses the default one.'
|
description: 'Rust toolchain name to use, e.g. `stable`, `nightly` or `1.68.0`. It will be installed if necessary and used regardless of local overrides and the `rust-toolchain.toml` file. However, if the input is set to be an empty string, the action assumes some Rust toolchain is already installed and uses the default one.'
|
||||||
required: false
|
required: false
|
||||||
default: 'stable'
|
default: 'stable'
|
||||||
cache-key:
|
shared-key:
|
||||||
description: 'Rustdoc baseline is cached separately for runs that differ in at least one of the following: runner OS, `rustc` version, `cargo-semver-checks` version, or any of the `Cargo.lock` files in the current workspace. This input might be used to further separate the caches by providing the unique key (by default the job name) for each of them.'
|
description: 'A cache key that will be used instead of the automatic key based on the name of the GitHub job and values of the inputs `package` and `manifest-path`. Might be provided e.g. to share the cache between the jobs.'
|
||||||
required: false
|
required: false
|
||||||
default: ${{ github.job }}
|
default: ''
|
||||||
prefix-key:
|
prefix-key:
|
||||||
description: 'Additional prefix of the cache key, can be set to start a new cache manually.'
|
description: 'Additional prefix of the cache key, can be set to start a new cache manually.'
|
||||||
required: false
|
required: false
|
||||||
|
|
2
dist/index.js
vendored
2
dist/index.js
vendored
File diff suppressed because one or more lines are too long
|
@ -5,7 +5,12 @@ import * as cache from "@actions/cache";
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import * as rustCore from "@actions-rs/core";
|
import * as rustCore from "@actions-rs/core";
|
||||||
|
|
||||||
import { getCargoSemverChecksVersion, getRustcVersion, hashFilesOrEmpty } from "./utils";
|
import {
|
||||||
|
getCargoSemverChecksVersion,
|
||||||
|
getRustcVersion,
|
||||||
|
hashFilesOrEmpty,
|
||||||
|
hashIfNotEmpty,
|
||||||
|
} from "./utils";
|
||||||
|
|
||||||
export class RustdocCache {
|
export class RustdocCache {
|
||||||
private readonly cargo;
|
private readonly cargo;
|
||||||
|
@ -53,7 +58,7 @@ export class RustdocCache {
|
||||||
if (!this.__cacheKey) {
|
if (!this.__cacheKey) {
|
||||||
this.__cacheKey = [
|
this.__cacheKey = [
|
||||||
rustCore.input.getInput("prefix-key") || "",
|
rustCore.input.getInput("prefix-key") || "",
|
||||||
rustCore.input.getInput("cache-key"),
|
rustCore.input.getInput("shared-key") || this.getRunDependentKey(),
|
||||||
os.platform() as string,
|
os.platform() as string,
|
||||||
await getRustcVersion(),
|
await getRustcVersion(),
|
||||||
await getCargoSemverChecksVersion(this.cargo),
|
await getCargoSemverChecksVersion(this.cargo),
|
||||||
|
@ -65,6 +70,14 @@ export class RustdocCache {
|
||||||
return this.__cacheKey;
|
return this.__cacheKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getRunDependentKey(): string {
|
||||||
|
return [
|
||||||
|
process.env["GITHUB_JOB"] || "",
|
||||||
|
rustCore.input.getInput("package"),
|
||||||
|
hashIfNotEmpty(rustCore.input.getInput("manifest-path")),
|
||||||
|
].join("-");
|
||||||
|
}
|
||||||
|
|
||||||
private getLocalCacheHash(): string {
|
private getLocalCacheHash(): string {
|
||||||
return hashFilesOrEmpty([path.join(this.cachePath, "**")]);
|
return hashFilesOrEmpty([path.join(this.cachePath, "**")]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import hashFiles = require("hash-files");
|
||||||
|
|
||||||
import * as exec from "@actions/exec";
|
import * as exec from "@actions/exec";
|
||||||
import * as rustCore from "@actions-rs/core";
|
import * as rustCore from "@actions-rs/core";
|
||||||
|
import { createHash } from "node:crypto";
|
||||||
|
|
||||||
export function getErrorMessage(error: unknown): string {
|
export function getErrorMessage(error: unknown): string {
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
|
@ -38,6 +39,10 @@ export function hashFilesOrEmpty(patterns: string[]): string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function hashIfNotEmpty(str: string): string {
|
||||||
|
return createHash("md5").update(str).digest("hex");
|
||||||
|
}
|
||||||
|
|
||||||
function makeExecOptions(stdout: { s: string }): exec.ExecOptions {
|
function makeExecOptions(stdout: { s: string }): exec.ExecOptions {
|
||||||
return {
|
return {
|
||||||
listeners: {
|
listeners: {
|
||||||
|
|
Loading…
Reference in a new issue