From 260a71318607eda96c27073637c508240499307d Mon Sep 17 00:00:00 2001 From: Nick Mosher Date: Fri, 16 Jul 2021 16:58:46 -0400 Subject: [PATCH] Cache multiple target directories from 'target-dir' --- .github/workflows/selftest.yml | 7 +- .gitignore | 10 ++- Cargo.lock | 96 ++++++++++++++++++++++++--- Cargo.toml | 1 + action.yml | 3 + src/common.ts | 46 ++++++++----- src/restore.ts | 16 +++-- src/save.ts | 20 ++++-- wasm-workspace/.cargo/config.toml | 2 + wasm-workspace/.gitignore | 1 + wasm-workspace/Cargo.toml | 5 ++ wasm-workspace/crates/one/Cargo.toml | 14 ++++ wasm-workspace/crates/one/src/main.rs | 3 + wasm-workspace/crates/two/Cargo.toml | 9 +++ wasm-workspace/crates/two/src/main.rs | 3 + 15 files changed, 195 insertions(+), 41 deletions(-) create mode 100644 wasm-workspace/.cargo/config.toml create mode 100644 wasm-workspace/.gitignore create mode 100644 wasm-workspace/Cargo.toml create mode 100644 wasm-workspace/crates/one/Cargo.toml create mode 100644 wasm-workspace/crates/one/src/main.rs create mode 100644 wasm-workspace/crates/two/Cargo.toml create mode 100644 wasm-workspace/crates/two/src/main.rs diff --git a/.github/workflows/selftest.yml b/.github/workflows/selftest.yml index ca4a3a7..3682d0d 100644 --- a/.github/workflows/selftest.yml +++ b/.github/workflows/selftest.yml @@ -24,8 +24,13 @@ jobs: - uses: ./ with: cache-on-failure: true + workspace-paths: | + ./ + wasm-workspace/ - run: | cargo install cargo-deny --locked cargo check - cargo test \ No newline at end of file + cargo test + rustup target install wasm32-unknown-unknown + cd wasm-workspace && cargo check \ No newline at end of file diff --git a/.gitignore b/.gitignore index a96f68c..710e1ce 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,8 @@ -node_modules -/target +node_modules/ +target/ + +# Editors +.idea/ + +# Mac +.DS_Store diff --git a/Cargo.lock b/Cargo.lock index 1a99441..d7bb1a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "actix-codec" version = "0.4.0-beta.1" @@ -228,6 +230,17 @@ dependencies = [ "memchr", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.0.1" @@ -328,9 +341,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.66" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" [[package]] name = "cfg-if" @@ -338,6 +351,30 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "3.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190814073e85d238f31ff738fcb0bf6910cedeb73376c87cd69291028966fd83" +dependencies = [ + "atty", + "bitflags", + "clap_lex", + "indexmap", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "const_fn" version = "0.4.5" @@ -701,9 +738,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.86" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" [[package]] name = "lock_api" @@ -813,9 +850,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.5.2" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" +checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" [[package]] name = "opaque-debug" @@ -856,6 +893,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "os_str_bytes" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" + [[package]] name = "parking_lot" version = "0.11.1" @@ -1090,6 +1133,7 @@ name = "rust-cache" version = "0.1.0" dependencies = [ "actix-web", + "clap", "reqwest", ] @@ -1314,6 +1358,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "syn" version = "1.0.60" @@ -1340,10 +1390,25 @@ dependencies = [ ] [[package]] -name = "thread_local" +name = "termcolor" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + +[[package]] +name = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" dependencies = [ "once_cell", ] @@ -1462,11 +1527,11 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.17" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f" +checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" dependencies = [ - "lazy_static", + "once_cell", ] [[package]] @@ -1649,6 +1714,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index e3f9484..3569a0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,5 @@ edition = "2018" [dev-dependencies] reqwest = "0.11.0" +clap = "3" actix-web = { git = "https://github.com/actix/actix-web.git", rev = "bd26083f333ecf63e3eb444748250364ce124f5e" } diff --git a/action.yml b/action.yml index ee9362d..a59095d 100644 --- a/action.yml +++ b/action.yml @@ -17,6 +17,9 @@ inputs: target-dir: description: "The target dir that should be cleaned and persisted, defaults to `./target`" required: false + workspace-paths: + description: "Paths to multiple Cargo workspaces, separated by newlines" + required: false cache-on-failure: description: "Cache even if the build fails. Defaults to false" required: false diff --git a/src/common.ts b/src/common.ts index 2eaaa8e..b72b9c9 100644 --- a/src/common.ts +++ b/src/common.ts @@ -15,8 +15,12 @@ process.on("uncaughtException", (e) => { }); const cwd = core.getInput("working-directory"); + +// Read each line of workspace-paths as a unique path // TODO: this could be read from .cargo config file directly -const targetDir = core.getInput("target-dir") || "./target"; +const workspacePathsInput = core.getInput("workspace-paths") || "./"; +const workspacePaths = workspacePathsInput.trim().split("\n"); + if (cwd) { process.chdir(cwd); } @@ -32,13 +36,16 @@ export const paths = { index: path.join(cargoHome, "registry/index"), cache: path.join(cargoHome, "registry/cache"), git: path.join(cargoHome, "git"), - target: targetDir, + workspaces: workspacePaths, }; interface CacheConfig { + // A list of common paths needing caching paths: Array; key: string; restoreKeys: Array; + // A list of one or more workspace directories + workspaces: Array; } const RefKey = "GITHUB_REF"; @@ -84,10 +91,10 @@ export async function getCacheConfig(): Promise { paths.git, paths.cache, paths.index, - paths.target, ], key: `${key}-${lockHash}`, restoreKeys: [key], + workspaces: paths.workspaces, }; } @@ -191,6 +198,7 @@ async function getLockfileHash(): Promise { followSymbolicLinks: false, }); const files = await globber.glob(); + core.debug("Lockfile Hash includes: " + JSON.stringify(files)); files.sort((a, b) => a.localeCompare(b)); const hasher = crypto.createHash("sha1"); @@ -220,26 +228,34 @@ interface Meta { }>; } -export async function getPackages(): Promise { +export async function getPackages(workspacePaths: Array): Promise { const cwd = process.cwd(); - const meta: Meta = JSON.parse(await getCmdOutput("cargo", ["metadata", "--all-features", "--format-version", "1"])); - return meta.packages - .filter((p) => !p.manifest_path.startsWith(cwd)) - .map((p) => { - const targets = p.targets.filter((t) => t.kind[0] === "lib").map((t) => t.name); - return { name: p.name, version: p.version, targets, path: path.dirname(p.manifest_path) }; - }); + let allPackages: Packages = []; + for (const workspacePath of workspacePaths) { + process.chdir(workspacePath); + const meta: Meta = JSON.parse(await getCmdOutput("cargo", ["metadata", "--all-features", "--format-version", "1"])); + const workspacePackages = meta.packages + .filter((p) => !p.manifest_path.startsWith(cwd)) + .map((p) => { + const targets = p.targets.filter((t) => t.kind[0] === "lib").map((t) => t.name); + return { name: p.name, version: p.version, targets, path: path.dirname(p.manifest_path) }; + }); + allPackages = allPackages.concat(workspacePackages); + } + + process.chdir(cwd); + return allPackages; } -export async function cleanTarget(packages: Packages) { +export async function cleanTarget(targetDir: string, packages: Packages) { await fs.promises.unlink(path.join(targetDir, "./.rustc_info.json")); - await cleanProfileTarget(packages, "debug"); - await cleanProfileTarget(packages, "release"); + await cleanProfileTarget(targetDir, packages, "debug"); + await cleanProfileTarget(targetDir, packages, "release"); } -async function cleanProfileTarget(packages: Packages, profile: string) { +async function cleanProfileTarget(targetDir: string, packages: Packages, profile: string) { try { await fs.promises.access(path.join(targetDir, profile)); } catch { diff --git a/src/restore.ts b/src/restore.ts index 347d026..a48e12c 100644 --- a/src/restore.ts +++ b/src/restore.ts @@ -1,5 +1,6 @@ import * as cache from "@actions/cache"; import * as core from "@actions/core"; +import path from "path"; import { cleanTarget, getCacheConfig, getCargoBins, getPackages, stateBins, stateKey } from "./common"; async function run() { @@ -16,24 +17,29 @@ async function run() { core.exportVariable("CACHE_ON_FAILURE", cacheOnFailure); core.exportVariable("CARGO_INCREMENTAL", 0); - const { paths, key, restoreKeys } = await getCacheConfig(); + const { paths, key, restoreKeys, workspaces } = await getCacheConfig(); + const restorePaths = paths.concat(workspaces); const bins = await getCargoBins(); core.saveState(stateBins, JSON.stringify([...bins])); - core.info(`Restoring paths:\n ${paths.join("\n ")}`); + core.info(`Restoring paths:\n ${restorePaths.join("\n ")}`); core.info(`In directory:\n ${process.cwd()}`); core.info(`Using keys:\n ${[key, ...restoreKeys].join("\n ")}`); - const restoreKey = await cache.restoreCache(paths, key, restoreKeys); + const restoreKey = await cache.restoreCache(restorePaths, key, restoreKeys); if (restoreKey) { core.info(`Restored from cache key "${restoreKey}".`); core.saveState(stateKey, restoreKey); if (restoreKey !== key) { // pre-clean the target directory on cache mismatch - const packages = await getPackages(); + const packages = await getPackages(workspaces); + core.info("Restoring the following repository packages: " + JSON.stringify(packages)); - await cleanTarget(packages); + for (const workspace of workspaces) { + const target = path.join(workspace, "target"); + await cleanTarget(target, packages); + } } setCacheHitOutput(restoreKey === key); diff --git a/src/save.ts b/src/save.ts index a34923c..50abe9e 100644 --- a/src/save.ts +++ b/src/save.ts @@ -23,7 +23,8 @@ async function run() { } try { - const { paths: savePaths, key } = await getCacheConfig(); + const { paths, workspaces, key } = await getCacheConfig(); + const savePaths = paths.concat(workspaces); if (core.getState(stateKey) === key) { core.info(`Cache up-to-date.`); @@ -34,7 +35,8 @@ async function run() { await macOsWorkaround(); const registryName = await getRegistryName(); - const packages = await getPackages(); + const packages = await getPackages(workspaces); + core.info("Detected repository packages to cache: " + JSON.stringify(packages)); if (registryName) { try { @@ -56,10 +58,14 @@ async function run() { core.info(`[warning] ${(e as any).stack}`); } - try { - await cleanTarget(packages); - } catch (e) { - core.info(`[warning] ${(e as any).stack}`); + for (const workspace of workspaces) { + const target = path.join(workspace, "target"); + try { + await cleanTarget(target, packages); + } + catch (e) { + core.info(`[warning] ${(e as any).stack}`); + } } core.info(`Saving paths:\n ${savePaths.join("\n ")}`); @@ -170,5 +176,5 @@ async function macOsWorkaround() { // 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 {} + } catch { } } diff --git a/wasm-workspace/.cargo/config.toml b/wasm-workspace/.cargo/config.toml new file mode 100644 index 0000000..f4e8c00 --- /dev/null +++ b/wasm-workspace/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target = "wasm32-unknown-unknown" diff --git a/wasm-workspace/.gitignore b/wasm-workspace/.gitignore new file mode 100644 index 0000000..03314f7 --- /dev/null +++ b/wasm-workspace/.gitignore @@ -0,0 +1 @@ +Cargo.lock diff --git a/wasm-workspace/Cargo.toml b/wasm-workspace/Cargo.toml new file mode 100644 index 0000000..3cd8359 --- /dev/null +++ b/wasm-workspace/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = [ + "crates/one", + "crates/two", +] diff --git a/wasm-workspace/crates/one/Cargo.toml b/wasm-workspace/crates/one/Cargo.toml new file mode 100644 index 0000000..2c89270 --- /dev/null +++ b/wasm-workspace/crates/one/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "wasm-one" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +reqwest = "0.11.0" +async-std = "1" +tracing = "0.1" +tracing-futures = "0.2" +serde = "1" +serde_json = "1" diff --git a/wasm-workspace/crates/one/src/main.rs b/wasm-workspace/crates/one/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/wasm-workspace/crates/one/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/wasm-workspace/crates/two/Cargo.toml b/wasm-workspace/crates/two/Cargo.toml new file mode 100644 index 0000000..d907f29 --- /dev/null +++ b/wasm-workspace/crates/two/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "wasm-two" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = "3" diff --git a/wasm-workspace/crates/two/src/main.rs b/wasm-workspace/crates/two/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/wasm-workspace/crates/two/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +}