From 4827442d41bb781aac8a06748fdd74a52788c315 Mon Sep 17 00:00:00 2001 From: Vincent Clemson Date: Sat, 18 Jun 2022 15:53:43 -0400 Subject: [PATCH 1/9] Add `reeval` & `only-restore` boolean input parameters * implement only-restore within save --- .gitignore | 3 ++ action.yml | 8 ++++ src/constants.ts | 2 + src/save.ts | 99 +++++++++++++++++++++++++----------------------- 4 files changed, 64 insertions(+), 48 deletions(-) diff --git a/.gitignore b/.gitignore index fda65d8..977c2c3 100644 --- a/.gitignore +++ b/.gitignore @@ -94,3 +94,6 @@ typings/ # Text editor files .vscode/ + +# OS +.DS_Store diff --git a/action.yml b/action.yml index 3e158e3..ed7e330 100644 --- a/action.yml +++ b/action.yml @@ -14,6 +14,14 @@ inputs: upload-chunk-size: description: 'The chunk size used to split up large files during upload, in bytes' required: false + reeval: + description: 'Boolean. Whether to reevaluate the key argument in post. Set to TRUE if you would like your cache key set after your job's steps are complete.' + required: false + default: false + only-restore: + description: 'Boolean. Whether to only perform cache restoration and NOT the save post run step.' + required: false + default: false outputs: cache-hit: description: 'A boolean value to indicate an exact match was found for the primary key' diff --git a/src/constants.ts b/src/constants.ts index 133f47d..6d2ec97 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,6 +1,8 @@ export enum Inputs { Key = "key", + OnlyRestore = "only-restore", Path = "path", + Reeval = "reeval", RestoreKeys = "restore-keys", UploadChunkSize = "upload-chunk-size" } diff --git a/src/save.ts b/src/save.ts index 7b333fb..1644b8b 100644 --- a/src/save.ts +++ b/src/save.ts @@ -10,57 +10,60 @@ import * as utils from "./utils/actionUtils"; process.on("uncaughtException", e => utils.logWarning(e.message)); async function run(): Promise { - 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); - 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 save = ! core.getBooleanInput(Inputs.OnlyRestore); + if (save) { try { - await cache.saveCache(cachePaths, primaryKey, { - uploadChunkSize: utils.getInputAsInt(Inputs.UploadChunkSize) - }); - core.info(`Cache saved with key: ${primaryKey}`); - } catch (error: unknown) { - const typedError = error as Error; - if (typedError.name === cache.ValidationError.name) { - throw error; - } else if (typedError.name === cache.ReserveCacheError.name) { - core.info(typedError.message); - } else { - utils.logWarning(typedError.message); + 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); + 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 + }); + + try { + await cache.saveCache(cachePaths, primaryKey, { + uploadChunkSize: utils.getInputAsInt(Inputs.UploadChunkSize) + }); + core.info(`Cache saved with key: ${primaryKey}`); + } catch (error: unknown) { + const typedError = error as Error; + if (typedError.name === cache.ValidationError.name) { + throw error; + } else if (typedError.name === cache.ReserveCacheError.name) { + core.info(typedError.message); + } else { + utils.logWarning(typedError.message); + } + } + } catch (error: unknown) { + utils.logWarning((error as Error).message); } - } catch (error: unknown) { - utils.logWarning((error as Error).message); } } From 02fa69bea4b9c3bd204187fe7d6408fe1ee60453 Mon Sep 17 00:00:00 2001 From: Vincent Clemson Date: Sat, 18 Jun 2022 17:20:32 -0400 Subject: [PATCH 2/9] build action & add jobs to Tests workflow for only-restore option * add regular & proxy server jobs * run job between save & restore jobs to test that only-restore option works with consecutive restores --- .github/workflows/workflow.yml | 48 ++++++++++++++++++++ dist/restore/index.js | 4 +- dist/save/index.js | 83 ++++++++++++++++++---------------- 3 files changed, 93 insertions(+), 42 deletions(-) diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 48f1ccb..2ba59e9 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -71,6 +71,30 @@ jobs: path: | test-cache ~/test-cache + test-only-restore: + needs: test-restore + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macOS-latest] + fail-fast: false + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Restore cache + uses: ./ + with: + only-restore: true + key: test-${{ runner.os }}-${{ github.run_id }} + path: | + test-cache + ~/test-cache + - name: Verify cache files in working directory + shell: bash + run: __tests__/verify-cache-files.sh ${{ runner.os }} test-cache + - name: Verify cache files outside working directory + shell: bash + run: __tests__/verify-cache-files.sh ${{ runner.os }} ~/test-cache test-restore: needs: test-save strategy: @@ -118,6 +142,30 @@ jobs: with: key: test-proxy-${{ github.run_id }} path: test-cache + test-proxy-only-restore: + needs: test-proxy-save + runs-on: ubuntu-latest + container: + image: ubuntu:latest + options: --dns 127.0.0.1 + services: + squid-proxy: + image: datadog/squid:latest + ports: + - 3128:3128 + env: + https_proxy: http://squid-proxy:3128 + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Restore cache + uses: ./ + with: + only-restore: true + key: test-proxy-${{ github.run_id }} + path: test-cache + - name: Verify cache + run: __tests__/verify-cache-files.sh proxy test-cache test-proxy-restore: needs: test-proxy-save runs-on: ubuntu-latest diff --git a/dist/restore/index.js b/dist/restore/index.js index 9351a66..e15a582 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -4607,7 +4607,9 @@ exports.RefKey = exports.Events = exports.State = exports.Outputs = exports.Inpu var Inputs; (function (Inputs) { Inputs["Key"] = "key"; + Inputs["OnlyRestore"] = "only-restore"; Inputs["Path"] = "path"; + Inputs["Reeval"] = "reeval"; Inputs["RestoreKeys"] = "restore-keys"; Inputs["UploadChunkSize"] = "upload-chunk-size"; })(Inputs = exports.Inputs || (exports.Inputs = {})); @@ -37317,8 +37319,6 @@ function createTar(archiveFolder, sourceDirectories, compressionMethod) { ...getCompressionProgram(), '-cf', cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), - '--exclude', - cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '-P', '-C', workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), diff --git a/dist/save/index.js b/dist/save/index.js index 983cb5d..3e76c65 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -4607,7 +4607,9 @@ exports.RefKey = exports.Events = exports.State = exports.Outputs = exports.Inpu var Inputs; (function (Inputs) { Inputs["Key"] = "key"; + Inputs["OnlyRestore"] = "only-restore"; Inputs["Path"] = "path"; + Inputs["Reeval"] = "reeval"; Inputs["RestoreKeys"] = "restore-keys"; Inputs["UploadChunkSize"] = "upload-chunk-size"; })(Inputs = exports.Inputs || (exports.Inputs = {})); @@ -37317,8 +37319,6 @@ function createTar(archiveFolder, sourceDirectories, compressionMethod) { ...getCompressionProgram(), '-cf', cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), - '--exclude', - cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '-P', '-C', workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), @@ -46770,50 +46770,53 @@ const utils = __importStar(__webpack_require__(443)); process.on("uncaughtException", e => utils.logWarning(e.message)); function run() { return __awaiter(this, void 0, void 0, function* () { - try { - if (!utils.isCacheFeatureAvailable()) { - return; - } - if (!utils.isValidEvent()) { - utils.logWarning(`Event Validation Error: The event type ${process.env[constants_1.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(constants_1.State.CachePrimaryKey); - 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(constants_1.Inputs.Path, { - required: true - }); + const save = !core.getBooleanInput(constants_1.Inputs.OnlyRestore); + if (save) { try { - yield cache.saveCache(cachePaths, primaryKey, { - uploadChunkSize: utils.getInputAsInt(constants_1.Inputs.UploadChunkSize) + if (!utils.isCacheFeatureAvailable()) { + return; + } + if (!utils.isValidEvent()) { + utils.logWarning(`Event Validation Error: The event type ${process.env[constants_1.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(constants_1.State.CachePrimaryKey); + 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(constants_1.Inputs.Path, { + required: true }); - core.info(`Cache saved with key: ${primaryKey}`); + try { + yield cache.saveCache(cachePaths, primaryKey, { + uploadChunkSize: utils.getInputAsInt(constants_1.Inputs.UploadChunkSize) + }); + core.info(`Cache saved with key: ${primaryKey}`); + } + catch (error) { + const typedError = error; + if (typedError.name === cache.ValidationError.name) { + throw error; + } + else if (typedError.name === cache.ReserveCacheError.name) { + core.info(typedError.message); + } + else { + utils.logWarning(typedError.message); + } + } } catch (error) { - const typedError = error; - if (typedError.name === cache.ValidationError.name) { - throw error; - } - else if (typedError.name === cache.ReserveCacheError.name) { - core.info(typedError.message); - } - else { - utils.logWarning(typedError.message); - } + utils.logWarning(error.message); } } - catch (error) { - utils.logWarning(error.message); - } }); } run(); From f20d3c830ca91bfddbf7f6ea7ba570205723937f Mon Sep 17 00:00:00 2001 From: Vincent Clemson Date: Sat, 18 Jun 2022 17:38:57 -0400 Subject: [PATCH 3/9] fix description using double quotes due to apostrophe --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index ed7e330..99cd388 100644 --- a/action.yml +++ b/action.yml @@ -15,7 +15,7 @@ inputs: description: 'The chunk size used to split up large files during upload, in bytes' required: false reeval: - description: 'Boolean. Whether to reevaluate the key argument in post. Set to TRUE if you would like your cache key set after your job's steps are complete.' + description: "Boolean. Whether to reevaluate the key argument in post. Set to TRUE if you would like your cache key set after your job's steps are complete." required: false default: false only-restore: From 2807da784fd5c6b7707c0ad2a98a5376c199f496 Mon Sep 17 00:00:00 2001 From: Vincent Clemson Date: Sat, 18 Jun 2022 17:50:09 -0400 Subject: [PATCH 4/9] fix `needs` option for `test-only-restore` job * also format code with prettier --- .github/workflows/workflow.yml | 2 +- src/save.ts | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 2ba59e9..138da32 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -72,7 +72,7 @@ jobs: test-cache ~/test-cache test-only-restore: - needs: test-restore + needs: test-save strategy: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] diff --git a/src/save.ts b/src/save.ts index 1644b8b..d37a086 100644 --- a/src/save.ts +++ b/src/save.ts @@ -10,13 +10,13 @@ import * as utils from "./utils/actionUtils"; process.on("uncaughtException", e => utils.logWarning(e.message)); async function run(): Promise { - const save = ! core.getBooleanInput(Inputs.OnlyRestore); + const save = !core.getBooleanInput(Inputs.OnlyRestore); if (save) { try { if (!utils.isCacheFeatureAvailable()) { return; } - + if (!utils.isValidEvent()) { utils.logWarning( `Event Validation Error: The event type ${ @@ -25,27 +25,27 @@ async function run(): Promise { ); 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); 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 }); - + try { await cache.saveCache(cachePaths, primaryKey, { uploadChunkSize: utils.getInputAsInt(Inputs.UploadChunkSize) From 78b8f18c17d30850eeb90bdf189ee098da45314f Mon Sep 17 00:00:00 2001 From: Vincent Clemson Date: Sat, 18 Jun 2022 18:18:08 -0400 Subject: [PATCH 5/9] update dependencies with npm ci - rebuild --- dist/restore/index.js | 2 ++ dist/save/index.js | 2 ++ 2 files changed, 4 insertions(+) diff --git a/dist/restore/index.js b/dist/restore/index.js index e15a582..a1bc1b5 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -37319,6 +37319,8 @@ function createTar(archiveFolder, sourceDirectories, compressionMethod) { ...getCompressionProgram(), '-cf', cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), + '--exclude', + cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '-P', '-C', workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), diff --git a/dist/save/index.js b/dist/save/index.js index 3e76c65..c69ee3a 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -37319,6 +37319,8 @@ function createTar(archiveFolder, sourceDirectories, compressionMethod) { ...getCompressionProgram(), '-cf', cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), + '--exclude', + cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '-P', '-C', workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), From 226c25a2b7fffde871f82a09a658449e8be06e86 Mon Sep 17 00:00:00 2001 From: Vincent Clemson Date: Sun, 19 Jun 2022 00:48:07 -0400 Subject: [PATCH 6/9] add primary key reevaluation boolean logic & jobs to Tests workflow --- .github/workflows/workflow.yml | 28 ++++++++++++++++++++++------ src/save.ts | 11 +++++++++-- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 138da32..20d22f7 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -53,6 +53,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] + reeval: [false, true] fail-fast: false runs-on: ${{ matrix.os }} steps: @@ -67,7 +68,8 @@ jobs: - name: Save cache uses: ./ with: - key: test-${{ runner.os }}-${{ github.run_id }} + reeval: ${{ matrix.reeval }} + key: test-${{ runner.os }}-${{ github.run_id }}-${{ matrix.reeval }} path: | test-cache ~/test-cache @@ -85,7 +87,8 @@ jobs: uses: ./ with: only-restore: true - key: test-${{ runner.os }}-${{ github.run_id }} + reeval: ${{ matrix.reeval }} + key: test-${{ runner.os }}-${{ github.run_id }}-${{ matrix.reeval }} path: | test-cache ~/test-cache @@ -108,7 +111,8 @@ jobs: - name: Restore cache uses: ./ with: - key: test-${{ runner.os }}-${{ github.run_id }} + reeval: ${{ matrix.reeval }} + key: test-${{ runner.os }}-${{ github.run_id }}-${{ matrix.reeval }} path: | test-cache ~/test-cache @@ -121,6 +125,9 @@ jobs: # End to end with proxy test-proxy-save: + strategy: + matrix: + reeval: [false, true] runs-on: ubuntu-latest container: image: ubuntu:latest @@ -140,10 +147,14 @@ jobs: - name: Save cache uses: ./ with: - key: test-proxy-${{ github.run_id }} + reeval: ${{ matrix.reeval }} + key: test-proxy-${{ github.run_id }}-${{ matrix.reeval }} path: test-cache test-proxy-only-restore: needs: test-proxy-save + strategy: + matrix: + reeval: [false, true] runs-on: ubuntu-latest container: image: ubuntu:latest @@ -162,12 +173,16 @@ jobs: uses: ./ with: only-restore: true - key: test-proxy-${{ github.run_id }} + reeval: ${{ matrix.reeval }} + key: test-proxy-${{ github.run_id }}-${{ matrix.reeval }} path: test-cache - name: Verify cache run: __tests__/verify-cache-files.sh proxy test-cache test-proxy-restore: needs: test-proxy-save + strategy: + matrix: + reeval: [false, true] runs-on: ubuntu-latest container: image: ubuntu:latest @@ -185,7 +200,8 @@ jobs: - name: Restore cache uses: ./ with: - key: test-proxy-${{ github.run_id }} + reeval: ${{ matrix.reeval }} + key: test-proxy-${{ github.run_id }}-${{ matrix.reeval }} path: test-cache - name: Verify cache run: __tests__/verify-cache-files.sh proxy test-cache diff --git a/src/save.ts b/src/save.ts index d37a086..adbdeac 100644 --- a/src/save.ts +++ b/src/save.ts @@ -28,8 +28,15 @@ async function run(): Promise { 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); + let primaryKey: string = ''; + const reeval = core.getBooleanInput(Inputs.Reeval); + if (!reeval) { + // Inputs are reevaluted before the post action, so we want the original key used for restore + primaryKey = core.getState(State.CachePrimaryKey); + } else { + // choose to reevaluate primary key + primaryKey = core.getInput(Inputs.Key, { required: true }); + } if (!primaryKey) { utils.logWarning(`Error retrieving key from state.`); return; From b134ca8d489c8f75272fd12463cf55a25364437a Mon Sep 17 00:00:00 2001 From: Vincent Clemson Date: Sun, 19 Jun 2022 00:48:47 -0400 Subject: [PATCH 7/9] format --- src/save.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/save.ts b/src/save.ts index adbdeac..fd5b30d 100644 --- a/src/save.ts +++ b/src/save.ts @@ -28,7 +28,7 @@ async function run(): Promise { const state = utils.getCacheState(); - let primaryKey: string = ''; + let primaryKey: string = ""; const reeval = core.getBooleanInput(Inputs.Reeval); if (!reeval) { // Inputs are reevaluted before the post action, so we want the original key used for restore From 88d49726bd6c24eff9b80e4f878ab43a654b54bd Mon Sep 17 00:00:00 2001 From: Vincent Clemson Date: Sun, 19 Jun 2022 00:50:29 -0400 Subject: [PATCH 8/9] build - adding reeval functionality --- dist/save/index.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/dist/save/index.js b/dist/save/index.js index c69ee3a..e3153a0 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -46783,8 +46783,16 @@ function run() { 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(constants_1.State.CachePrimaryKey); + let primaryKey = ""; + const reeval = core.getBooleanInput(constants_1.Inputs.Reeval); + if (!reeval) { + // Inputs are reevaluted before the post action, so we want the original key used for restore + primaryKey = core.getState(constants_1.State.CachePrimaryKey); + } + else { + // choose to reevaluate primary key + primaryKey = core.getInput(constants_1.Inputs.Key, { required: true }); + } if (!primaryKey) { utils.logWarning(`Error retrieving key from state.`); return; From b830d6f730e75c13e7d4ea9629041a647b02a099 Mon Sep 17 00:00:00 2001 From: Vincent Clemson Date: Sun, 19 Jun 2022 01:05:27 -0400 Subject: [PATCH 9/9] lint, fix, and rebuild --- src/save.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/save.ts b/src/save.ts index fd5b30d..df2fe4a 100644 --- a/src/save.ts +++ b/src/save.ts @@ -28,7 +28,7 @@ async function run(): Promise { const state = utils.getCacheState(); - let primaryKey: string = ""; + let primaryKey = ""; const reeval = core.getBooleanInput(Inputs.Reeval); if (!reeval) { // Inputs are reevaluted before the post action, so we want the original key used for restore