Skip to content

Commit

Permalink
Implement built-in cache support (#8)
Browse files Browse the repository at this point in the history
Resolves #2.

Using [@actions/toolkit](https://github.com/actions/toolkit) Scarb cache
saving/restoring is now supported out of the box. Cache key is based on
sha256 has of Scarb.toml file which is retreived by path returned from
`scarb manifest-path`. Right now cache directories paths are hardcoded
into the action but in the future there is a possibility to make a
command in Scarb that will return cache directory as other package
managers such as npm or yarn are doing.
  • Loading branch information
szymmis authored Aug 2, 2023
1 parent b4a66bd commit 321b326
Show file tree
Hide file tree
Showing 16 changed files with 122,957 additions and 3 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Install Scarb

Sets up [Scarb] in your GitHub Actions workflow.
Sets up [Scarb] in your GitHub Actions workflow supporting caching out of the box.

## Example workflow

Expand Down
4 changes: 3 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ outputs:
description: The version of the installed Scarb
runs:
using: "node16"
main: "dist/index.js"
main: "dist/setup/index.js"
post: "dist/cache-save/index.js"
post-if: success()
59,434 changes: 59,434 additions & 0 deletions dist/cache-save/index.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions dist/cache-save/index.js.map

Large diffs are not rendered by default.

997 changes: 997 additions & 0 deletions dist/cache-save/licenses.txt

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions dist/cache-save/sourcemap-register.js

Large diffs are not rendered by default.

60,609 changes: 60,609 additions & 0 deletions dist/setup/index.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions dist/setup/index.js.map

Large diffs are not rendered by default.

1,009 changes: 1,009 additions & 0 deletions dist/setup/licenses.txt

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions dist/setup/sourcemap-register.js

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions lib/cache-restore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as core from "@actions/core";
import * as cache from "@actions/cache";

import fs from "fs/promises";

import { getCacheDirectory, getCacheKey, State } from "./cache-utils";

export async function restoreCache() {
const cacheDir = getCacheDirectory();
await fs.mkdir(cacheDir, { recursive: true });

core.info(`Restoring Scarb cache into ${cacheDir}`);

const primaryKey = await getCacheKey();
core.info(`Cache primary key is ${primaryKey}`);
core.saveState(State.CachePrimaryKey, primaryKey);

const matchedKey = await cache.restoreCache([cacheDir], primaryKey);
if (!matchedKey) {
core.info(`Cache entry not found.`);
return;
}

core.saveState(State.CacheMatchedKey, matchedKey);
}
21 changes: 21 additions & 0 deletions lib/cache-save.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as core from "@actions/core";
import * as cache from "@actions/cache";

import { getCacheDirectory, State } from "./cache-utils";

async function saveCache() {
try {
const primaryKey = core.getState(State.CachePrimaryKey);
const matchedKey = core.getState(State.CacheMatchedKey);

if (primaryKey !== matchedKey) {
await cache.saveCache([getCacheDirectory()], primaryKey);
} else {
core.info(`Cache hit occurred, not saving cache.`);
}
} catch (e) {
core.error(e);
}
}

saveCache();
49 changes: 49 additions & 0 deletions lib/cache-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import * as exec from "@actions/exec";
import * as glob from "@actions/glob";

import os from "os";
import path from "path";

export const State = {
CachePrimaryKey: "primary_key",
CacheMatchedKey: "matched_key",
};

export function getCacheDirectory() {
const platform = os.platform();
const home = process.env.HOME;

switch (platform) {
case "linux":
return path.join(home, ".cache/scarb");
case "darwin":
return path.join(home, `Library/Caches/com.swmansion.Scarb`);
case "win32":
return path.join(process.env.APPDATA, "swmansion/Scarb/config");
default:
throw new Error(`Caching not available for ${platform} platform.`);
}
}

export async function getCacheKey() {
const platform = process.env.RUNNER_OS;
const fileHash = await glob.hashFiles(await getScarbManifestPath());

if (!fileHash) {
throw new Error(
"Unable to hash Scarb.toml file, cannot cache dependencies.",
);
}

return `scarb-cache-${platform}-${fileHash}`.toLowerCase();
}

async function getScarbManifestPath() {
const { stdout, exitCode } = await exec.getExecOutput("scarb manifest-path");

if (exitCode > 0) {
throw new Error("Unable to resolve Scarb.toml path.");
}

return stdout.trim();
}
9 changes: 9 additions & 0 deletions lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as tc from "@actions/tool-cache";
import { determineVersion } from "./versions";
import { downloadScarb } from "./download";
import { getOsTriplet } from "./platform";
import { restoreCache } from "./cache-restore";

const REPO = "software-mansion/scarb";

Expand All @@ -30,6 +31,14 @@ export default async function main() {
core.setOutput("scarb-version", scarbVersion);
core.addPath(path.join(scarbPrefix, "bin"));
});

await restoreCache().catch((e) => {
core.error(
`There was an error when restoring cache: ${
e instanceof Error ? e.message : e
}`,
);
});
} catch (e) {
core.setFailed(e);
}
Expand Down
Loading

0 comments on commit 321b326

Please sign in to comment.