Skip to content

Commit

Permalink
save cache on the end of the job (#1328)
Browse files Browse the repository at this point in the history
* improve document of cache

* save cache on the end of the job

* npm run format

* fix the path for versions json

* fix the package path

* fix the package path in the tests

* fix path
  • Loading branch information
shogo82148 committed Nov 12, 2022
1 parent cae9fc4 commit a04ef8d
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 39 deletions.
7 changes: 5 additions & 2 deletions README.md
Expand Up @@ -129,13 +129,16 @@ The argument for CPAN module installer.

### `install-modules`

List of one or more CPAN modules, separated by white spaces.
List of one or more CPAN modules, separated by white spaces (space or new line).
They are installed `local` directory on your working directory.

- Default: Nothing

### `enable-modules-cache`

Enable caching when install CPAN modules. `true` and `false` are accepted.
Enable caching when install CPAN modules. `true` enables cache and `false` disable it.
The key of cache will generated by the hash of `cpanfile` in the repository root.
Modules in the `local` directory are cached in the end of the job.

- Default: `true`

Expand Down
6 changes: 5 additions & 1 deletion action.yml
Expand Up @@ -52,9 +52,13 @@ outputs:
The digest of perl -V.
It contains useful information to use as the cache key,
e.g. the platform, the version of perl, the compiler option for building perl.
cache-hit:
description: 'A boolean value to indicate if a cache was hit'
runs:
using: "node16"
main: "dist/index.js"
main: "dist/setup/index.js"
post: 'dist/cache-save/index.js'
post-if: success()
branding:
icon: "play"
color: "blue"
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -7,7 +7,7 @@
"build": "tsc",
"format": "prettier --write **/*.ts",
"format-check": "prettier --check **/*.ts",
"package": "ncc build --source-map --license licenses.txt",
"package": "tsc && ncc build -o dist/setup --source-map --license licenses.txt src/setup-perl.ts && ncc build -o dist/cache-save --source-map --license licenses.txt src/cache-save.ts",
"test": "jest"
},
"repository": {
Expand Down
1 change: 1 addition & 0 deletions prepare.sh
Expand Up @@ -35,6 +35,7 @@ git push origin main
: build the action
npm ci
npm run build
rm -rf dist
npm run package
perl -ne 'print unless m(^/dist/$)' -i .gitignore

Expand Down
41 changes: 41 additions & 0 deletions src/cache-save.ts
@@ -0,0 +1,41 @@
import * as core from "@actions/core";
import * as cache from "@actions/cache";
import { State } from "./constants";

async function run() {
try {
const cachePath = core.getState(State.CachePath);
const key = core.getState(State.CachePrimaryKey);
const cachedKey = core.getState(State.CacheMatchedKey);
const paths = [cachePath];
// save cache
if (cachedKey !== key) {
core.info(`saving cache for ${key}.`);
try {
await cache.saveCache(paths, key);
} catch (error) {
if (error instanceof Error) {
if (error.name === cache.ValidationError.name) {
throw error;
} else if (error.name === cache.ReserveCacheError.name) {
core.info(error.message);
} else {
core.info(`[warning]${error.message}`);
}
} else {
core.info(`[warning]${error}`);
}
}
} else {
core.info(`cache for ${key} already exists, skip saving.`);
}
} catch (error) {
if (error instanceof Error) {
core.setFailed(error);
} else {
core.setFailed(`${error}`);
}
}
}

run();
9 changes: 9 additions & 0 deletions src/constants.ts
@@ -0,0 +1,9 @@
export enum State {
CachePrimaryKey = "CACHE_KEY",
CacheMatchedKey = "CACHE_RESULT",
CachePath = "CACHE_PATH",
}

export enum Outputs {
CacheHit = "cache-hit",
}
36 changes: 11 additions & 25 deletions src/cpan-installer.ts
Expand Up @@ -8,6 +8,8 @@ import * as fs from "fs";
import * as stream from "stream";
import * as util from "util";
import * as path from "path";
import { State, Outputs } from "./constants";
import { getPackagePath } from "./utils";

export interface Options {
// the digest of `perl -V`
Expand Down Expand Up @@ -72,8 +74,10 @@ export async function install(opt: Options): Promise<void> {
}
if (cachedKey) {
core.info(`Found cache for key: ${cachedKey}`);
core.setOutput(Outputs.CacheHit, "true");
} else {
core.info(`cache not found for input keys: ${key}, ${restoreKeys.join(", ")}`);
core.setOutput(Outputs.CacheHit, "false");
}
}

Expand All @@ -88,27 +92,9 @@ export async function install(opt: Options): Promise<void> {
core.exportVariable("PERL5LIB", libPath + path.delimiter + libArchPath + path.delimiter + process.env["PERL5LIB"]);

if (opt.enable_modules_cache) {
// save cache
if (cachedKey !== key) {
core.info(`saving cache for ${key}.`);
try {
await cache.saveCache(paths, key);
} catch (error) {
if (error instanceof Error) {
if (error.name === cache.ValidationError.name) {
throw error;
} else if (error.name === cache.ReserveCacheError.name) {
core.info(error.message);
} else {
core.info(`[warning]${error.message}`);
}
} else {
core.info(`[warning]${error}`);
}
}
} else {
core.info(`cache for ${key} already exists, skip saving.`);
}
core.saveState(State.CachePath, cachePath);
core.saveState(State.CachePrimaryKey, key);
core.saveState(State.CacheMatchedKey, cachedKey);
}

return;
Expand Down Expand Up @@ -151,7 +137,7 @@ function hashString(s: string): string {

async function installWithCpanm(opt: Options): Promise<void> {
const perl = path.join(opt.toolPath, "bin", "perl");
const cpanm = path.join(__dirname, "..", "bin", "cpanm");
const cpanm = path.join(getPackagePath(), "bin", "cpanm");
const workingDirectory = path.join(process.cwd(), opt.working_directory || ".");
const execOpt = {
cwd: workingDirectory,
Expand All @@ -174,7 +160,7 @@ async function installWithCpanm(opt: Options): Promise<void> {

async function installWithCpm(opt: Options): Promise<void> {
const perl = path.join(opt.toolPath, "bin", "perl");
const cpm = path.join(__dirname, "..", "bin", "cpm");
const cpm = path.join(getPackagePath(), "bin", "cpm");
const workingDirectory = path.join(process.cwd(), opt.working_directory || ".");
const execOpt = {
cwd: workingDirectory,
Expand All @@ -198,7 +184,7 @@ async function installWithCpm(opt: Options): Promise<void> {

async function installWithCarton(opt: Options): Promise<void> {
const perl = path.join(opt.toolPath, "bin", "perl");
const carton = path.join(__dirname, "..", "bin", "carton");
const carton = path.join(getPackagePath(), "bin", "carton");
const workingDirectory = path.join(process.cwd(), opt.working_directory || ".");
const execOpt = {
cwd: workingDirectory,
Expand All @@ -213,7 +199,7 @@ async function installWithCarton(opt: Options): Promise<void> {
}
const modules = splitModules(opt.install_modules);
if (modules.length > 0) {
const cpanm = path.join(__dirname, "..", "bin", "cpanm");
const cpanm = path.join(getPackagePath(), "bin", "cpanm");
const args = [cpanm, "--local-lib-contained", "local", "--notest"];
if (core.isDebug()) {
args.push("--verbose");
Expand Down
5 changes: 3 additions & 2 deletions src/installer.ts
Expand Up @@ -5,6 +5,7 @@ import { readFile } from "fs/promises";
import * as path from "path";
import * as semver from "semver";
import * as tcp from "./tool-cache-port";
import { getPackagePath } from "./utils";

const osPlat = os.platform();
const osArch = os.arch();
Expand All @@ -22,7 +23,7 @@ async function readJSON<T>(path: string): Promise<T> {
return JSON.parse(data) as T;
}
async function getAvailableVersions(): Promise<string[]> {
const filename = path.join(__dirname, "..", "versions", `${osPlat}.json`);
const filename = path.join(getPackagePath(), "versions", `${osPlat}.json`);
return readJSON<string[]>(filename);
}

Expand Down Expand Up @@ -106,7 +107,7 @@ interface PackageVersion {
}

async function getDownloadUrl(filename: string): Promise<string> {
const pkg = path.join(__dirname, "..", "package.json");
const pkg = path.join(getPackagePath(), "package.json");
const info = await readJSON<PackageVersion>(pkg);
const actionsVersion = info.version;
return `https://github.com/shogo82148/actions-setup-perl/releases/download/v${actionsVersion}/${filename}`;
Expand Down
14 changes: 7 additions & 7 deletions src/setup-perl.ts
Expand Up @@ -4,8 +4,8 @@ import * as installer from "./installer";
import * as path from "path";
import * as crypto from "crypto";
import * as strawberry from "./strawberry";
import * as utils from "./utils";
import * as cpan from "./cpan-installer";
import { getPackagePath, parseBoolean } from "./utils";

async function run() {
try {
Expand All @@ -19,7 +19,7 @@ async function run() {
await core.group("install perl", async () => {
let thread: boolean;
if (platform === "win32") {
thread = utils.parseBoolean(multiThread || "true");
thread = parseBoolean(multiThread || "true");
if (dist === "strawberry" && !thread) {
core.warning("non-thread Strawberry Perl is not provided.");
}
Expand All @@ -30,7 +30,7 @@ async function run() {
);
dist = "default";
}
thread = utils.parseBoolean(multiThread || "false");
thread = parseBoolean(multiThread || "false");
}

switch (dist) {
Expand All @@ -47,14 +47,14 @@ async function run() {
perlHash = await digestOfPerlVersion(result.path);
core.setOutput("perl-hash", perlHash);

const matchersPath = path.join(__dirname, "..", "scripts");
const matchersPath = path.join(getPackagePath(), "scripts");
console.log(`::add-matcher::${path.join(matchersPath, "perl.json")}`);

// for pre-installed scripts
core.addPath(path.join(__dirname, "..", "bin"));
core.addPath(path.join(getPackagePath(), "bin"));

// for pre-installed modules
core.exportVariable("PERL5LIB", path.join(__dirname, "..", "scripts", "lib"));
core.exportVariable("PERL5LIB", path.join(getPackagePath(), "scripts", "lib"));
});

await core.group("install CPAN modules", async () => {
Expand All @@ -64,7 +64,7 @@ async function run() {
install_modules_with: core.getInput("install-modules-with"),
install_modules_args: core.getInput("install-modules-args"),
install_modules: core.getInput("install-modules"),
enable_modules_cache: utils.parseBoolean(core.getInput("enable-modules-cache")),
enable_modules_cache: parseBoolean(core.getInput("enable-modules-cache")),
working_directory: core.getInput("working-directory"),
});
});
Expand Down
3 changes: 2 additions & 1 deletion src/strawberry.ts
Expand Up @@ -4,6 +4,7 @@ import * as path from "path";
import * as semver from "semver";
import * as fs from "fs";
import * as tcp from "./tool-cache-port";
import { getPackagePath } from "./utils";

interface PerlVersion {
version: string;
Expand Down Expand Up @@ -36,7 +37,7 @@ export interface Result {
// 64 bit Portable binaries are not available with Perl 5.12.x and older.
async function getAvailableVersions(): Promise<PerlVersion[]> {
return new Promise<PerlVersion[]>((resolve, reject) => {
fs.readFile(path.join(__dirname, "..", "versions", `strawberry.json`), (err, data) => {
fs.readFile(path.join(getPackagePath(), "versions", `strawberry.json`), (err, data) => {
if (err) {
reject(err);
}
Expand Down
9 changes: 9 additions & 0 deletions src/utils.ts
@@ -1,3 +1,5 @@
import * as path from "path";

export function parseBoolean(s: string): boolean {
// YAML 1.0 compatible boolean values
switch (s) {
Expand All @@ -22,3 +24,10 @@ export function parseBoolean(s: string): boolean {
}
throw `invalid boolean value: ${s}`;
}

export function getPackagePath(): string {
if (process.env["ACTIONS_SETUP_PERL_TESTING"]) {
return path.join(__dirname, "..");
}
return path.join(__dirname, "..", "..");
}

0 comments on commit a04ef8d

Please sign in to comment.