Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 70 additions & 4 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -67,15 +68,43 @@ 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
test-only-restore:
needs: test-save
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
reeval: [false, true]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Restore cache
uses: ./
with:
only-restore: true
reeval: ${{ matrix.reeval }}
key: test-${{ runner.os }}-${{ github.run_id }}-${{ matrix.reeval }}
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:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
reeval: [false, true]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
Expand All @@ -84,7 +113,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
Expand All @@ -97,6 +127,9 @@ jobs:

# End to end with proxy
test-proxy-save:
strategy:
matrix:
reeval: [false, true]
runs-on: ubuntu-latest
container:
image: ubuntu:latest
Expand All @@ -116,10 +149,42 @@ 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
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
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
Expand All @@ -137,7 +202,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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,6 @@ typings/

# Text editor files
.vscode/

# OS
.DS_Store
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ If you are using this inside a container, a POSIX-compliant `tar` needs to be in
* `key` - An explicit key for restoring and saving the cache
* `restore-keys` - An ordered list of keys to use for restoring stale cache if no cache hit occurred for key. Note
`cache-hit` returns false in this case.
* `reeval` - A boolean. Default set to `false`. Whether to reevaluate the `key` argument in the action's post run script when saving cache. Set to `true` if you would like your cache key set after your job's steps are complete.
* `only-restore` - A boolean. Default set to `false`. Whether to only perform cache restoration and not the save post run script.

### Outputs

Expand Down
8 changes: 8 additions & 0 deletions __tests__/restore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,19 @@ beforeAll(() => {
return actualUtils.getInputAsArray(name, options);
}
);

jest.spyOn(actionUtils, "getInputAsBoolean").mockImplementation(
(name, options) => {
const actualUtils = jest.requireActual("../src/utils/actionUtils");
return actualUtils.getInputAsBoolean(name, options);
}
);
});

beforeEach(() => {
process.env[Events.Key] = Events.Push;
process.env[RefKey] = "refs/heads/feature-branch";
testUtils.setInput(Inputs.Reeval, "false");

jest.spyOn(actionUtils, "isGhes").mockImplementation(() => false);
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
Expand Down
8 changes: 8 additions & 0 deletions __tests__/save.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ beforeAll(() => {
}
);

jest.spyOn(actionUtils, "getInputAsBoolean").mockImplementation(
(name, options) => {
const actualUtils = jest.requireActual("../src/utils/actionUtils");
return actualUtils.getInputAsBoolean(name, options);
}
);

jest.spyOn(actionUtils, "getInputAsInt").mockImplementation(
(name, options) => {
return jest
Expand All @@ -52,6 +59,7 @@ beforeAll(() => {
beforeEach(() => {
process.env[Events.Key] = Events.Push;
process.env[RefKey] = "refs/heads/feature-branch";
testUtils.setInput(Inputs.Reeval, "false");

jest.spyOn(actionUtils, "isGhes").mockImplementation(() => false);
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
Expand Down
8 changes: 8 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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: "A boolean. Whether to reevaluate the `key` argument in the action's post run script when saving cache. 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: 'A boolean. Whether to only perform cache restoration and not the save post run script.'
required: false
default: false
outputs:
cache-hit:
description: 'A boolean value to indicate an exact match was found for the primary key'
Expand Down
15 changes: 13 additions & 2 deletions dist/restore/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}));
Expand Down Expand Up @@ -37586,7 +37588,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isCacheFeatureAvailable = exports.getInputAsInt = exports.getInputAsArray = exports.isValidEvent = exports.logWarning = exports.getCacheState = exports.setOutputAndState = exports.setCacheHitOutput = exports.setCacheState = exports.isExactKeyMatch = exports.isGhes = void 0;
exports.isCacheFeatureAvailable = exports.getInputAsInt = exports.getInputAsBoolean = exports.getInputAsArray = exports.isValidEvent = exports.logWarning = exports.getCacheState = exports.setOutputAndState = exports.setCacheHitOutput = exports.setCacheState = exports.isExactKeyMatch = exports.isGhes = void 0;
const cache = __importStar(__webpack_require__(692));
const core = __importStar(__webpack_require__(470));
const constants_1 = __webpack_require__(196);
Expand Down Expand Up @@ -37644,6 +37646,11 @@ function getInputAsArray(name, options) {
.filter(x => x !== "");
}
exports.getInputAsArray = getInputAsArray;
function getInputAsBoolean(name, options) {
const value = core.getBooleanInput(name, options);
return value;
}
exports.getInputAsBoolean = getInputAsBoolean;
function getInputAsInt(name, options) {
const value = parseInt(core.getInput(name, options));
if (isNaN(value) || value < 0) {
Expand Down Expand Up @@ -48991,7 +48998,11 @@ function run() {
return;
}
const primaryKey = core.getInput(constants_1.Inputs.Key, { required: true });
core.saveState(constants_1.State.CachePrimaryKey, primaryKey);
// when selecting to reevaluate primary key - state is saved in save step
const reeval = utils.getInputAsBoolean(constants_1.Inputs.Reeval);
if (!reeval) {
core.saveState(constants_1.State.CachePrimaryKey, primaryKey);
}
const restoreKeys = utils.getInputAsArray(constants_1.Inputs.RestoreKeys);
const cachePaths = utils.getInputAsArray(constants_1.Inputs.Path, {
required: true
Expand Down
95 changes: 57 additions & 38 deletions dist/save/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}));
Expand Down Expand Up @@ -37586,7 +37588,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isCacheFeatureAvailable = exports.getInputAsInt = exports.getInputAsArray = exports.isValidEvent = exports.logWarning = exports.getCacheState = exports.setOutputAndState = exports.setCacheHitOutput = exports.setCacheState = exports.isExactKeyMatch = exports.isGhes = void 0;
exports.isCacheFeatureAvailable = exports.getInputAsInt = exports.getInputAsBoolean = exports.getInputAsArray = exports.isValidEvent = exports.logWarning = exports.getCacheState = exports.setOutputAndState = exports.setCacheHitOutput = exports.setCacheState = exports.isExactKeyMatch = exports.isGhes = void 0;
const cache = __importStar(__webpack_require__(692));
const core = __importStar(__webpack_require__(470));
const constants_1 = __webpack_require__(196);
Expand Down Expand Up @@ -37644,6 +37646,11 @@ function getInputAsArray(name, options) {
.filter(x => x !== "");
}
exports.getInputAsArray = getInputAsArray;
function getInputAsBoolean(name, options) {
const value = core.getBooleanInput(name, options);
return value;
}
exports.getInputAsBoolean = getInputAsBoolean;
function getInputAsInt(name, options) {
const value = parseInt(core.getInput(name, options));
if (isNaN(value) || value < 0) {
Expand Down Expand Up @@ -46770,49 +46777,61 @@ 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)
});
core.info(`Cache saved with key: ${primaryKey}`);
}
catch (error) {
const typedError = error;
if (typedError.name === cache.ValidationError.name) {
throw error;
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;
}
else if (typedError.name === cache.ReserveCacheError.name) {
core.info(typedError.message);
const state = utils.getCacheState();
let primaryKey = "";
const reeval = utils.getInputAsBoolean(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 {
utils.logWarning(typedError.message);
// choose to reevaluate primary key - resave state to correctly test cache hit on next run
primaryKey = core.getInput(constants_1.Inputs.Key, { required: true });
core.saveState(constants_1.State.CachePrimaryKey, primaryKey);
}
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
});
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) {
utils.logWarning(error.message);
catch (error) {
utils.logWarning(error.message);
}
}
});
}
Expand Down
Loading