13 Commits

Author SHA1 Message Date
Arpad Borsos
a4a1d8e7a6 1.0.1 2020-09-28 13:06:41 +02:00
Arpad Borsos
33677a20f2 add changelog 2020-09-28 12:53:56 +02:00
Arpad Borsos
1d1bff80c5 update readme 2020-09-28 12:51:40 +02:00
Arpad Borsos
08ca2ff969 make macos workaround silent 2020-09-28 12:46:36 +02:00
Arpad Borsos
ef89c3a8eb typo 2020-09-28 12:30:40 +02:00
Arpad Borsos
d45cd2b045 rebuild 2020-09-28 12:26:12 +02:00
Arpad Borsos
271ff4b692 log individual timings 2020-09-28 12:26:11 +02:00
Arpad Borsos
a6b59fa340 clean up exports 2020-09-28 12:14:11 +02:00
Arpad Borsos
e0c07d2a65 work around macos cache corruption 2020-09-28 12:08:11 +02:00
Arpad Borsos
06ff70612d remove git-db for now 2020-09-28 12:06:51 +02:00
Arpad Borsos
1304a2ec8d add ability to version caches 2020-09-28 12:00:58 +02:00
Arpad Borsos
cfcc373039 improve logging 2020-09-28 11:54:24 +02:00
Arpad Borsos
8902a8fc6c collect packages with --all-features 2020-09-28 11:44:06 +02:00
9 changed files with 542 additions and 440 deletions

8
CHANGELOG.md Normal file
View File

@@ -0,0 +1,8 @@
# Changelog
## 1.0.1
- Improved logging output.
- Make sure to consider `all-features` dependencies when pruning.
- Work around macOS cache corruption.
- Remove git-db cache for now.

View File

@@ -30,20 +30,16 @@ assumption is that we will likely recompile the own crate(s) anyway.
It also separates the cache into 4 groups, each treated differently:
- Index: `~/.cargo/registry/index/<registry>`:
- Registry Index: `~/.cargo/registry/index/<registry>`:
This is always restored from its latest snapshot, and persisted based on the
most recent revision.
- Registry / Cache: `~/.cargo/registry/cache/<registry>`:
- Registry Cache: `~/.cargo/registry/cache/<registry>`:
Automatically keyed by the lockfile/toml hash, and is being pruned to only
persist the dependencies that are being used.
- Registry / Git: `~/.cargo/registry/git/<registry>`:
Automatically keyed by the lockfile/toml hash. Pruning is still TODO.
- target: `./target`
Automatically keyed by the lockfile/toml hash, and is being pruned to only

45
dist/restore/index.js vendored
View File

