Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

save cache on the end of the job #1328

Merged
merged 7 commits into from Nov 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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, "..", "..");
}