update save as well

This commit is contained in:
Bishal Prasad 2022-12-06 18:26:58 +00:00
parent d95c048983
commit ac8fc97c06
12 changed files with 700 additions and 569 deletions

View file

@ -6,9 +6,7 @@ export enum Inputs {
}
export enum Outputs {
CacheHit = "cache-hit",
Key = "key",
Path = "path"
CacheHit = "cache-hit"
}
export enum State {

View file

@ -1,16 +0,0 @@
import * as core from "@actions/core";
export interface IOutputSetter {
setOutput(key: string, value: string): void;
setState(key: string, value: string): void;
}
export class StateOutputSetter implements IOutputSetter {
setOutput = core.setOutput;
setState = core.saveState;
}
export class NonStateOuputSetter implements IOutputSetter {
setOutput = core.setOutput;
setState = core.setOutput;
}

View file

@ -1,8 +1,10 @@
import { StateOutputSetter } from "./outputSetter";
import run from "./restoreImpl";
import { StateProvider } from "./stateProvider";
import restoreImpl from "./restoreImpl";
async function restore(): Promise<void> {
await run(new StateOutputSetter());
async function run(): Promise<void> {
await restoreImpl(new StateProvider());
}
export default restore;
run();
export default run;

View file

@ -2,10 +2,10 @@ import * as cache from "@actions/cache";
import * as core from "@actions/core";
import { Events, Inputs, Outputs, State } from "./constants";
import { IOutputSetter } from "./outputSetter";
import { IStateProvider } from "./stateProvider";
import * as utils from "./utils/actionUtils";
async function run(outputter: IOutputSetter): Promise<string | undefined> {
async function restoreImpl(outputter: IStateProvider): Promise<string | undefined> {
try {
if (!utils.isCacheFeatureAvailable()) {
utils.setCacheHitOutput(false);
@ -48,15 +48,14 @@ async function run(outputter: IOutputSetter): Promise<string | undefined> {
}
// Store the matched cache key in states
//utils.setCacheState(cacheKey);
outputter.setState(State.CacheMatchedKey, cacheKey);
const isExactKeyMatch = utils.isExactKeyMatch(
core.getInput(Inputs.Key, { required: true }),
cacheKey
);
//utils.setCacheHitOutput(isExactKeyMatch);
outputter.setOutput(Outputs.CacheHit, isExactKeyMatch.toString());
core.setOutput(Outputs.CacheHit, isExactKeyMatch.toString());
core.info(`Cache restored from key: ${cacheKey}`);
return cacheKey;
@ -65,4 +64,4 @@ async function run(outputter: IOutputSetter): Promise<string | undefined> {
}
}
export default run;
export default restoreImpl;

View file

@ -1,8 +1,10 @@
import { NonStateOuputSetter } from "./outputSetter";
import run from "./restoreImpl";
import restoreImpl from "./restoreImpl";
import { NullStateProvider } from "./stateProvider";
async function restoreOnly(): Promise<void> {
await run(new NonStateOuputSetter());
async function run(): Promise<void> {
await restoreImpl(new NullStateProvider());
}
export default restoreOnly;
run();
export default run;

View file

@ -1,61 +1,8 @@
import * as cache from "@actions/cache";
import * as core from "@actions/core";
import { Events, Inputs, State } from "./constants";
import * as utils from "./utils/actionUtils";
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
// throw an uncaught exception. Instead of failing this action, just warn.
process.on("uncaughtException", e => utils.logWarning(e.message));
import saveImpl from "./saveImpl";
import { StateProvider } from "./stateProvider";
async function run(): Promise<void> {
try {
if (!utils.isCacheFeatureAvailable()) {
return;
}
if (!utils.isValidEvent()) {
utils.logWarning(
`Event Validation Error: The event type ${
process.env[Events.Key]
} is not supported because it's not tied to a branch or tag ref.`
);
return;
}
const state = utils.getCacheState();
// Inputs are re-evaluted before the post action, so we want the original key used for restore
const primaryKey =
core.getState(State.CachePrimaryKey) || core.getInput(Inputs.Key);
if (!primaryKey) {
utils.logWarning(`Error retrieving key from state.`);
return;
}
if (utils.isExactKeyMatch(primaryKey, state)) {
core.info(
`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`
);
return;
}
const cachePaths = utils.getInputAsArray(Inputs.Path, {
required: true
});
const cacheId = await cache.saveCache(cachePaths, primaryKey, {
uploadChunkSize: utils.getInputAsInt(Inputs.UploadChunkSize)
});
if (cacheId != -1) {
core.info(`Cache saved with key: ${primaryKey}`);
}
} catch (error: unknown) {
utils.logWarning((error as Error).message);
}
await saveImpl(new StateProvider());
}
run();

65
src/saveImpl.ts Normal file
View file

@ -0,0 +1,65 @@
import * as cache from "@actions/cache";
import * as core from "@actions/core";
import { Events, Inputs, State } from "./constants";
import { IStateProvider } from "./stateProvider";
import * as utils from "./utils/actionUtils";
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
// throw an uncaught exception. Instead of failing this action, just warn.
process.on("uncaughtException", e => utils.logWarning(e.message));
async function saveImpl(stateProvider: IStateProvider): Promise<void> {
try {
if (!utils.isCacheFeatureAvailable()) {
return;
}
if (!utils.isValidEvent()) {
utils.logWarning(
`Event Validation Error: The event type ${
process.env[Events.Key]
} is not supported because it's not tied to a branch or tag ref.`
);
return;
}
// If restore has stored a primary key in state, reuse that
// Else re-evaluate from inputs
const primaryKey =
stateProvider.getState(State.CachePrimaryKey) ||
core.getInput(Inputs.Key);
if (!primaryKey) {
utils.logWarning(`Error retrieving key from state.`);
return;
}
// If matched restore key is same as primary key, then do not save cache
// NO-OP in case of SaveOnly action
const state = stateProvider.getCacheState();
if (utils.isExactKeyMatch(primaryKey, state)) {
core.info(
`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`
);
return;
}
const cachePaths = utils.getInputAsArray(Inputs.Path, {
required: true
});
const cacheId = await cache.saveCache(cachePaths, primaryKey, {
uploadChunkSize: utils.getInputAsInt(Inputs.UploadChunkSize)
});
if (cacheId != -1) {
core.info(`Cache saved with key: ${primaryKey}`);
}
} catch (error: unknown) {
utils.logWarning((error as Error).message);
}
}
export default saveImpl;

10
src/saveOnly.ts Normal file
View file

@ -0,0 +1,10 @@
import saveImpl from "./saveImpl";
import { NullStateProvider } from "./stateProvider";
async function run(): Promise<void> {
await saveImpl(new NullStateProvider());
}
run();
export default run;

42
src/stateProvider.ts Normal file
View file

@ -0,0 +1,42 @@
import * as core from "@actions/core";
import { State } from "./constants";
export interface IStateProvider {
//setOutput(key: string, value: string): void;
setState(key: string, value: string): void;
getState(key: string): string;
getCacheState(): string | undefined;
}
class StateProviderBase implements IStateProvider {
getCacheState(): string | undefined {
const cacheKey = this.getState(State.CacheMatchedKey);
if (cacheKey) {
core.debug(`Cache state/key: ${cacheKey}`);
return cacheKey;
}
return undefined;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
setState = (key: string, value: string) => {};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
getState = (key: string) => "";
}
export class StateProvider extends StateProviderBase {
//setOutput = core.setOutput;
setState = core.saveState;
getState = core.getState;
}
export class NullStateProvider extends StateProviderBase {
//setOutput = core.setOutput;
setState = core.setOutput;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
getState = (key: string) => "";
}

View file

@ -1,7 +1,7 @@
import * as cache from "@actions/cache";
import * as core from "@actions/core";
import { Outputs, RefKey, State } from "../constants";
import { Outputs, RefKey } from "../constants";
export function isGhes(): boolean {
const ghUrl = new URL(
@ -19,30 +19,10 @@ export function isExactKeyMatch(key: string, cacheKey?: string): boolean {
);
}
export function setCacheState(state: string): void {
core.saveState(State.CacheMatchedKey, state);
}
export function setCacheHitOutput(isCacheHit: boolean): void {
core.setOutput(Outputs.CacheHit, isCacheHit.toString());
}
export function setOutputAndState(key: string, cacheKey?: string): void {
setCacheHitOutput(isExactKeyMatch(key, cacheKey));
// Store the matched cache key if it exists
cacheKey && setCacheState(cacheKey);
}
export function getCacheState(): string | undefined {
const cacheKey = core.getState(State.CacheMatchedKey);
if (cacheKey) {
core.debug(`Cache state/key: ${cacheKey}`);
return cacheKey;
}
return undefined;
}
export function logWarning(message: string): void {
const warningPrefix = "[warning]";
core.info(`${warningPrefix}${message}`);