@@ -54634,14 +54634,32 @@ async function getCaches() {
if (targetKey) {
targetKey = `${targetKey}-`;
}
const registryIndex = `v0-registry-index`;
const registryCache = `v0-registry-cache`;
const target = `v0-target-${targetKey}${rustKey}`;
return {
index: { path: paths.index, key: "registry-index-XXX", restoreKeys: ["registry-index"] },
cache: { path: paths.cache, key: `registry-cache-${lockHash}`, restoreKeys: ["registry-cache"] },
git: { path: paths.git, key: "git-db" },
index: {
name: "Registry Index",
path: paths.index,
key: `${registryIndex}-`,
restoreKeys: [registryIndex],
},
cache: {
name: "Registry Cache",
path: paths.cache,
key: `${registryCache}-${lockHash}`,
restoreKeys: [registryCache],
},
// git: {
// name: "Git Dependencies",
// path: paths.git,
// key: "git-db",
// },
target: {
name: "Target",
path: paths.target,
key: `target-${targetKey}${rustKey}-${lockHash}`,
restoreKeys: [`target-${targetKey}${rustKey}`],
key: `${target}-${lockHash}`,
restoreKeys: [target],
},
};
}
@@ -54714,13 +54732,16 @@ async function run() {
try {
core.exportVariable("CARGO_INCREMENTAL", 0);
const caches = await getCaches();
for (const [name, { path, key, restoreKeys }] of Object.entries(caches)) {
for (const [type, { name, path, key, restoreKeys }] of Object.entries(caches)) {
const start = Date.now();
core.startGroup(`Restoring ${name}`);
core.info(`Restoring to path "${path}".`);
core.info(`Using keys:\n ${[key, ...restoreKeys].join("\n ")}`);
try {
core.startGroup(`Restoring "${path}" from "${key}"…`);
const restoreKey = await cache.restoreCache([path], key, restoreKeys);
if (restoreKey) {
core.info(`Restored "${path}" from cache key "${restoreKey}".`);
core.saveState(name, restoreKey);
core.info(`Restored from cache key "${restoreKey}".`);
core.saveState(type, restoreKey);
}
else {
core.info("No cache found.");
@@ -54729,9 +54750,11 @@ async function run() {
catch (e) {
core.info(`[warning] ${e.message}`);
}
finally {
core.endGroup();
const duration = Math.round((Date.now() - start) / 1000);
if (duration) {
core.info(`Took ${duration}s.`);
}
core.endGroup();
}
}
catch (e) {

80
dist/save/index.js vendored
View File

@@ -54581,25 +54581,25 @@ var exec = __webpack_require__(1514);
// EXTERNAL MODULE: ./node_modules/@actions/glob/lib/glob.js
var glob = __webpack_require__(8090);
// EXTERNAL MODULE: ./node_modules/@actions/io/lib/io.js
var io = __webpack_require__(7436);
// EXTERNAL MODULE: external "crypto"
var external_crypto_ = __webpack_require__(6417);
var external_crypto_default = /*#__PURE__*/__webpack_require__.n(external_crypto_);
// EXTERNAL MODULE: ./node_modules/@actions/io/lib/io.js
var io = __webpack_require__(7436);
// EXTERNAL MODULE: external "fs"
var external_fs_ = __webpack_require__(5747);
var external_fs_default = /*#__PURE__*/__webpack_require__.n(external_fs_);
// EXTERNAL MODULE: external "path"
var external_path_ = __webpack_require__(5622);
var external_path_default = /*#__PURE__*/__webpack_require__.n(external_path_);
// EXTERNAL MODULE: external "os"
var external_os_ = __webpack_require__(2087);
var external_os_default = /*#__PURE__*/__webpack_require__.n(external_os_);
// EXTERNAL MODULE: external "path"
var external_path_ = __webpack_require__(5622);
var external_path_default = /*#__PURE__*/__webpack_require__.n(external_path_);
// CONCATENATED MODULE: ./src/common.ts
var __asyncValues = (undefined && undefined.__asyncValues) || function (o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
@@ -54637,14 +54637,32 @@ async function getCaches() {
if (targetKey) {
targetKey = `${targetKey}-`;
}
const registryIndex = `v0-registry-index`;
const registryCache = `v0-registry-cache`;
const target = `v0-target-${targetKey}${rustKey}`;
return {
index: { path: paths.index, key: "registry-index-XXX", restoreKeys: ["registry-index"] },
cache: { path: paths.cache, key: `registry-cache-${lockHash}`, restoreKeys: ["registry-cache"] },
git: { path: paths.git, key: "git-db" },
index: {
name: "Registry Index",
path: paths.index,
key: `${registryIndex}-`,
restoreKeys: [registryIndex],
},
cache: {
name: "Registry Cache",
path: paths.cache,
key: `${registryCache}-${lockHash}`,
restoreKeys: [registryCache],
},
// git: {
// name: "Git Dependencies",
// path: paths.git,
// key: "git-db",
// },
target: {
name: "Target",
path: paths.target,
key: `target-${targetKey}${rustKey}-${lockHash}`,
restoreKeys: [`target-${targetKey}${rustKey}`],
key: `${target}-${lockHash}`,
restoreKeys: [target],
},
};
}
@@ -54720,19 +54738,22 @@ var save_asyncValues = (undefined && undefined.__asyncValues) || function (o) {
async function run() {
if (!isValidEvent()) {
//return;
return;
}
try {
const caches = await getCaches();
const registryName = await getRegistryName();
const packages = await getPackages();
// TODO: remove this once https://github.com/actions/toolkit/pull/553 lands
await macOsWorkaround();
await pruneTarget(packages);
if (registryName) {
// save the index based on its revision
const indexRef = await getIndexRef(registryName);
caches.index.key = `registry-index-${indexRef}`;
caches.index.key += indexRef;
await io.rmRF(external_path_default().join(paths.index, registryName, ".cache"));
await pruneRegistryCache(registryName, packages);
}
@@ -54740,23 +54761,26 @@ async function run() {
delete caches.index;
delete caches.cache;
}
for (const [name, { path, key }] of Object.entries(caches)) {
if (core.getState(name) === key) {
core.info(`Cache for "${path}" up-to-date.`);
for (const [type, { name, path, key }] of Object.entries(caches)) {
if (core.getState(type) === key) {
core.info(`${name} up-to-date.`);
continue;
}
const start = Date.now();
core.startGroup(`Saving ${name}`);
core.info(`Saving path "${path}".`);
core.info(`Using key "${key}".`);
try {
core.startGroup(`Saving "${path}" to cache key "${key}"…`);
if (await cache.saveCache([path], key)) {
core.info(`Saved "${path}" to cache key "${key}".`);
}
await cache.saveCache([path], key);
}
catch (e) {
core.info(`[warning] ${e.message}`);
}
finally {
core.endGroup();
const duration = Math.round((Date.now() - start) / 1000);
if (duration) {
core.info(`Took ${duration}s.`);
}
core.endGroup();
}
}
catch (e) {
@@ -54769,7 +54793,7 @@ async function getIndexRef(registryName) {
return (await getCmdOutput("git", ["rev-parse", "--short", "origin/master"], { cwd })).trim();
}
async function getPackages() {
const meta = JSON.parse(await getCmdOutput("cargo", ["metadata", "--format-version", "1"]));
const meta = JSON.parse(await getCmdOutput("cargo", ["metadata", "--all-features", "--format-version", "1"]));
return meta.packages.map(({ name, version }) => ({ name, version }));
}
async function pruneRegistryCache(registryName, packages) {
@@ -54860,6 +54884,14 @@ async function rmExcept(dirName, keepPrefix) {
finally { if (e_3) throw e_3.error; }
}
}
async function macOsWorkaround() {
try {
// Workaround for https://github.com/actions/cache/issues/403
// Also see https://github.com/rust-lang/cargo/issues/8603
await exec.exec("sudo", ["/usr/sbin/purge"], { silent: true });
}
catch (_a) { }
}
/***/ }),

2
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "rust-cache",
"version": "1.0.0",
"version": "1.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -1,7 +1,7 @@
{
"private": true,
"name": "rust-cache",
"version": "1.0.0",
"version": "1.0.1",
"description": "A GitHub Action that implements smart caching for rust/cargo projects",
"keywords": [
"actions",

View File

@@ -14,16 +14,17 @@ export const paths = {
target: "target",
};
export interface CacheConfig {
interface CacheConfig {
name: string;
path: string;
key: string;
restoreKeys?: Array<string>;
}
export interface Caches {
interface Caches {
index: CacheConfig;
cache: CacheConfig;
git: CacheConfig;
// git: CacheConfig;
target: CacheConfig;
}
@@ -44,19 +45,38 @@ export async function getCaches(): Promise<Caches> {
if (targetKey) {
targetKey = `${targetKey}-`;
}
const registryIndex = `v0-registry-index`;
const registryCache = `v0-registry-cache`;
const target = `v0-target-${targetKey}${rustKey}`;
return {
index: { path: paths.index, key: "registry-index-XXX", restoreKeys: ["registry-index"] },
cache: { path: paths.cache, key: `registry-cache-${lockHash}`, restoreKeys: ["registry-cache"] },
git: { path: paths.git, key: "git-db" },
index: {
name: "Registry Index",
path: paths.index,
key: `${registryIndex}-`,
restoreKeys: [registryIndex],
},
cache: {
name: "Registry Cache",
path: paths.cache,
key: `${registryCache}-${lockHash}`,
restoreKeys: [registryCache],
},
// git: {
// name: "Git Dependencies",
// path: paths.git,
// key: "git-db",
// },
target: {
name: "Target",
path: paths.target,
key: `target-${targetKey}${rustKey}-${lockHash}`,
restoreKeys: [`target-${targetKey}${rustKey}`],
key: `${target}-${lockHash}`,
restoreKeys: [target],
},
};
}
export async function getRustKey(): Promise<string> {
async function getRustKey(): Promise<string> {
const rustc = await getRustVersion();
return `${rustc.release}-${rustc.host}-${rustc["commit-hash"]}`;
}
@@ -67,7 +87,7 @@ interface RustVersion {
"commit-hash": string;
}
export async function getRustVersion(): Promise<RustVersion> {
async function getRustVersion(): Promise<RustVersion> {
const stdout = await getCmdOutput("rustc", ["-vV"]);
let splits = stdout
.split(/[\n\r]+/)
@@ -109,7 +129,7 @@ export async function getRegistryName() {
return path.basename(path.dirname(first));
}
export async function getLockfileHash() {
async function getLockfileHash() {
const globber = await glob.create("**/Cargo.toml\n**/Cargo.lock", { followSymbolicLinks: false });
const files = await globber.glob();
files.sort((a, b) => a.localeCompare(b));

View File

@@ -11,21 +11,27 @@ async function run() {
core.exportVariable("CARGO_INCREMENTAL", 0);
const caches = await getCaches();
for (const [name, { path, key, restoreKeys }] of Object.entries(caches)) {
for (const [type, { name, path, key, restoreKeys }] of Object.entries(caches)) {
const start = Date.now();
core.startGroup(`Restoring ${name}`);
core.info(`Restoring to path "${path}".`);
core.info(`Using keys:\n ${[key, ...restoreKeys].join("\n ")}`);
try {
core.startGroup(`Restoring "${path}" from "${key}"…`);
const restoreKey = await cache.restoreCache([path], key, restoreKeys);
if (restoreKey) {
core.info(`Restored "${path}" from cache key "${restoreKey}".`);
core.saveState(name, restoreKey);
core.info(`Restored from cache key "${restoreKey}".`);
core.saveState(type, restoreKey);
} else {
core.info("No cache found.");
}
} catch (e) {
core.info(`[warning] ${e.message}`);
} finally {
core.endGroup();
}
const duration = Math.round((Date.now() - start) / 1000);
if (duration) {
core.info(`Took ${duration}s.`);
}
core.endGroup();
}
} catch (e) {
core.info(`[warning] ${e.message}`);

View File

@@ -1,5 +1,6 @@
import * as cache from "@actions/cache";
import * as core from "@actions/core";
import * as exec from "@actions/exec";
import * as io from "@actions/io";
import fs from "fs";
import path from "path";
@@ -7,7 +8,7 @@ import { getCaches, getCmdOutput, getRegistryName, isValidEvent, paths } from ".
async function run() {
if (!isValidEvent()) {
//return;
return;
}
try {
@@ -15,11 +16,15 @@ async function run() {
const registryName = await getRegistryName();
const packages = await getPackages();
// TODO: remove this once https://github.com/actions/toolkit/pull/553 lands
await macOsWorkaround();
await pruneTarget(packages);
if (registryName) {
// save the index based on its revision
const indexRef = await getIndexRef(registryName);
caches.index.key = `registry-index-${indexRef}`;
caches.index.key += indexRef;
await io.rmRF(path.join(paths.index, registryName, ".cache"));
await pruneRegistryCache(registryName, packages);
@@ -28,21 +33,25 @@ async function run() {
delete (caches as any).cache;
}
for (const [name, { path, key }] of Object.entries(caches)) {
if (core.getState(name) === key) {
core.info(`Cache for "${path}" up-to-date.`);
for (const [type, { name, path, key }] of Object.entries(caches)) {
if (core.getState(type) === key) {
core.info(`${name} up-to-date.`);
continue;
}
const start = Date.now();
core.startGroup(`Saving ${name}`);
core.info(`Saving path "${path}".`);
core.info(`Using key "${key}".`);
try {
core.startGroup(`Saving "${path}" to cache key "${key}"…`);
if (await cache.saveCache([path], key)) {
core.info(`Saved "${path}" to cache key "${key}".`);
}
await cache.saveCache([path], key);
} catch (e) {
core.info(`[warning] ${e.message}`);
} finally {
core.endGroup();
}
const duration = Math.round((Date.now() - start) / 1000);
if (duration) {
core.info(`Took ${duration}s.`);
}
core.endGroup();
}
} catch (e) {
core.info(`[warning] ${e.message}`);
@@ -64,7 +73,7 @@ interface PackageDefinition {
type Packages = Array<PackageDefinition>;
async function getPackages(): Promise<Packages> {
const meta = JSON.parse(await getCmdOutput("cargo", ["metadata", "--format-version", "1"]));
const meta = JSON.parse(await getCmdOutput("cargo", ["metadata", "--all-features", "--format-version", "1"]));
return meta.packages.map(({ name, version }: any) => ({ name, version }));
}
@@ -131,3 +140,11 @@ async function rmExcept(dirName: string, keepPrefix: Set<string>) {
}
}
}
async function macOsWorkaround() {
try {
// Workaround for https://github.com/actions/cache/issues/403
// Also see https://github.com/rust-lang/cargo/issues/8603
await exec.exec("sudo", ["/usr/sbin/purge"], { silent: true });
} catch {}
}