Compare commits

..
Author SHA1 Message Date
Josh Gross 86dff562ab v1.0.1 release binaries 2019-11-05 15:43:33 -05:00
Josh Gross 0f810ad45a Release v1.0.1 2019-11-05 15:42:18 -05:00
Josh Gross 9d8c7b4041 Release v1 2019-11-04 15:13:15 -05:00
22 changed files with 338 additions and 2838 deletions
-16
View File
@@ -1,16 +0,0 @@
{
"env": { "node": true, "jest": true },
"parser": "@typescript-eslint/parser",
"parserOptions": { "ecmaVersion": 2020, "sourceType": "module" },
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:import/typescript",
"plugin:prettier/recommended",
"prettier/@typescript-eslint"
],
"plugins": ["@typescript-eslint", "jest"]
}
+2 -24
View File
@@ -1,11 +1,6 @@
name: Tests
on:
pull_request:
branches:
- master
paths-ignore:
- '**.md'
push:
branches:
- master
@@ -15,39 +10,22 @@ on:
jobs:
test:
name: Test on ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: '12.x'
- name: Get npm cache directory
id: npm-cache
run: |
echo "::set-output name=dir::$(npm config get cache)"
- uses: actions/cache@v1
with:
path: ${{ steps.npm-cache.outputs.dir }}
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- run: npm ci
- name: Prettier Format Check
run: npm run format-check
- name: ESLint Check
run: npm run lint
- name: Build & Test
run: npm run test
+19 -33
View File
@@ -2,7 +2,7 @@
This GitHub Action allows caching dependencies and build outputs to improve workflow execution time.
<a href="https://github.com/actions/cache/actions?query=workflow%3ATests"><img alt="GitHub Actions status" src="https://github.com/actions/cache/workflows/Tests/badge.svg?branch=master&event=push"></a>
<a href="https://github.com/actions/cache"><img alt="GitHub Actions status" src="https://github.com/actions/cache/workflows/Tests/badge.svg?branch=master&event=push"></a>
## Documentation
@@ -28,52 +28,38 @@ Create a workflow `.yml` file in your repositories `.github/workflows` directory
### Example workflow
```yaml
name: Caching Primes
name: Example Caching with npm
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Cache Primes
id: cache-primes
- name: Cache node modules
uses: actions/cache@v1
with:
path: prime-numbers
key: ${{ runner.os }}-primes
path: node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Generate Prime Numbers
if: steps.cache-primes.outputs.cache-hit != 'true'
run: /generate-primes.sh -d prime-numbers
- name: Install Dependencies
run: npm install
- name: Build
run: npm run build
- name: Use Prime Numbers
run: /primes.sh -d prime-numbers
- name: Test
run: npm run test
```
## Implementation Examples
Every programming language and framework has its own way of caching.
See [Examples](examples.md) for a list of `actions/cache` implementations for use with:
- [C# - Nuget](./examples.md#c---nuget)
- [Elixir - Mix](./examples.md#elixir---mix)
- [Go - Modules](./examples.md#go---modules)
- [Java - Gradle](./examples.md#java---gradle)
- [Java - Maven](./examples.md#java---maven)
- [Node - npm](./examples.md#node---npm)
- [Node - Yarn](./examples.md#node---yarn)
- [PHP - Composer](./examples.md#php---composer)
- [Python - pip](./examples.md#python---pip)
- [Ruby - Gem](./examples.md#ruby---gem)
- [Rust - Cargo](./examples.md#rust---cargo)
- [Swift, Objective-C - Carthage](./examples.md#swift-objective-c---carthage)
- [Swift, Objective-C - CocoaPods](./examples.md#swift-objective-c---cocoapods)
## Ecosystem Examples
See [Examples](examples.md)
## Cache Limits
@@ -92,8 +78,8 @@ steps:
id: cache
with:
path: path/to/dependencies
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles')}}
- name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: /install.sh
-1
View File
@@ -1 +0,0 @@
hello world
-236
View File
@@ -1,236 +0,0 @@
import * as core from "@actions/core";
import * as os from "os";
import * as path from "path";
import { Events, Outputs, State } from "../src/constants";
import { ArtifactCacheEntry } from "../src/contracts";
import * as actionUtils from "../src/utils/actionUtils";
jest.mock("@actions/core");
jest.mock("os");
afterEach(() => {
delete process.env[Events.Key];
});
test("getArchiveFileSize returns file size", () => {
const filePath = path.join(__dirname, "__fixtures__", "helloWorld.txt");
const size = actionUtils.getArchiveFileSize(filePath);
expect(size).toBe(11);
});
test("isExactKeyMatch with undefined cache entry returns false", () => {
const key = "linux-rust";
const cacheEntry = undefined;
expect(actionUtils.isExactKeyMatch(key, cacheEntry)).toBe(false);
});
test("isExactKeyMatch with empty cache entry returns false", () => {
const key = "linux-rust";
const cacheEntry: ArtifactCacheEntry = {};
expect(actionUtils.isExactKeyMatch(key, cacheEntry)).toBe(false);
});
test("isExactKeyMatch with different keys returns false", () => {
const key = "linux-rust";
const cacheEntry: ArtifactCacheEntry = {
cacheKey: "linux-"
};
expect(actionUtils.isExactKeyMatch(key, cacheEntry)).toBe(false);
});
test("isExactKeyMatch with different key accents returns false", () => {
const key = "linux-áccent";
const cacheEntry: ArtifactCacheEntry = {
cacheKey: "linux-accent"
};
expect(actionUtils.isExactKeyMatch(key, cacheEntry)).toBe(false);
});
test("isExactKeyMatch with same key returns true", () => {
const key = "linux-rust";
const cacheEntry: ArtifactCacheEntry = {
cacheKey: "linux-rust"
};
expect(actionUtils.isExactKeyMatch(key, cacheEntry)).toBe(true);
});
test("isExactKeyMatch with same key and different casing returns true", () => {
const key = "linux-rust";
const cacheEntry: ArtifactCacheEntry = {
cacheKey: "LINUX-RUST"
};
expect(actionUtils.isExactKeyMatch(key, cacheEntry)).toBe(true);
});
test("setOutputAndState with undefined entry to set cache-hit output", () => {
const key = "linux-rust";
const cacheEntry = undefined;
const setOutputMock = jest.spyOn(core, "setOutput");
const saveStateMock = jest.spyOn(core, "saveState");
actionUtils.setOutputAndState(key, cacheEntry);
expect(setOutputMock).toHaveBeenCalledWith(Outputs.CacheHit, "false");
expect(setOutputMock).toHaveBeenCalledTimes(1);
expect(saveStateMock).toHaveBeenCalledTimes(0);
});
test("setOutputAndState with exact match to set cache-hit output and state", () => {
const key = "linux-rust";
const cacheEntry: ArtifactCacheEntry = {
cacheKey: "linux-rust"
};
const setOutputMock = jest.spyOn(core, "setOutput");
const saveStateMock = jest.spyOn(core, "saveState");
actionUtils.setOutputAndState(key, cacheEntry);
expect(setOutputMock).toHaveBeenCalledWith(Outputs.CacheHit, "true");
expect(setOutputMock).toHaveBeenCalledTimes(1);
expect(saveStateMock).toHaveBeenCalledWith(
State.CacheResult,
JSON.stringify(cacheEntry)
);
expect(saveStateMock).toHaveBeenCalledTimes(1);
});
test("setOutputAndState with no exact match to set cache-hit output and state", () => {
const key = "linux-rust";
const cacheEntry: ArtifactCacheEntry = {
cacheKey: "linux-rust-bb828da54c148048dd17899ba9fda624811cfb43"
};
const setOutputMock = jest.spyOn(core, "setOutput");
const saveStateMock = jest.spyOn(core, "saveState");
actionUtils.setOutputAndState(key, cacheEntry);
expect(setOutputMock).toHaveBeenCalledWith(Outputs.CacheHit, "false");
expect(setOutputMock).toHaveBeenCalledTimes(1);
expect(saveStateMock).toHaveBeenCalledWith(
State.CacheResult,
JSON.stringify(cacheEntry)
);
expect(saveStateMock).toHaveBeenCalledTimes(1);
});
test("getCacheState with no state returns undefined", () => {
const getStateMock = jest.spyOn(core, "getState");
getStateMock.mockImplementation(() => {
return "";
});
const state = actionUtils.getCacheState();
expect(state).toBe(undefined);
expect(getStateMock).toHaveBeenCalledWith(State.CacheResult);
expect(getStateMock).toHaveBeenCalledTimes(1);
});
test("getCacheState with valid state", () => {
const cacheEntry: ArtifactCacheEntry = {
cacheKey: "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43",
scope: "refs/heads/master",
creationTime: "2019-11-13T19:18:02+00:00",
archiveLocation: "www.actionscache.test/download"
};
const getStateMock = jest.spyOn(core, "getState");
getStateMock.mockImplementation(() => {
return JSON.stringify(cacheEntry);
});
const state = actionUtils.getCacheState();
expect(state).toEqual(cacheEntry);
expect(getStateMock).toHaveBeenCalledWith(State.CacheResult);
expect(getStateMock).toHaveBeenCalledTimes(1);
});
test("logWarning logs a message with a warning prefix", () => {
const message = "A warning occurred.";
const infoMock = jest.spyOn(core, "info");
actionUtils.logWarning(message);
expect(infoMock).toHaveBeenCalledWith(`[warning]${message}`);
});
test("isValidEvent returns false for unknown event", () => {
const event = "foo";
process.env[Events.Key] = event;
const isValidEvent = actionUtils.isValidEvent();
expect(isValidEvent).toBe(false);
});
test("resolvePath with no ~ in path", () => {
const filePath = ".cache/yarn";
const resolvedPath = actionUtils.resolvePath(filePath);
const expectedPath = path.resolve(filePath);
expect(resolvedPath).toBe(expectedPath);
});
test("resolvePath with ~ in path", () => {
const filePath = "~/.cache/yarn";
const homedir = jest.requireActual("os").homedir();
const homedirMock = jest.spyOn(os, "homedir");
homedirMock.mockImplementation(() => {
return homedir;
});
const resolvedPath = actionUtils.resolvePath(filePath);
const expectedPath = path.join(homedir, ".cache/yarn");
expect(resolvedPath).toBe(expectedPath);
});
test("resolvePath with home not found", () => {
const filePath = "~/.cache/yarn";
const homedirMock = jest.spyOn(os, "homedir");
homedirMock.mockImplementation(() => {
return "";
});
expect(() => actionUtils.resolvePath(filePath)).toThrow(
"Unable to resolve `~` to HOME"
);
});
test("isValidEvent returns true for push event", () => {
const event = Events.Push;
process.env[Events.Key] = event;
const isValidEvent = actionUtils.isValidEvent();
expect(isValidEvent).toBe(true);
});
test("isValidEvent returns true for pull request event", () => {
const event = Events.PullRequest;
process.env[Events.Key] = event;
const isValidEvent = actionUtils.isValidEvent();
expect(isValidEvent).toBe(true);
});
+22
View File
@@ -0,0 +1,22 @@
import * as core from "@actions/core";
import { Inputs } from "../src/constants";
import run from "../src/restore";
import * as testUtils from "../src/utils/testUtils";
test("restore with no path", async () => {
const failedMock = jest.spyOn(core, "setFailed");
await run();
expect(failedMock).toHaveBeenCalledWith(
"Input required and not supplied: path"
);
});
test("restore with no key", async () => {
testUtils.setInput(Inputs.Path, "node_modules");
const failedMock = jest.spyOn(core, "setFailed");
await run();
expect(failedMock).toHaveBeenCalledWith(
"Input required and not supplied: key"
);
});
-394
View File
@@ -1,394 +0,0 @@
import * as core from "@actions/core";
import * as path from "path";
import * as cacheHttpClient from "../src/cacheHttpClient";
import { Events, Inputs } from "../src/constants";
import { ArtifactCacheEntry } from "../src/contracts";
import run from "../src/restore";
import * as tar from "../src/tar";
import * as actionUtils from "../src/utils/actionUtils";
import * as testUtils from "../src/utils/testUtils";
jest.mock("../src/cacheHttpClient");
jest.mock("../src/tar");
jest.mock("../src/utils/actionUtils");
beforeAll(() => {
jest.spyOn(actionUtils, "resolvePath").mockImplementation(filePath => {
return path.resolve(filePath);
});
jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
(key, cacheResult) => {
const actualUtils = jest.requireActual("../src/utils/actionUtils");
return actualUtils.isExactKeyMatch(key, cacheResult);
}
);
jest.spyOn(actionUtils, "isValidEvent").mockImplementation(() => {
const actualUtils = jest.requireActual("../src/utils/actionUtils");
return actualUtils.isValidEvent();
});
jest.spyOn(actionUtils, "getSupportedEvents").mockImplementation(() => {
const actualUtils = jest.requireActual("../src/utils/actionUtils");
return actualUtils.getSupportedEvents();
});
});
beforeEach(() => {
process.env[Events.Key] = Events.Push;
});
afterEach(() => {
testUtils.clearInputs();
delete process.env[Events.Key];
});
test("restore with invalid event outputs warning", async () => {
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
const failedMock = jest.spyOn(core, "setFailed");
const invalidEvent = "commit_comment";
process.env[Events.Key] = invalidEvent;
await run();
expect(logWarningMock).toHaveBeenCalledWith(
`Event Validation Error: The event type ${invalidEvent} is not supported. Only push, pull_request events are supported at this time.`
);
expect(failedMock).toHaveBeenCalledTimes(0);
});
test("restore with no path should fail", async () => {
const failedMock = jest.spyOn(core, "setFailed");
await run();
expect(failedMock).toHaveBeenCalledWith(
"Input required and not supplied: path"
);
});
test("restore with no key", async () => {
testUtils.setInput(Inputs.Path, "node_modules");
const failedMock = jest.spyOn(core, "setFailed");
await run();
expect(failedMock).toHaveBeenCalledWith(
"Input required and not supplied: key"
);
});
test("restore with too many keys should fail", async () => {
const key = "node-test";
const restoreKeys = [...Array(20).keys()].map(x => x.toString());
testUtils.setInputs({
path: "node_modules",
key,
restoreKeys
});
const failedMock = jest.spyOn(core, "setFailed");
await run();
expect(failedMock).toHaveBeenCalledWith(
`Key Validation Error: Keys are limited to a maximum of 10.`
);
});
test("restore with large key should fail", async () => {
const key = "foo".repeat(512); // Over the 512 character limit
testUtils.setInputs({
path: "node_modules",
key
});
const failedMock = jest.spyOn(core, "setFailed");
await run();
expect(failedMock).toHaveBeenCalledWith(
`Key Validation Error: ${key} cannot be larger than 512 characters.`
);
});
test("restore with invalid key should fail", async () => {
const key = "comma,comma";
testUtils.setInputs({
path: "node_modules",
key
});
const failedMock = jest.spyOn(core, "setFailed");
await run();
expect(failedMock).toHaveBeenCalledWith(
`Key Validation Error: ${key} cannot contain commas.`
);
});
test("restore with no cache found", async () => {
const key = "node-test";
testUtils.setInputs({
path: "node_modules",
key
});
const infoMock = jest.spyOn(core, "info");
const failedMock = jest.spyOn(core, "setFailed");
const stateMock = jest.spyOn(core, "saveState");
const clientMock = jest.spyOn(cacheHttpClient, "getCacheEntry");
clientMock.mockImplementation(() => {
return Promise.resolve(null);
});
await run();
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
expect(failedMock).toHaveBeenCalledTimes(0);
expect(infoMock).toHaveBeenCalledWith(
`Cache not found for input keys: ${key}.`
);
});
test("restore with server error should fail", async () => {
const key = "node-test";
testUtils.setInputs({
path: "node_modules",
key
});
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
const failedMock = jest.spyOn(core, "setFailed");
const stateMock = jest.spyOn(core, "saveState");
const clientMock = jest.spyOn(cacheHttpClient, "getCacheEntry");
clientMock.mockImplementation(() => {
throw new Error("HTTP Error Occurred");
});
const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
await run();
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
expect(logWarningMock).toHaveBeenCalledTimes(1);
expect(logWarningMock).toHaveBeenCalledWith("HTTP Error Occurred");
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
expect(setCacheHitOutputMock).toHaveBeenCalledWith(false);
expect(failedMock).toHaveBeenCalledTimes(0);
});
test("restore with restore keys and no cache found", async () => {
const key = "node-test";
const restoreKey = "node-";
testUtils.setInputs({
path: "node_modules",
key,
restoreKeys: [restoreKey]
});
const infoMock = jest.spyOn(core, "info");
const failedMock = jest.spyOn(core, "setFailed");
const stateMock = jest.spyOn(core, "saveState");
const clientMock = jest.spyOn(cacheHttpClient, "getCacheEntry");
clientMock.mockImplementation(() => {
return Promise.resolve(null);
});
await run();
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
expect(failedMock).toHaveBeenCalledTimes(0);
expect(infoMock).toHaveBeenCalledWith(
`Cache not found for input keys: ${key}, ${restoreKey}.`
);
});
test("restore with cache found", async () => {
const key = "node-test";
const cachePath = path.resolve("node_modules");
testUtils.setInputs({
path: "node_modules",
key
});
const infoMock = jest.spyOn(core, "info");
const failedMock = jest.spyOn(core, "setFailed");
const stateMock = jest.spyOn(core, "saveState");
const cacheEntry: ArtifactCacheEntry = {
cacheKey: key,
scope: "refs/heads/master",
archiveLocation: "www.actionscache.test/download"
};
const getCacheMock = jest.spyOn(cacheHttpClient, "getCacheEntry");
getCacheMock.mockImplementation(() => {
return Promise.resolve(cacheEntry);
});
const tempPath = "/foo/bar";
const createTempDirectoryMock = jest.spyOn(
actionUtils,
"createTempDirectory"
);
createTempDirectoryMock.mockImplementation(() => {
return Promise.resolve(tempPath);
});
const archivePath = path.join(tempPath, "cache.tgz");
const setCacheStateMock = jest.spyOn(actionUtils, "setCacheState");
const downloadCacheMock = jest.spyOn(cacheHttpClient, "downloadCache");
const fileSize = 142;
const getArchiveFileSizeMock = jest
.spyOn(actionUtils, "getArchiveFileSize")
.mockReturnValue(fileSize);
const extractTarMock = jest.spyOn(tar, "extractTar");
const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
await run();
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
expect(getCacheMock).toHaveBeenCalledWith([key]);
expect(setCacheStateMock).toHaveBeenCalledWith(cacheEntry);
expect(createTempDirectoryMock).toHaveBeenCalledTimes(1);
expect(downloadCacheMock).toHaveBeenCalledWith(cacheEntry, archivePath);
expect(getArchiveFileSizeMock).toHaveBeenCalledWith(archivePath);
expect(extractTarMock).toHaveBeenCalledTimes(1);
expect(extractTarMock).toHaveBeenCalledWith(archivePath, cachePath);
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
expect(setCacheHitOutputMock).toHaveBeenCalledWith(true);
expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`);
expect(failedMock).toHaveBeenCalledTimes(0);
});
test("restore with a pull request event and cache found", async () => {
const key = "node-test";
const cachePath = path.resolve("node_modules");
testUtils.setInputs({
path: "node_modules",
key
});
process.env[Events.Key] = Events.PullRequest;
const infoMock = jest.spyOn(core, "info");
const failedMock = jest.spyOn(core, "setFailed");
const stateMock = jest.spyOn(core, "saveState");
const cacheEntry: ArtifactCacheEntry = {
cacheKey: key,
scope: "refs/heads/master",
archiveLocation: "www.actionscache.test/download"
};
const getCacheMock = jest.spyOn(cacheHttpClient, "getCacheEntry");
getCacheMock.mockImplementation(() => {
return Promise.resolve(cacheEntry);
});
const tempPath = "/foo/bar";
const createTempDirectoryMock = jest.spyOn(
actionUtils,
"createTempDirectory"
);
createTempDirectoryMock.mockImplementation(() => {
return Promise.resolve(tempPath);
});
const archivePath = path.join(tempPath, "cache.tgz");
const setCacheStateMock = jest.spyOn(actionUtils, "setCacheState");
const downloadCacheMock = jest.spyOn(cacheHttpClient, "downloadCache");
const fileSize = 62915000;
const getArchiveFileSizeMock = jest
.spyOn(actionUtils, "getArchiveFileSize")
.mockReturnValue(fileSize);
const extractTarMock = jest.spyOn(tar, "extractTar");
const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
await run();
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
expect(getCacheMock).toHaveBeenCalledWith([key]);
expect(setCacheStateMock).toHaveBeenCalledWith(cacheEntry);
expect(createTempDirectoryMock).toHaveBeenCalledTimes(1);
expect(downloadCacheMock).toHaveBeenCalledWith(cacheEntry, archivePath);
expect(getArchiveFileSizeMock).toHaveBeenCalledWith(archivePath);
expect(infoMock).toHaveBeenCalledWith(`Cache Size: ~60 MB (62915000 B)`);
expect(extractTarMock).toHaveBeenCalledTimes(1);
expect(extractTarMock).toHaveBeenCalledWith(archivePath, cachePath);
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
expect(setCacheHitOutputMock).toHaveBeenCalledWith(true);
expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`);
expect(failedMock).toHaveBeenCalledTimes(0);
});
test("restore with cache found for restore key", async () => {
const key = "node-test";
const restoreKey = "node-";
const cachePath = path.resolve("node_modules");
testUtils.setInputs({
path: "node_modules",
key,
restoreKeys: [restoreKey]
});
const infoMock = jest.spyOn(core, "info");
const failedMock = jest.spyOn(core, "setFailed");
const stateMock = jest.spyOn(core, "saveState");
const cacheEntry: ArtifactCacheEntry = {
cacheKey: restoreKey,
scope: "refs/heads/master",
archiveLocation: "www.actionscache.test/download"
};
const getCacheMock = jest.spyOn(cacheHttpClient, "getCacheEntry");
getCacheMock.mockImplementation(() => {
return Promise.resolve(cacheEntry);
});
const tempPath = "/foo/bar";
const createTempDirectoryMock = jest.spyOn(
actionUtils,
"createTempDirectory"
);
createTempDirectoryMock.mockImplementation(() => {
return Promise.resolve(tempPath);
});
const archivePath = path.join(tempPath, "cache.tgz");
const setCacheStateMock = jest.spyOn(actionUtils, "setCacheState");
const downloadCacheMock = jest.spyOn(cacheHttpClient, "downloadCache");
const fileSize = 142;
const getArchiveFileSizeMock = jest
.spyOn(actionUtils, "getArchiveFileSize")
.mockReturnValue(fileSize);
const extractTarMock = jest.spyOn(tar, "extractTar");
const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
await run();
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
expect(getCacheMock).toHaveBeenCalledWith([key, restoreKey]);
expect(setCacheStateMock).toHaveBeenCalledWith(cacheEntry);
expect(createTempDirectoryMock).toHaveBeenCalledTimes(1);
expect(downloadCacheMock).toHaveBeenCalledWith(cacheEntry, archivePath);
expect(getArchiveFileSizeMock).toHaveBeenCalledWith(archivePath);
expect(infoMock).toHaveBeenCalledWith(`Cache Size: ~0 MB (142 B)`);
expect(extractTarMock).toHaveBeenCalledTimes(1);
expect(extractTarMock).toHaveBeenCalledWith(archivePath, cachePath);
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
expect(setCacheHitOutputMock).toHaveBeenCalledWith(false);
expect(infoMock).toHaveBeenCalledWith(
`Cache restored from key: ${restoreKey}`
);
expect(failedMock).toHaveBeenCalledTimes(0);
});
-306
View File
@@ -1,306 +0,0 @@
import * as core from "@actions/core";
import * as path from "path";
import * as cacheHttpClient from "../src/cacheHttpClient";
import { Events, Inputs } from "../src/constants";
import { ArtifactCacheEntry } from "../src/contracts";
import run from "../src/save";
import * as tar from "../src/tar";
import * as actionUtils from "../src/utils/actionUtils";
import * as testUtils from "../src/utils/testUtils";
jest.mock("@actions/core");
jest.mock("../src/cacheHttpClient");
jest.mock("../src/tar");
jest.mock("../src/utils/actionUtils");
beforeAll(() => {
jest.spyOn(core, "getInput").mockImplementation((name, options) => {
return jest.requireActual("@actions/core").getInput(name, options);
});
jest.spyOn(actionUtils, "getCacheState").mockImplementation(() => {
return jest.requireActual("../src/utils/actionUtils").getCacheState();
});
jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
(key, cacheResult) => {
return jest
.requireActual("../src/utils/actionUtils")
.isExactKeyMatch(key, cacheResult);
}
);
jest.spyOn(actionUtils, "isValidEvent").mockImplementation(() => {
const actualUtils = jest.requireActual("../src/utils/actionUtils");
return actualUtils.isValidEvent();
});
jest.spyOn(actionUtils, "getSupportedEvents").mockImplementation(() => {
const actualUtils = jest.requireActual("../src/utils/actionUtils");
return actualUtils.getSupportedEvents();
});
jest.spyOn(actionUtils, "resolvePath").mockImplementation(filePath => {
return path.resolve(filePath);
});
jest.spyOn(actionUtils, "createTempDirectory").mockImplementation(() => {
return Promise.resolve("/foo/bar");
});
});
beforeEach(() => {
process.env[Events.Key] = Events.Push;
});
afterEach(() => {
testUtils.clearInputs();
delete process.env[Events.Key];
});
test("save with invalid event outputs warning", async () => {
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
const failedMock = jest.spyOn(core, "setFailed");
const invalidEvent = "commit_comment";
process.env[Events.Key] = invalidEvent;
await run();
expect(logWarningMock).toHaveBeenCalledWith(
`Event Validation Error: The event type ${invalidEvent} is not supported. Only push, pull_request events are supported at this time.`
);
expect(failedMock).toHaveBeenCalledTimes(0);
});
test("save with no primary key in state outputs warning", async () => {
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
const failedMock = jest.spyOn(core, "setFailed");
const cacheEntry: ArtifactCacheEntry = {
cacheKey: "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43",
scope: "refs/heads/master",
creationTime: "2019-11-13T19:18:02+00:00",
archiveLocation: "www.actionscache.test/download"
};
jest.spyOn(core, "getState")
// Cache Entry State
.mockImplementationOnce(() => {
return JSON.stringify(cacheEntry);
})
// Cache Key State
.mockImplementationOnce(() => {
return "";
});
await run();
expect(logWarningMock).toHaveBeenCalledWith(
`Error retrieving key from state.`
);
expect(logWarningMock).toHaveBeenCalledTimes(1);
expect(failedMock).toHaveBeenCalledTimes(0);
});
test("save with exact match returns early", async () => {
const infoMock = jest.spyOn(core, "info");
const failedMock = jest.spyOn(core, "setFailed");
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
const cacheEntry: ArtifactCacheEntry = {
cacheKey: primaryKey,
scope: "refs/heads/master",
creationTime: "2019-11-13T19:18:02+00:00",
archiveLocation: "www.actionscache.test/download"
};
jest.spyOn(core, "getState")
// Cache Entry State
.mockImplementationOnce(() => {
return JSON.stringify(cacheEntry);
})
// Cache Key State
.mockImplementationOnce(() => {
return primaryKey;
});
const createTarMock = jest.spyOn(tar, "createTar");
await run();
expect(infoMock).toHaveBeenCalledWith(
`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`
);
expect(createTarMock).toHaveBeenCalledTimes(0);
expect(failedMock).toHaveBeenCalledTimes(0);
});
test("save with missing input outputs warning", async () => {
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
const failedMock = jest.spyOn(core, "setFailed");
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
const cacheEntry: ArtifactCacheEntry = {
cacheKey: "Linux-node-",
scope: "refs/heads/master",
creationTime: "2019-11-13T19:18:02+00:00",
archiveLocation: "www.actionscache.test/download"
};
jest.spyOn(core, "getState")
// Cache Entry State
.mockImplementationOnce(() => {
return JSON.stringify(cacheEntry);
})
// Cache Key State
.mockImplementationOnce(() => {
return primaryKey;
});
await run();
expect(logWarningMock).toHaveBeenCalledWith(
"Input required and not supplied: path"
);
expect(logWarningMock).toHaveBeenCalledTimes(1);
expect(failedMock).toHaveBeenCalledTimes(0);
});
test("save with large cache outputs warning", async () => {
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
const failedMock = jest.spyOn(core, "setFailed");
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
const cacheEntry: ArtifactCacheEntry = {
cacheKey: "Linux-node-",
scope: "refs/heads/master",
creationTime: "2019-11-13T19:18:02+00:00",
archiveLocation: "www.actionscache.test/download"
};
jest.spyOn(core, "getState")
// Cache Entry State
.mockImplementationOnce(() => {
return JSON.stringify(cacheEntry);
})
// Cache Key State
.mockImplementationOnce(() => {
return primaryKey;
});
const inputPath = "node_modules";
const cachePath = path.resolve(inputPath);
testUtils.setInput(Inputs.Path, inputPath);
const createTarMock = jest.spyOn(tar, "createTar");
const cacheSize = 1024 * 1024 * 1024; //~1GB, over the 400MB limit
jest.spyOn(actionUtils, "getArchiveFileSize").mockImplementationOnce(() => {
return cacheSize;
});
await run();
const archivePath = path.join("/foo/bar", "cache.tgz");
expect(createTarMock).toHaveBeenCalledTimes(1);
expect(createTarMock).toHaveBeenCalledWith(archivePath, cachePath);
expect(logWarningMock).toHaveBeenCalledTimes(1);
expect(logWarningMock).toHaveBeenCalledWith(
"Cache size of ~1024 MB (1073741824 B) is over the 400MB limit, not saving cache."
);
expect(failedMock).toHaveBeenCalledTimes(0);
});
test("save with server error outputs warning", async () => {
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
const failedMock = jest.spyOn(core, "setFailed");
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
const cacheEntry: ArtifactCacheEntry = {
cacheKey: "Linux-node-",
scope: "refs/heads/master",
creationTime: "2019-11-13T19:18:02+00:00",
archiveLocation: "www.actionscache.test/download"
};
jest.spyOn(core, "getState")
// Cache Entry State
.mockImplementationOnce(() => {
return JSON.stringify(cacheEntry);
})
// Cache Key State
.mockImplementationOnce(() => {
return primaryKey;
});
const inputPath = "node_modules";
const cachePath = path.resolve(inputPath);
testUtils.setInput(Inputs.Path, inputPath);
const createTarMock = jest.spyOn(tar, "createTar");
const saveCacheMock = jest
.spyOn(cacheHttpClient, "saveCache")
.mockImplementationOnce(() => {
throw new Error("HTTP Error Occurred");
});
await run();
const archivePath = path.join("/foo/bar", "cache.tgz");
expect(createTarMock).toHaveBeenCalledTimes(1);
expect(createTarMock).toHaveBeenCalledWith(archivePath, cachePath);
expect(saveCacheMock).toHaveBeenCalledTimes(1);
expect(saveCacheMock).toHaveBeenCalledWith(primaryKey, archivePath);
expect(logWarningMock).toHaveBeenCalledTimes(1);
expect(logWarningMock).toHaveBeenCalledWith("HTTP Error Occurred");
expect(failedMock).toHaveBeenCalledTimes(0);
});
test("save with valid inputs uploads a cache", async () => {
const failedMock = jest.spyOn(core, "setFailed");
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
const cacheEntry: ArtifactCacheEntry = {
cacheKey: "Linux-node-",
scope: "refs/heads/master",
creationTime: "2019-11-13T19:18:02+00:00",
archiveLocation: "www.actionscache.test/download"
};
jest.spyOn(core, "getState")
// Cache Entry State
.mockImplementationOnce(() => {
return JSON.stringify(cacheEntry);
})
// Cache Key State
.mockImplementationOnce(() => {
return primaryKey;
});
const inputPath = "node_modules";
const cachePath = path.resolve(inputPath);
testUtils.setInput(Inputs.Path, inputPath);
const createTarMock = jest.spyOn(tar, "createTar");
const saveCacheMock = jest.spyOn(cacheHttpClient, "saveCache");
await run();
const archivePath = path.join("/foo/bar", "cache.tgz");
expect(createTarMock).toHaveBeenCalledTimes(1);
expect(createTarMock).toHaveBeenCalledWith(archivePath, cachePath);
expect(saveCacheMock).toHaveBeenCalledTimes(1);
expect(saveCacheMock).toHaveBeenCalledWith(primaryKey, archivePath);
expect(failedMock).toHaveBeenCalledTimes(0);
});
-58
View File
@@ -1,58 +0,0 @@
import * as exec from "@actions/exec";
import * as io from "@actions/io";
import * as tar from "../src/tar";
jest.mock("@actions/exec");
jest.mock("@actions/io");
beforeAll(() => {
jest.spyOn(io, "which").mockImplementation(tool => {
return Promise.resolve(tool);
});
});
test("extract tar", async () => {
const mkdirMock = jest.spyOn(io, "mkdirP");
const execMock = jest.spyOn(exec, "exec");
const archivePath = "cache.tar";
const targetDirectory = "~/.npm/cache";
await tar.extractTar(archivePath, targetDirectory);
expect(mkdirMock).toHaveBeenCalledWith(targetDirectory);
const IS_WINDOWS = process.platform === "win32";
const tarPath = IS_WINDOWS
? `${process.env["windir"]}\\System32\\tar.exe`
: "tar";
expect(execMock).toHaveBeenCalledTimes(1);
expect(execMock).toHaveBeenCalledWith(`"${tarPath}"`, [
"-xz",
"-f",
archivePath,
"-C",
targetDirectory
]);
});
test("create tar", async () => {
const execMock = jest.spyOn(exec, "exec");
const archivePath = "cache.tar";
const sourceDirectory = "~/.npm/cache";
await tar.createTar(archivePath, sourceDirectory);
const IS_WINDOWS = process.platform === "win32";
const tarPath = IS_WINDOWS
? `${process.env["windir"]}\\System32\\tar.exe`
: "tar";
expect(execMock).toHaveBeenCalledTimes(1);
expect(execMock).toHaveBeenCalledWith(`"${tarPath}"`, [
"-cz",
"-f",
archivePath,
"-C",
sourceDirectory,
"."
]);
});
+68 -168
View File
@@ -1496,26 +1496,6 @@ const fs = __importStar(__webpack_require__(747));
const Handlers_1 = __webpack_require__(941);
const HttpClient_1 = __webpack_require__(874);
const RestClient_1 = __webpack_require__(105);
function getCacheUrl() {
// Ideally we just use ACTIONS_CACHE_URL
const cacheUrl = (process.env["ACTIONS_CACHE_URL"] ||
process.env["ACTIONS_RUNTIME_URL"] ||
"").replace("pipelines", "artifactcache");
if (!cacheUrl) {
throw new Error("Cache Service Url not found, unable to restore cache.");
}
core.debug(`Cache Url: ${cacheUrl}`);
return cacheUrl;
}
function createAcceptHeader(type, apiVersion) {
return `${type};api-version=${apiVersion}`;
}
function getRequestOptions() {
const requestOptions = {
acceptHeader: createAcceptHeader("application/json", "5.2-preview.1")
};
return requestOptions;
}
function getCacheEntry(keys) {
return __awaiter(this, void 0, void 0, function* () {
const cacheUrl = getCacheUrl();
@@ -1533,16 +1513,24 @@ function getCacheEntry(keys) {
throw new Error(`Cache service responded with ${response.statusCode}`);
}
const cacheResult = response.result;
core.debug(`Cache Result:`);
core.debug(JSON.stringify(cacheResult));
if (!cacheResult || !cacheResult.archiveLocation) {
throw new Error("Cache not found.");
}
core.setSecret(cacheResult.archiveLocation);
core.debug(`Cache Result:`);
core.debug(JSON.stringify(cacheResult));
return cacheResult;
});
}
exports.getCacheEntry = getCacheEntry;
function downloadCache(cacheEntry, archivePath) {
return __awaiter(this, void 0, void 0, function* () {
const stream = fs.createWriteStream(archivePath);
const httpClient = new HttpClient_1.HttpClient("actions/cache");
const downloadResponse = yield httpClient.get(cacheEntry.archiveLocation);
yield pipeResponseToStream(downloadResponse, stream);
});
}
exports.downloadCache = downloadCache;
function pipeResponseToStream(response, stream) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise(resolve => {
@@ -1552,19 +1540,8 @@ function pipeResponseToStream(response, stream) {
});
});
}
function downloadCache(cacheEntry, archivePath) {
function saveCache(stream, key) {
return __awaiter(this, void 0, void 0, function* () {
const stream = fs.createWriteStream(archivePath);
const httpClient = new HttpClient_1.HttpClient("actions/cache");
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const downloadResponse = yield httpClient.get(cacheEntry.archiveLocation);
yield pipeResponseToStream(downloadResponse, stream);
});
}
exports.downloadCache = downloadCache;
function saveCache(key, archivePath) {
return __awaiter(this, void 0, void 0, function* () {
const stream = fs.createReadStream(archivePath);
const cacheUrl = getCacheUrl();
const token = process.env["ACTIONS_RUNTIME_TOKEN"] || "";
const bearerCredentialHandler = new Handlers_1.BearerCredentialHandler(token);
@@ -1585,6 +1562,26 @@ function saveCache(key, archivePath) {
});
}
exports.saveCache = saveCache;
function getRequestOptions() {
const requestOptions = {
acceptHeader: createAcceptHeader("application/json", "5.2-preview.1")
};
return requestOptions;
}
function createAcceptHeader(type, apiVersion) {
return `${type};api-version=${apiVersion}`;
}
function getCacheUrl() {
// Ideally we just use ACTIONS_CACHE_URL
let cacheUrl = (process.env["ACTIONS_CACHE_URL"] ||
process.env["ACTIONS_RUNTIME_URL"] ||
"").replace("pipelines", "artifactcache");
if (!cacheUrl) {
throw new Error("Cache Service Url not found, unable to restore cache.");
}
core.debug(`Cache Url: ${cacheUrl}`);
return cacheUrl;
}
/***/ }),
@@ -2142,7 +2139,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(__webpack_require__(470));
const io = __importStar(__webpack_require__(1));
const fs = __importStar(__webpack_require__(747));
const os = __importStar(__webpack_require__(87));
const path = __importStar(__webpack_require__(622));
const uuidV4 = __importStar(__webpack_require__(826));
@@ -2174,10 +2170,6 @@ function createTempDirectory() {
});
}
exports.createTempDirectory = createTempDirectory;
function getArchiveFileSize(path) {
return fs.statSync(path).size;
}
exports.getArchiveFileSize = getArchiveFileSize;
function isExactKeyMatch(key, cacheResult) {
return !!(cacheResult &&
cacheResult.cacheKey &&
@@ -2186,14 +2178,6 @@ function isExactKeyMatch(key, cacheResult) {
}) === 0);
}
exports.isExactKeyMatch = isExactKeyMatch;
function setCacheState(state) {
core.saveState(constants_1.State.CacheResult, JSON.stringify(state));
}
exports.setCacheState = setCacheState;
function setCacheHitOutput(isCacheHit) {
core.setOutput(constants_1.Outputs.CacheHit, isCacheHit.toString());
}
exports.setCacheHitOutput = setCacheHitOutput;
function setOutputAndState(key, cacheResult) {
setCacheHitOutput(isExactKeyMatch(key, cacheResult));
// Store the cache result if it exists
@@ -2203,17 +2187,17 @@ exports.setOutputAndState = setOutputAndState;
function getCacheState() {
const stateData = core.getState(constants_1.State.CacheResult);
core.debug(`State: ${stateData}`);
if (stateData) {
return JSON.parse(stateData);
}
return undefined;
return (stateData && JSON.parse(stateData));
}
exports.getCacheState = getCacheState;
function logWarning(message) {
const warningPrefix = "[warning]";
core.info(`${warningPrefix}${message}`);
function setCacheState(state) {
core.saveState(constants_1.State.CacheResult, JSON.stringify(state));
}
exports.logWarning = logWarning;
exports.setCacheState = setCacheState;
function setCacheHitOutput(isCacheHit) {
core.setOutput(constants_1.Outputs.CacheHit, isCacheHit.toString());
}
exports.setCacheHitOutput = setCacheHitOutput;
function resolvePath(filePath) {
if (filePath[0] === "~") {
const home = os.homedir();
@@ -2225,18 +2209,6 @@ function resolvePath(filePath) {
return path.resolve(filePath);
}
exports.resolvePath = resolvePath;
function getSupportedEvents() {
return [constants_1.Events.Push, constants_1.Events.PullRequest];
}
exports.getSupportedEvents = getSupportedEvents;
// Currently the cache token is only authorized for push and pull_request events
// All other events will fail when reading and saving the cache
// See GitHub Context https://help.github.com/actions/automating-your-workflow-with-github-actions/contexts-and-expression-syntax-for-github-actions#github-context
function isValidEvent() {
const githubEvent = process.env[constants_1.Events.Key] || "";
return getSupportedEvents().includes(githubEvent);
}
exports.isValidEvent = isValidEvent;
/***/ }),
@@ -2864,25 +2836,19 @@ function isUnixExecutable(stats) {
Object.defineProperty(exports, "__esModule", { value: true });
var Inputs;
(function (Inputs) {
Inputs["Key"] = "key";
Inputs["Path"] = "path";
Inputs["RestoreKeys"] = "restore-keys";
Inputs.Key = "key";
Inputs.Path = "path";
Inputs.RestoreKeys = "restore-keys";
})(Inputs = exports.Inputs || (exports.Inputs = {}));
var Outputs;
(function (Outputs) {
Outputs["CacheHit"] = "cache-hit";
Outputs.CacheHit = "cache-hit";
})(Outputs = exports.Outputs || (exports.Outputs = {}));
var State;
(function (State) {
State["CacheKey"] = "CACHE_KEY";
State["CacheResult"] = "CACHE_RESULT";
State.CacheKey = "CACHE_KEY";
State.CacheResult = "CACHE_RESULT";
})(State = exports.State || (exports.State = {}));
var Events;
(function (Events) {
Events["Key"] = "GITHUB_EVENT_NAME";
Events["Push"] = "push";
Events["PullRequest"] = "pull_request";
})(Events = exports.Events || (exports.Events = {}));
/***/ }),
@@ -2991,22 +2957,18 @@ var __importStar = (this && this.__importStar) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(__webpack_require__(470));
const exec_1 = __webpack_require__(986);
const io = __importStar(__webpack_require__(1));
const fs = __importStar(__webpack_require__(747));
const path = __importStar(__webpack_require__(622));
const cacheHttpClient = __importStar(__webpack_require__(154));
const constants_1 = __webpack_require__(694);
const tar_1 = __webpack_require__(943);
const utils = __importStar(__webpack_require__(443));
function run() {
return __awaiter(this, void 0, void 0, function* () {
try {
// Validate inputs, this can cause task failure
if (!utils.isValidEvent()) {
utils.logWarning(`Event Validation Error: The event type ${process.env[constants_1.Events.Key]} is not supported. Only ${utils
.getSupportedEvents()
.join(", ")} events are supported at this time.`);
return;
}
const cachePath = utils.resolvePath(core.getInput(constants_1.Inputs.Path, { required: true }));
let cachePath = utils.resolvePath(core.getInput(constants_1.Inputs.Path, { required: true }));
core.debug(`Cache Path: ${cachePath}`);
const primaryKey = core.getInput(constants_1.Inputs.Key, { required: true });
core.saveState(constants_1.State.CacheKey, primaryKey);
@@ -3038,21 +3000,34 @@ function run() {
core.info(`Cache not found for input keys: ${keys.join(", ")}.`);
return;
}
const archivePath = path.join(yield utils.createTempDirectory(), "cache.tgz");
let archivePath = path.join(yield utils.createTempDirectory(), "cache.tgz");
core.debug(`Archive Path: ${archivePath}`);
// Store the cache result
utils.setCacheState(cacheEntry);
// Download the cache from the cache entry
yield cacheHttpClient.downloadCache(cacheEntry, archivePath);
const archiveFileSize = utils.getArchiveFileSize(archivePath);
core.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`);
yield tar_1.extractTar(archivePath, cachePath);
io.mkdirP(cachePath);
// http://man7.org/linux/man-pages/man1/tar.1.html
// tar [-options] <name of the tar archive> [files or directories which to add into archive]
const args = ["-xz"];
const IS_WINDOWS = process.platform === "win32";
if (IS_WINDOWS) {
args.push("--force-local");
archivePath = archivePath.replace(/\\/g, "/");
cachePath = cachePath.replace(/\\/g, "/");
}
args.push(...["-f", archivePath, "-C", cachePath]);
const tarPath = yield io.which("tar", true);
core.debug(`Tar Path: ${tarPath}`);
const archiveFileSize = fs.statSync(archivePath).size;
core.debug(`File Size: ${archiveFileSize}`);
yield exec_1.exec(`"${tarPath}"`, args);
const isExactKeyMatch = utils.isExactKeyMatch(primaryKey, cacheEntry);
utils.setCacheHitOutput(isExactKeyMatch);
core.info(`Cache restored from key: ${cacheEntry && cacheEntry.cacheKey}`);
}
catch (error) {
utils.logWarning(error.message);
core.warning(error.message);
utils.setCacheHitOutput(false);
}
}
@@ -5142,81 +5117,6 @@ var personalaccesstoken_1 = __webpack_require__(327);
exports.PersonalAccessTokenCredentialHandler = personalaccesstoken_1.PersonalAccessTokenCredentialHandler;
/***/ }),
/***/ 943:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const exec_1 = __webpack_require__(986);
const io = __importStar(__webpack_require__(1));
const fs_1 = __webpack_require__(747);
function getTarPath() {
return __awaiter(this, void 0, void 0, function* () {
// Explicitly use BSD Tar on Windows
const IS_WINDOWS = process.platform === "win32";
if (IS_WINDOWS) {
const systemTar = `${process.env["windir"]}\\System32\\tar.exe`;
if (fs_1.existsSync(systemTar)) {
return systemTar;
}
}
return yield io.which("tar", true);
});
}
function execTar(args) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
try {
const tarPath = yield getTarPath();
const tarExec = process.platform !== "win32" ? `sudo ${tarPath}` : tarPath;
yield exec_1.exec(`"${tarExec}"`, args);
}
catch (error) {
const IS_WINDOWS = process.platform === "win32";
if (IS_WINDOWS) {
throw new Error(`Tar failed with error: ${(_a = error) === null || _a === void 0 ? void 0 : _a.message}. Ensure BSD tar is installed and on the PATH.`);
}
throw new Error(`Tar failed with error: ${(_b = error) === null || _b === void 0 ? void 0 : _b.message}`);
}
});
}
function extractTar(archivePath, targetDirectory) {
return __awaiter(this, void 0, void 0, function* () {
// Create directory to extract tar into
yield io.mkdirP(targetDirectory);
const args = ["-xz", "-f", archivePath, "-C", targetDirectory];
yield execTar(args);
});
}
exports.extractTar = extractTar;
function createTar(archivePath, sourceDirectory) {
return __awaiter(this, void 0, void 0, function* () {
const args = ["-cz", "-f", archivePath, "-C", sourceDirectory, "."];
yield execTar(args);
});
}
exports.createTar = createTar;
/***/ }),
/***/ 986:
+70 -170
View File
@@ -1496,26 +1496,6 @@ const fs = __importStar(__webpack_require__(747));
const Handlers_1 = __webpack_require__(941);
const HttpClient_1 = __webpack_require__(874);
const RestClient_1 = __webpack_require__(105);
function getCacheUrl() {
// Ideally we just use ACTIONS_CACHE_URL
const cacheUrl = (process.env["ACTIONS_CACHE_URL"] ||
process.env["ACTIONS_RUNTIME_URL"] ||
"").replace("pipelines", "artifactcache");
if (!cacheUrl) {
throw new Error("Cache Service Url not found, unable to restore cache.");
}
core.debug(`Cache Url: ${cacheUrl}`);
return cacheUrl;
}
function createAcceptHeader(type, apiVersion) {
return `${type};api-version=${apiVersion}`;
}
function getRequestOptions() {
const requestOptions = {
acceptHeader: createAcceptHeader("application/json", "5.2-preview.1")
};
return requestOptions;
}
function getCacheEntry(keys) {
return __awaiter(this, void 0, void 0, function* () {
const cacheUrl = getCacheUrl();
@@ -1533,16 +1513,24 @@ function getCacheEntry(keys) {
throw new Error(`Cache service responded with ${response.statusCode}`);
}
const cacheResult = response.result;
core.debug(`Cache Result:`);
core.debug(JSON.stringify(cacheResult));
if (!cacheResult || !cacheResult.archiveLocation) {
throw new Error("Cache not found.");
}
core.setSecret(cacheResult.archiveLocation);
core.debug(`Cache Result:`);
core.debug(JSON.stringify(cacheResult));
return cacheResult;
});
}
exports.getCacheEntry = getCacheEntry;
function downloadCache(cacheEntry, archivePath) {
return __awaiter(this, void 0, void 0, function* () {
const stream = fs.createWriteStream(archivePath);
const httpClient = new HttpClient_1.HttpClient("actions/cache");
const downloadResponse = yield httpClient.get(cacheEntry.archiveLocation);
yield pipeResponseToStream(downloadResponse, stream);
});
}
exports.downloadCache = downloadCache;
function pipeResponseToStream(response, stream) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise(resolve => {
@@ -1552,19 +1540,8 @@ function pipeResponseToStream(response, stream) {
});
});
}
function downloadCache(cacheEntry, archivePath) {
function saveCache(stream, key) {
return __awaiter(this, void 0, void 0, function* () {
const stream = fs.createWriteStream(archivePath);
const httpClient = new HttpClient_1.HttpClient("actions/cache");
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const downloadResponse = yield httpClient.get(cacheEntry.archiveLocation);
yield pipeResponseToStream(downloadResponse, stream);
});
}
exports.downloadCache = downloadCache;
function saveCache(key, archivePath) {
return __awaiter(this, void 0, void 0, function* () {
const stream = fs.createReadStream(archivePath);
const cacheUrl = getCacheUrl();
const token = process.env["ACTIONS_RUNTIME_TOKEN"] || "";
const bearerCredentialHandler = new Handlers_1.BearerCredentialHandler(token);
@@ -1585,6 +1562,26 @@ function saveCache(key, archivePath) {
});
}
exports.saveCache = saveCache;
function getRequestOptions() {
const requestOptions = {
acceptHeader: createAcceptHeader("application/json", "5.2-preview.1")
};
return requestOptions;
}
function createAcceptHeader(type, apiVersion) {
return `${type};api-version=${apiVersion}`;
}
function getCacheUrl() {
// Ideally we just use ACTIONS_CACHE_URL
let cacheUrl = (process.env["ACTIONS_CACHE_URL"] ||
process.env["ACTIONS_RUNTIME_URL"] ||
"").replace("pipelines", "artifactcache");
if (!cacheUrl) {
throw new Error("Cache Service Url not found, unable to restore cache.");
}
core.debug(`Cache Url: ${cacheUrl}`);
return cacheUrl;
}
/***/ }),
@@ -2142,7 +2139,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(__webpack_require__(470));
const io = __importStar(__webpack_require__(1));
const fs = __importStar(__webpack_require__(747));
const os = __importStar(__webpack_require__(87));
const path = __importStar(__webpack_require__(622));
const uuidV4 = __importStar(__webpack_require__(826));
@@ -2174,10 +2170,6 @@ function createTempDirectory() {
});
}
exports.createTempDirectory = createTempDirectory;
function getArchiveFileSize(path) {
return fs.statSync(path).size;
}
exports.getArchiveFileSize = getArchiveFileSize;
function isExactKeyMatch(key, cacheResult) {
return !!(cacheResult &&
cacheResult.cacheKey &&
@@ -2186,14 +2178,6 @@ function isExactKeyMatch(key, cacheResult) {
}) === 0);
}
exports.isExactKeyMatch = isExactKeyMatch;
function setCacheState(state) {
core.saveState(constants_1.State.CacheResult, JSON.stringify(state));
}
exports.setCacheState = setCacheState;
function setCacheHitOutput(isCacheHit) {
core.setOutput(constants_1.Outputs.CacheHit, isCacheHit.toString());
}
exports.setCacheHitOutput = setCacheHitOutput;
function setOutputAndState(key, cacheResult) {
setCacheHitOutput(isExactKeyMatch(key, cacheResult));
// Store the cache result if it exists
@@ -2203,17 +2187,17 @@ exports.setOutputAndState = setOutputAndState;
function getCacheState() {
const stateData = core.getState(constants_1.State.CacheResult);
core.debug(`State: ${stateData}`);
if (stateData) {
return JSON.parse(stateData);
}
return undefined;
return (stateData && JSON.parse(stateData));
}
exports.getCacheState = getCacheState;
function logWarning(message) {
const warningPrefix = "[warning]";
core.info(`${warningPrefix}${message}`);
function setCacheState(state) {
core.saveState(constants_1.State.CacheResult, JSON.stringify(state));
}
exports.logWarning = logWarning;
exports.setCacheState = setCacheState;
function setCacheHitOutput(isCacheHit) {
core.setOutput(constants_1.Outputs.CacheHit, isCacheHit.toString());
}
exports.setCacheHitOutput = setCacheHitOutput;
function resolvePath(filePath) {
if (filePath[0] === "~") {
const home = os.homedir();
@@ -2225,18 +2209,6 @@ function resolvePath(filePath) {
return path.resolve(filePath);
}
exports.resolvePath = resolvePath;
function getSupportedEvents() {
return [constants_1.Events.Push, constants_1.Events.PullRequest];
}
exports.getSupportedEvents = getSupportedEvents;
// Currently the cache token is only authorized for push and pull_request events
// All other events will fail when reading and saving the cache
// See GitHub Context https://help.github.com/actions/automating-your-workflow-with-github-actions/contexts-and-expression-syntax-for-github-actions#github-context
function isValidEvent() {
const githubEvent = process.env[constants_1.Events.Key] || "";
return getSupportedEvents().includes(githubEvent);
}
exports.isValidEvent = isValidEvent;
/***/ }),
@@ -2879,47 +2851,56 @@ var __importStar = (this && this.__importStar) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(__webpack_require__(470));
const exec_1 = __webpack_require__(986);
const io = __importStar(__webpack_require__(1));
const fs = __importStar(__webpack_require__(747));
const path = __importStar(__webpack_require__(622));
const cacheHttpClient = __importStar(__webpack_require__(154));
const constants_1 = __webpack_require__(694);
const tar_1 = __webpack_require__(943);
const utils = __importStar(__webpack_require__(443));
function run() {
return __awaiter(this, void 0, void 0, function* () {
try {
if (!utils.isValidEvent()) {
utils.logWarning(`Event Validation Error: The event type ${process.env[constants_1.Events.Key]} is not supported. Only ${utils
.getSupportedEvents()
.join(", ")} events are supported at this time.`);
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.CacheKey);
if (!primaryKey) {
utils.logWarning(`Error retrieving key from state.`);
core.warning(`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 cachePath = utils.resolvePath(core.getInput(constants_1.Inputs.Path, { required: true }));
let cachePath = utils.resolvePath(core.getInput(constants_1.Inputs.Path, { required: true }));
core.debug(`Cache Path: ${cachePath}`);
const archivePath = path.join(yield utils.createTempDirectory(), "cache.tgz");
let archivePath = path.join(yield utils.createTempDirectory(), "cache.tgz");
core.debug(`Archive Path: ${archivePath}`);
yield tar_1.createTar(archivePath, cachePath);
// http://man7.org/linux/man-pages/man1/tar.1.html
// tar [-options] <name of the tar archive> [files or directories which to add into archive]
const args = ["-cz"];
const IS_WINDOWS = process.platform === "win32";
if (IS_WINDOWS) {
args.push("--force-local");
archivePath = archivePath.replace(/\\/g, "/");
cachePath = cachePath.replace(/\\/g, "/");
}
args.push(...["-f", archivePath, "-C", cachePath, "."]);
const tarPath = yield io.which("tar", true);
core.debug(`Tar Path: ${tarPath}`);
yield exec_1.exec(`"${tarPath}"`, args);
const fileSizeLimit = 400 * 1024 * 1024; // 400MB
const archiveFileSize = utils.getArchiveFileSize(archivePath);
const archiveFileSize = fs.statSync(archivePath).size;
core.debug(`File Size: ${archiveFileSize}`);
if (archiveFileSize > fileSizeLimit) {
utils.logWarning(`Cache size of ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B) is over the 400MB limit, not saving cache.`);
core.warning(`Cache size of ${archiveFileSize} bytes is over the 400MB limit, not saving cache.`);
return;
}
yield cacheHttpClient.saveCache(primaryKey, archivePath);
const stream = fs.createReadStream(archivePath);
yield cacheHttpClient.saveCache(stream, primaryKey);
}
catch (error) {
utils.logWarning(error.message);
core.warning(error.message);
}
});
}
@@ -2937,25 +2918,19 @@ exports.default = run;
Object.defineProperty(exports, "__esModule", { value: true });
var Inputs;
(function (Inputs) {
Inputs["Key"] = "key";
Inputs["Path"] = "path";
Inputs["RestoreKeys"] = "restore-keys";
Inputs.Key = "key";
Inputs.Path = "path";
Inputs.RestoreKeys = "restore-keys";
})(Inputs = exports.Inputs || (exports.Inputs = {}));
var Outputs;
(function (Outputs) {
Outputs["CacheHit"] = "cache-hit";
Outputs.CacheHit = "cache-hit";
})(Outputs = exports.Outputs || (exports.Outputs = {}));
var State;
(function (State) {
State["CacheKey"] = "CACHE_KEY";
State["CacheResult"] = "CACHE_RESULT";
State.CacheKey = "CACHE_KEY";
State.CacheResult = "CACHE_RESULT";
})(State = exports.State || (exports.State = {}));
var Events;
(function (Events) {
Events["Key"] = "GITHUB_EVENT_NAME";
Events["Push"] = "push";
Events["PullRequest"] = "pull_request";
})(Events = exports.Events || (exports.Events = {}));
/***/ }),
@@ -5116,81 +5091,6 @@ var personalaccesstoken_1 = __webpack_require__(327);
exports.PersonalAccessTokenCredentialHandler = personalaccesstoken_1.PersonalAccessTokenCredentialHandler;
/***/ }),
/***/ 943:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const exec_1 = __webpack_require__(986);
const io = __importStar(__webpack_require__(1));
const fs_1 = __webpack_require__(747);
function getTarPath() {
return __awaiter(this, void 0, void 0, function* () {
// Explicitly use BSD Tar on Windows
const IS_WINDOWS = process.platform === "win32";
if (IS_WINDOWS) {
const systemTar = `${process.env["windir"]}\\System32\\tar.exe`;
if (fs_1.existsSync(systemTar)) {
return systemTar;
}
}
return yield io.which("tar", true);
});
}
function execTar(args) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
try {
const tarPath = yield getTarPath();
const tarExec = process.platform !== "win32" ? `sudo ${tarPath}` : tarPath;
yield exec_1.exec(`"${tarExec}"`, args);
}
catch (error) {
const IS_WINDOWS = process.platform === "win32";
if (IS_WINDOWS) {
throw new Error(`Tar failed with error: ${(_a = error) === null || _a === void 0 ? void 0 : _a.message}. Ensure BSD tar is installed and on the PATH.`);
}
throw new Error(`Tar failed with error: ${(_b = error) === null || _b === void 0 ? void 0 : _b.message}`);
}
});
}
function extractTar(archivePath, targetDirectory) {
return __awaiter(this, void 0, void 0, function* () {
// Create directory to extract tar into
yield io.mkdirP(targetDirectory);
const args = ["-xz", "-f", archivePath, "-C", targetDirectory];
yield execTar(args);
});
}
exports.extractTar = extractTar;
function createTar(archivePath, sourceDirectory) {
return __awaiter(this, void 0, void 0, function* () {
const args = ["-cz", "-f", archivePath, "-C", sourceDirectory, "."];
yield execTar(args);
});
}
exports.createTar = createTar;
/***/ }),
/***/ 986:
+5 -148
View File
@@ -1,20 +1,18 @@
# Examples
- [C# - NuGet](#c---nuget)
- [C# - Nuget](#c---nuget)
- [Elixir - Mix](#elixir---mix)
- [Go - Modules](#go---modules)
- [Java - Gradle](#java---gradle)
- [Java - Maven](#java---maven)
- [Node - npm](#node---npm)
- [Node - Yarn](#node---yarn)
- [PHP - Composer](#php---composer)
- [Python - pip](#python---pip)
- [Ruby - Gem](#ruby---gem)
- [Rust - Cargo](#rust---cargo)
- [Swift, Objective-C - Carthage](#swift-objective-c---carthage)
- [Swift, Objective-C - CocoaPods](#swift-objective-c---cocoapods)
## C# - NuGet
## C# - Nuget
Using [NuGet lock files](https://docs.microsoft.com/nuget/consume-packages/package-references-in-project-files#locking-dependencies):
```yaml
@@ -26,21 +24,6 @@ Using [NuGet lock files](https://docs.microsoft.com/nuget/consume-packages/packa
${{ runner.os }}-nuget-
```
Depending on the environment, huge packages might be pre-installed in the global cache folder.
If you do not want to include them, consider to move the cache folder like below.
>Note: This workflow does not work for projects that require files to be placed in user profile package folder
```yaml
env:
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
steps:
- uses: actions/cache@v1
with:
path: ${{ github.workspace }}/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
restore-keys: |
${{ runner.os }}-nuget-
```
## Elixir - Mix
```yaml
- uses: actions/cache@v1
@@ -86,144 +69,26 @@ steps:
## Node - npm
For npm, cache files are stored in `~/.npm` on Posix, or `%AppData%/npm-cache` on Windows. See https://docs.npmjs.com/cli/cache#cache
>Note: It is not recommended to cache `node_modules`, as it can break across Node versions and won't work with `npm ci`
### macOS and Ubuntu
```yaml
- uses: actions/cache@v1
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
```
### Windows
```yaml
- uses: actions/cache@v1
with:
path: ~\AppData\Roaming\npm-cache
key: ${{ runner.os }}-node-${{ hashFiles('**\package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
```
### Using multiple systems and `npm config`
```yaml
- name: Get npm cache directory
id: npm-cache
run: |
echo "::set-output name=dir::$(npm config get cache)"
- uses: actions/cache@v1
with:
path: ${{ steps.npm-cache.outputs.dir }}
path: node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
```
## Node - Yarn
The yarn cache directory will depend on your operating system and version of `yarn`. See https://yarnpkg.com/lang/en/docs/cli/cache/ for more info.
```yaml
- name: Get yarn cache
id: yarn-cache
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v1
with:
path: ${{ steps.yarn-cache.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
path: ~/.cache/yarn
key: ${{ runner.os }}-yarn-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }}
restore-keys: |
${{ runner.os }}-yarn-
```
## PHP - Composer
```yaml
- name: Get Composer Cache Directory
id: composer-cache
run: |
echo "::set-output name=dir::$(composer config cache-files-dir)"
- uses: actions/cache@v1
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-composer-
```
## Python - pip
For pip, the cache directory will vary by OS. See https://pip.pypa.io/en/stable/reference/pip_install/#caching
Locations:
- Ubuntu: `~/.cache/pip`
- Windows: `~\AppData\Local\pip\Cache`
- macOS: `~/Library/Caches/pip`
### Simple example
```yaml
- uses: actions/cache@v1
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
```
Replace `~/.cache/pip` with the correct `path` if not using Ubuntu.
### Multiple OS's in a workflow
```yaml
- uses: actions/cache@v1
if: startsWith(runner.os, 'Linux')
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- uses: actions/cache@v1
if: startsWith(runner.os, 'macOS')
with:
path: ~/Library/Caches/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- uses: actions/cache@v1
if: startsWith(runner.os, 'Windows')
with:
path: ~\AppData\Local\pip\Cache
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
```
### Using a script to get cache location
> Note: This uses an internal pip API and may not always work
```yaml
- name: Get pip cache
id: pip-cache
run: |
python -c "from pip._internal.locations import USER_CACHE_DIR; print('::set-output name=dir::' + USER_CACHE_DIR)"
- uses: actions/cache@v1
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
```
## Ruby - Gem
```yaml
@@ -234,14 +99,6 @@ Replace `~/.cache/pip` with the correct `path` if not using Ubuntu.
restore-keys: |
${{ runner.os }}-gem-
```
When dependencies are installed later in the workflow, we must specify the same path for the bundler.
```yaml
- name: Bundle install
run: |
bundle config path vendor/bundle
bundle install --jobs 4 --retry 3
```
## Rust - Cargo
+17 -20
View File
@@ -1,23 +1,20 @@
require("nock").disableNetConnect();
module.exports = {
clearMocks: true,
moduleFileExtensions: ["js", "ts"],
testEnvironment: "node",
testMatch: ["**/*.test.ts"],
testRunner: "jest-circus/runner",
transform: {
"^.+\\.ts$": "ts-jest"
},
verbose: true
};
clearMocks: true,
moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
testRunner: 'jest-circus/runner',
transform: {
'^.+\\.ts$': 'ts-jest'
},
verbose: true
}
const processStdoutWrite = process.stdout.write.bind(process.stdout);
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const processStdoutWrite = process.stdout.write.bind(process.stdout)
process.stdout.write = (str, encoding, cb) => {
// Core library will directly call process.stdout.write for commands
// We don't want :: commands to be executed by the runner during tests
if (!str.match(/^::/)) {
return processStdoutWrite(str, encoding, cb);
}
};
// Core library will directly call process.stdout.write for commands
// We don't want :: commands to be executed by the runner during tests
if (!str.match(/^::/)) {
return processStdoutWrite(str, encoding, cb);
}
}
+7 -1030
View File
@@ -1,6 +1,6 @@
{
"name": "cache",
"version": "1.0.3",
"version": "1.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -477,12 +477,6 @@
"@babel/types": "^7.3.0"
}
},
"@types/eslint-visitor-keys": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
"integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==",
"dev": true
},
"@types/istanbul-lib-coverage": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz",
@@ -523,21 +517,6 @@
"integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==",
"dev": true
},
"@types/json-schema": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz",
"integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==",
"dev": true
},
"@types/nock": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/@types/nock/-/nock-11.1.0.tgz",
"integrity": "sha512-jI/ewavBQ7X5178262JQR0ewicPAcJhXS/iFaNJl0VHLfyosZ/kwSrsa6VNQNSO8i9d8SqdRgOtZSOKJ/+iNMw==",
"dev": true,
"requires": {
"nock": "*"
}
},
"@types/node": {
"version": "12.6.9",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.6.9.tgz",
@@ -565,73 +544,6 @@
"integrity": "sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw==",
"dev": true
},
"@typescript-eslint/eslint-plugin": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.7.0.tgz",
"integrity": "sha512-H5G7yi0b0FgmqaEUpzyBlVh0d9lq4cWG2ap0RKa6BkF3rpBb6IrAoubt1NWh9R2kRs/f0k6XwRDiDz3X/FqXhQ==",
"dev": true,
"requires": {
"@typescript-eslint/experimental-utils": "2.7.0",
"eslint-utils": "^1.4.2",
"functional-red-black-tree": "^1.0.1",
"regexpp": "^2.0.1",
"tsutils": "^3.17.1"
}
},
"@typescript-eslint/experimental-utils": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.7.0.tgz",
"integrity": "sha512-9/L/OJh2a5G2ltgBWJpHRfGnt61AgDeH6rsdg59BH0naQseSwR7abwHq3D5/op0KYD/zFT4LS5gGvWcMmegTEg==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.3",
"@typescript-eslint/typescript-estree": "2.7.0",
"eslint-scope": "^5.0.0"
}
},
"@typescript-eslint/parser": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.7.0.tgz",
"integrity": "sha512-ctC0g0ZvYclxMh/xI+tyqP0EC2fAo6KicN9Wm2EIao+8OppLfxji7KAGJosQHSGBj3TcqUrA96AjgXuKa5ob2g==",
"dev": true,
"requires": {
"@types/eslint-visitor-keys": "^1.0.0",
"@typescript-eslint/experimental-utils": "2.7.0",
"@typescript-eslint/typescript-estree": "2.7.0",
"eslint-visitor-keys": "^1.1.0"
}
},
"@typescript-eslint/typescript-estree": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.7.0.tgz",
"integrity": "sha512-vVCE/DY72N4RiJ/2f10PTyYekX2OLaltuSIBqeHYI44GQ940VCYioInIb8jKMrK9u855OEJdFC+HmWAZTnC+Ag==",
"dev": true,
"requires": {
"debug": "^4.1.1",
"glob": "^7.1.4",
"is-glob": "^4.0.1",
"lodash.unescape": "4.0.1",
"semver": "^6.3.0",
"tsutils": "^3.17.1"
},
"dependencies": {
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
}
}
},
"@zeit/ncc": {
"version": "0.20.5",
"resolved": "https://registry.npmjs.org/@zeit/ncc/-/ncc-0.20.5.tgz",
@@ -668,12 +580,6 @@
}
}
},
"acorn-jsx": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz",
"integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==",
"dev": true
},
"acorn-walk": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz",
@@ -723,15 +629,6 @@
"normalize-path": "^2.1.1"
}
},
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"requires": {
"sprintf-js": "~1.0.2"
}
},
"arr-diff": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
@@ -756,16 +653,6 @@
"integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=",
"dev": true
},
"array-includes": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
"integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=",
"dev": true,
"requires": {
"define-properties": "^1.1.2",
"es-abstract": "^1.7.0"
}
},
"array-unique": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
@@ -787,12 +674,6 @@
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
"dev": true
},
"assertion-error": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
"dev": true
},
"assign-symbols": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
@@ -1082,12 +963,6 @@
}
}
},
"callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
"dev": true
},
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
@@ -1109,20 +984,6 @@
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
"dev": true
},
"chai": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
"integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==",
"dev": true,
"requires": {
"assertion-error": "^1.1.0",
"check-error": "^1.0.2",
"deep-eql": "^3.0.1",
"get-func-name": "^2.0.0",
"pathval": "^1.1.0",
"type-detect": "^4.0.5"
}
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -1134,18 +995,6 @@
"supports-color": "^5.3.0"
}
},
"chardet": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
"dev": true
},
"check-error": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
"dev": true
},
"ci-info": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
@@ -1181,21 +1030,6 @@
}
}
},
"cli-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
"integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
"dev": true,
"requires": {
"restore-cursor": "^3.1.0"
}
},
"cli-width": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
"integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
"dev": true
},
"cliui": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
@@ -1289,12 +1123,6 @@
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"contains-path": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz",
"integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=",
"dev": true
},
"convert-source-map": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz",
@@ -1406,15 +1234,6 @@
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
"dev": true
},
"deep-eql": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
"integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
"dev": true,
"requires": {
"type-detect": "^4.0.0"
}
},
"deep-is": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@@ -1495,15 +1314,6 @@
"integrity": "sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw==",
"dev": true
},
"doctrine": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
"dev": true,
"requires": {
"esutils": "^2.0.2"
}
},
"domexception": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz",
@@ -1523,12 +1333,6 @@
"safer-buffer": "^2.1.0"
}
},
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
"end-of-stream": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
@@ -1599,267 +1403,6 @@
}
}
},
"eslint": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-6.6.0.tgz",
"integrity": "sha512-PpEBq7b6qY/qrOmpYQ/jTMDYfuQMELR4g4WI1M/NaSDDD/bdcMb+dj4Hgks7p41kW2caXsPsEZAEAyAgjVVC0g==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
"ajv": "^6.10.0",
"chalk": "^2.1.0",
"cross-spawn": "^6.0.5",
"debug": "^4.0.1",
"doctrine": "^3.0.0",
"eslint-scope": "^5.0.0",
"eslint-utils": "^1.4.3",
"eslint-visitor-keys": "^1.1.0",
"espree": "^6.1.2",
"esquery": "^1.0.1",
"esutils": "^2.0.2",
"file-entry-cache": "^5.0.1",
"functional-red-black-tree": "^1.0.1",
"glob-parent": "^5.0.0",
"globals": "^11.7.0",
"ignore": "^4.0.6",
"import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4",
"inquirer": "^7.0.0",
"is-glob": "^4.0.0",
"js-yaml": "^3.13.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.3.0",
"lodash": "^4.17.14",
"minimatch": "^3.0.4",
"mkdirp": "^0.5.1",
"natural-compare": "^1.4.0",
"optionator": "^0.8.2",
"progress": "^2.0.0",
"regexpp": "^2.0.1",
"semver": "^6.1.2",
"strip-ansi": "^5.2.0",
"strip-json-comments": "^3.0.1",
"table": "^5.2.3",
"text-table": "^0.2.0",
"v8-compile-cache": "^2.0.3"
},
"dependencies": {
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
}
}
},
"eslint-config-prettier": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.5.0.tgz",
"integrity": "sha512-cjXp8SbO9VFGW/Z7mbTydqS9to8Z58E5aYhj3e1+Hx7lS9s6gL5ILKNpCqZAFOVYRcSkWPFYljHrEh8QFEK5EQ==",
"dev": true,
"requires": {
"get-stdin": "^6.0.0"
}
},
"eslint-import-resolver-node": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz",
"integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==",
"dev": true,
"requires": {
"debug": "^2.6.9",
"resolve": "^1.5.0"
}
},
"eslint-module-utils": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz",
"integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==",
"dev": true,
"requires": {
"debug": "^2.6.8",
"pkg-dir": "^2.0.0"
}
},
"eslint-plugin-import": {
"version": "2.18.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz",
"integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==",
"dev": true,
"requires": {
"array-includes": "^3.0.3",
"contains-path": "^0.1.0",
"debug": "^2.6.9",
"doctrine": "1.5.0",
"eslint-import-resolver-node": "^0.3.2",
"eslint-module-utils": "^2.4.0",
"has": "^1.0.3",
"minimatch": "^3.0.4",
"object.values": "^1.1.0",
"read-pkg-up": "^2.0.0",
"resolve": "^1.11.0"
},
"dependencies": {
"doctrine": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
"integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
"dev": true,
"requires": {
"esutils": "^2.0.2",
"isarray": "^1.0.0"
}
},
"find-up": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
"integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
"dev": true,
"requires": {
"locate-path": "^2.0.0"
}
},
"locate-path": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
"integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
"dev": true,
"requires": {
"p-locate": "^2.0.0",
"path-exists": "^3.0.0"
}
},
"p-limit": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
"integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
"dev": true,
"requires": {
"p-try": "^1.0.0"
}
},
"p-locate": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
"integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
"dev": true,
"requires": {
"p-limit": "^1.1.0"
}
},
"p-try": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
"integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
"dev": true
},
"read-pkg-up": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
"integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
"dev": true,
"requires": {
"find-up": "^2.0.0",
"read-pkg": "^2.0.0"
}
}
}
},
"eslint-plugin-jest": {
"version": "23.0.3",
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-23.0.3.tgz",
"integrity": "sha512-9cNxr66zeOyz1S9AkQL4/ouilR6QHpYj8vKOQZ60fu9hAt5PJWS4KqWqfr1aqN5NFEZSPjFOla2Azn+KTWiGwg==",
"dev": true,
"requires": {
"@typescript-eslint/experimental-utils": "^2.5.0"
}
},
"eslint-plugin-prettier": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.1.tgz",
"integrity": "sha512-A+TZuHZ0KU0cnn56/9mfR7/KjUJ9QNVXUhwvRFSR7PGPe0zQR6PTkmyqg1AtUUEOzTqeRsUwyKFh0oVZKVCrtA==",
"dev": true,
"requires": {
"prettier-linter-helpers": "^1.0.0"
}
},
"eslint-scope": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
"integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==",
"dev": true,
"requires": {
"esrecurse": "^4.1.0",
"estraverse": "^4.1.1"
}
},
"eslint-utils": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
"integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
"dev": true,
"requires": {
"eslint-visitor-keys": "^1.1.0"
}
},
"eslint-visitor-keys": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
"integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
"dev": true
},
"espree": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz",
"integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==",
"dev": true,
"requires": {
"acorn": "^7.1.0",
"acorn-jsx": "^5.1.0",
"eslint-visitor-keys": "^1.1.0"
},
"dependencies": {
"acorn": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz",
"integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==",
"dev": true
}
}
},
"esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"dev": true
},
"esquery": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
"integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==",
"dev": true,
"requires": {
"estraverse": "^4.0.0"
}
},
"esrecurse": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
"integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
"dev": true,
"requires": {
"estraverse": "^4.1.0"
}
},
"estraverse": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
@@ -1990,17 +1533,6 @@
}
}
},
"external-editor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
"integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
"dev": true,
"requires": {
"chardet": "^0.7.0",
"iconv-lite": "^0.4.24",
"tmp": "^0.0.33"
}
},
"extglob": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
@@ -2078,12 +1610,6 @@
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
"dev": true
},
"fast-diff": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
"dev": true
},
"fast-json-stable-stringify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
@@ -2105,24 +1631,6 @@
"bser": "^2.0.0"
}
},
"figures": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz",
"integrity": "sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==",
"dev": true,
"requires": {
"escape-string-regexp": "^1.0.5"
}
},
"file-entry-cache": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
"integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
"dev": true,
"requires": {
"flat-cache": "^2.0.1"
}
},
"fill-range": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
@@ -2155,23 +1663,6 @@
"locate-path": "^3.0.0"
}
},
"flat-cache": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
"integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
"dev": true,
"requires": {
"flatted": "^2.0.0",
"rimraf": "2.6.3",
"write": "1.0.3"
}
},
"flatted": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz",
"integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==",
"dev": true
},
"for-in": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@@ -2764,30 +2255,12 @@
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
"functional-red-black-tree": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
"dev": true
},
"get-caller-file": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
"integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
"dev": true
},
"get-func-name": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
"dev": true
},
"get-stdin": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz",
"integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==",
"dev": true
},
"get-stream": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
@@ -2826,15 +2299,6 @@
"path-is-absolute": "^1.0.0"
}
},
"glob-parent": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz",
"integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==",
"dev": true,
"requires": {
"is-glob": "^4.0.1"
}
},
"globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
@@ -2977,30 +2441,6 @@
"safer-buffer": ">= 2.1.2 < 3"
}
},
"ignore": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
"dev": true
},
"import-fresh": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz",
"integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==",
"dev": true,
"requires": {
"parent-module": "^1.0.0",
"resolve-from": "^4.0.0"
},
"dependencies": {
"resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true
}
}
},
"import-local": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
@@ -3044,72 +2484,6 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"inquirer": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.0.tgz",
"integrity": "sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ==",
"dev": true,
"requires": {
"ansi-escapes": "^4.2.1",
"chalk": "^2.4.2",
"cli-cursor": "^3.1.0",
"cli-width": "^2.0.0",
"external-editor": "^3.0.3",
"figures": "^3.0.0",
"lodash": "^4.17.15",
"mute-stream": "0.0.8",
"run-async": "^2.2.0",
"rxjs": "^6.4.0",
"string-width": "^4.1.0",
"strip-ansi": "^5.1.0",
"through": "^2.3.6"
},
"dependencies": {
"ansi-escapes": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.2.1.tgz",
"integrity": "sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q==",
"dev": true,
"requires": {
"type-fest": "^0.5.2"
}
},
"ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
"dev": true
},
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true
},
"string-width": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
"integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
"dev": true,
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.0"
},
"dependencies": {
"strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"dev": true,
"requires": {
"ansi-regex": "^5.0.0"
}
}
}
}
}
},
"invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
@@ -3223,12 +2597,6 @@
"integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
"dev": true
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"dev": true
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
@@ -3241,15 +2609,6 @@
"integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
"dev": true
},
"is-glob": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
"dev": true,
"requires": {
"is-extglob": "^2.1.1"
}
},
"is-number": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
@@ -3270,12 +2629,6 @@
}
}
},
"is-promise": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
"integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
"dev": true
},
"is-regex": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
@@ -3902,16 +3255,6 @@
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true
},
"js-yaml": {
"version": "3.13.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
"dev": true,
"requires": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
}
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
@@ -3976,12 +3319,6 @@
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true
},
"json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
"dev": true
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
@@ -4086,12 +3423,6 @@
"integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
"dev": true
},
"lodash.unescape": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz",
"integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=",
"dev": true
},
"loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -4300,12 +3631,6 @@
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
},
"mute-stream": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
"dev": true
},
"nan": {
"version": "2.14.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
@@ -4350,37 +3675,6 @@
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
"dev": true
},
"nock": {
"version": "11.7.0",
"resolved": "https://registry.npmjs.org/nock/-/nock-11.7.0.tgz",
"integrity": "sha512-7c1jhHew74C33OBeRYyQENT+YXQiejpwIrEjinh6dRurBae+Ei4QjeUaPlkptIF0ZacEiVCnw8dWaxqepkiihg==",
"dev": true,
"requires": {
"chai": "^4.1.2",
"debug": "^4.1.0",
"json-stringify-safe": "^5.0.1",
"lodash": "^4.17.13",
"mkdirp": "^0.5.0",
"propagate": "^2.0.0"
},
"dependencies": {
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
}
}
},
"node-int64": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
@@ -4551,18 +3845,6 @@
}
}
},
"object.values": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz",
"integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==",
"dev": true,
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.12.0",
"function-bind": "^1.1.1",
"has": "^1.0.3"
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -4572,15 +3854,6 @@
"wrappy": "1"
}
},
"onetime": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
"integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
"dev": true,
"requires": {
"mimic-fn": "^2.1.0"
}
},
"optimist": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
@@ -4632,12 +3905,6 @@
"mem": "^4.0.0"
}
},
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true
},
"p-defer": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
@@ -4695,15 +3962,6 @@
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true
},
"parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dev": true,
"requires": {
"callsites": "^3.0.0"
}
},
"parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
@@ -4759,12 +4017,6 @@
"pify": "^3.0.0"
}
},
"pathval": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz",
"integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=",
"dev": true
},
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@@ -4786,60 +4038,6 @@
"node-modules-regexp": "^1.0.0"
}
},
"pkg-dir": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
"integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
"dev": true,
"requires": {
"find-up": "^2.1.0"
},
"dependencies": {
"find-up": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
"integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
"dev": true,
"requires": {
"locate-path": "^2.0.0"
}
},
"locate-path": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
"integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
"dev": true,
"requires": {
"p-locate": "^2.0.0",
"path-exists": "^3.0.0"
}
},
"p-limit": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
"integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
"dev": true,
"requires": {
"p-try": "^1.0.0"
}
},
"p-locate": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
"integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
"dev": true,
"requires": {
"p-limit": "^1.1.0"
}
},
"p-try": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
"integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
"dev": true
}
}
},
"pn": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz",
@@ -4859,20 +4057,11 @@
"dev": true
},
"prettier": {
"version": "1.19.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz",
"integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==",
"version": "1.18.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz",
"integrity": "sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==",
"dev": true
},
"prettier-linter-helpers": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
"integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
"dev": true,
"requires": {
"fast-diff": "^1.1.2"
}
},
"pretty-format": {
"version": "24.8.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.8.0.tgz",
@@ -4891,12 +4080,6 @@
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"dev": true
},
"progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"dev": true
},
"prompts": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.1.0.tgz",
@@ -4907,12 +4090,6 @@
"sisteransi": "^1.0.0"
}
},
"propagate": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz",
"integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==",
"dev": true
},
"psl": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.3.0.tgz",
@@ -4947,55 +4124,6 @@
"integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==",
"dev": true
},
"read-pkg": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
"integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
"dev": true,
"requires": {
"load-json-file": "^2.0.0",
"normalize-package-data": "^2.3.2",
"path-type": "^2.0.0"
},
"dependencies": {
"load-json-file": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
"integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
"dev": true,
"requires": {
"graceful-fs": "^4.1.2",
"parse-json": "^2.2.0",
"pify": "^2.0.0",
"strip-bom": "^3.0.0"
}
},
"parse-json": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
"integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
"dev": true,
"requires": {
"error-ex": "^1.2.0"
}
},
"path-type": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
"integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
"dev": true,
"requires": {
"pify": "^2.0.0"
}
},
"pify": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
"dev": true
}
}
},
"read-pkg-up": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz",
@@ -5053,12 +4181,6 @@
"safe-regex": "^1.1.0"
}
},
"regexpp": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
"integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
"dev": true
},
"remove-trailing-separator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
@@ -5185,16 +4307,6 @@
"integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
"dev": true
},
"restore-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
"integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
"dev": true,
"requires": {
"onetime": "^5.1.0",
"signal-exit": "^3.0.2"
}
},
"ret": {
"version": "0.1.15",
"resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
@@ -5216,24 +4328,6 @@
"integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==",
"dev": true
},
"run-async": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
"integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
"dev": true,
"requires": {
"is-promise": "^2.1.0"
}
},
"rxjs": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz",
"integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==",
"dev": true,
"requires": {
"tslib": "^1.9.0"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@@ -5361,17 +4455,6 @@
"integrity": "sha512-ZcYcZcT69nSLAR2oLN2JwNmLkJEKGooFMCdvOkFrToUt/WfcRWqhIg4P4KwY4dmLbuyXIx4o4YmPsvMRJYJd/w==",
"dev": true
},
"slice-ansi": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
"integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.0",
"astral-regex": "^1.0.0",
"is-fullwidth-code-point": "^2.0.0"
}
},
"snapdragon": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
@@ -5567,12 +4650,6 @@
"extend-shallow": "^3.0.0"
}
},
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true
},
"sshpk": {
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
@@ -5707,12 +4784,6 @@
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
"dev": true
},
"strip-json-comments": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz",
"integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==",
"dev": true
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@@ -5728,37 +4799,6 @@
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
"dev": true
},
"table": {
"version": "5.4.6",
"resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
"integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
"dev": true,
"requires": {
"ajv": "^6.10.2",
"lodash": "^4.17.14",
"slice-ansi": "^2.1.0",
"string-width": "^3.0.0"
},
"dependencies": {
"emoji-regex": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
"dev": true
},
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"dev": true,
"requires": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
}
}
}
},
"test-exclude": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz",
@@ -5771,33 +4811,12 @@
"require-main-filename": "^2.0.0"
}
},
"text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
"dev": true
},
"throat": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz",
"integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=",
"dev": true
},
"through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
"dev": true
},
"tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
"dev": true,
"requires": {
"os-tmpdir": "~1.0.2"
}
},
"tmpl": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
@@ -5917,21 +4936,6 @@
}
}
},
"tslib": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
"integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==",
"dev": true
},
"tsutils": {
"version": "3.17.1",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz",
"integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==",
"dev": true,
"requires": {
"tslib": "^1.8.1"
}
},
"tunnel": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.4.tgz",
@@ -5961,18 +4965,6 @@
"prelude-ls": "~1.1.2"
}
},
"type-detect": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
"dev": true
},
"type-fest": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz",
"integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==",
"dev": true
},
"typed-rest-client": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.5.0.tgz",
@@ -5983,9 +4975,9 @@
}
},
"typescript": {
"version": "3.7.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz",
"integrity": "sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==",
"version": "3.6.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.4.tgz",
"integrity": "sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==",
"dev": true
},
"uglify-js": {
@@ -6104,12 +5096,6 @@
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
"integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
},
"v8-compile-cache": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz",
"integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==",
"dev": true
},
"validate-npm-package-license": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
@@ -6255,15 +5241,6 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
"write": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
"integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
"dev": true,
"requires": {
"mkdirp": "^0.5.1"
}
},
"write-file-atomic": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz",
+3 -13
View File
@@ -1,13 +1,12 @@
{
"name": "cache",
"version": "1.0.3",
"version": "1.0.1",
"private": true,
"description": "Cache dependencies and build outputs",
"main": "dist/restore/index.js",
"scripts": {
"build": "tsc",
"test": "tsc --noEmit && jest --coverage",
"lint": "eslint **/*.ts --cache",
"format": "prettier --write **/*.ts",
"format-check": "prettier --check **/*.ts",
"release": "ncc build -o dist/restore src/restore.ts && ncc build -o dist/save src/save.ts && git add -f dist/"
@@ -32,22 +31,13 @@
},
"devDependencies": {
"@types/jest": "^24.0.13",
"@types/nock": "^11.1.0",
"@types/node": "^12.0.4",
"@types/uuid": "^3.4.5",
"@typescript-eslint/eslint-plugin": "^2.7.0",
"@typescript-eslint/parser": "^2.7.0",
"@zeit/ncc": "^0.20.5",
"eslint": "^6.6.0",
"eslint-config-prettier": "^6.5.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-jest": "^23.0.3",
"eslint-plugin-prettier": "^3.1.1",
"jest": "^24.8.0",
"jest-circus": "^24.7.1",
"nock": "^11.7.0",
"prettier": "^1.19.1",
"prettier": "1.18.2",
"ts-jest": "^24.0.2",
"typescript": "^3.7.3"
"typescript": "^3.6.4"
}
}
+45 -50
View File
@@ -1,40 +1,13 @@
import * as core from "@actions/core";
import * as fs from "fs";
import { BearerCredentialHandler } from "typed-rest-client/Handlers";
import { HttpClient } from "typed-rest-client/HttpClient";
import { IHttpClientResponse } from "typed-rest-client/Interfaces";
import { IRequestOptions, RestClient } from "typed-rest-client/RestClient";
import { RestClient, IRequestOptions } from "typed-rest-client/RestClient";
import { ArtifactCacheEntry } from "./contracts";
function getCacheUrl(): string {
// Ideally we just use ACTIONS_CACHE_URL
const cacheUrl: string = (
process.env["ACTIONS_CACHE_URL"] ||
process.env["ACTIONS_RUNTIME_URL"] ||
""
).replace("pipelines", "artifactcache");
if (!cacheUrl) {
throw new Error(
"Cache Service Url not found, unable to restore cache."
);
}
core.debug(`Cache Url: ${cacheUrl}`);
return cacheUrl;
}
function createAcceptHeader(type: string, apiVersion: string): string {
return `${type};api-version=${apiVersion}`;
}
function getRequestOptions(): IRequestOptions {
const requestOptions: IRequestOptions = {
acceptHeader: createAcceptHeader("application/json", "5.2-preview.1")
};
return requestOptions;
}
export async function getCacheEntry(
keys: string[]
): Promise<ArtifactCacheEntry | null> {
@@ -61,16 +34,25 @@ export async function getCacheEntry(
throw new Error(`Cache service responded with ${response.statusCode}`);
}
const cacheResult = response.result;
core.debug(`Cache Result:`);
core.debug(JSON.stringify(cacheResult));
if (!cacheResult || !cacheResult.archiveLocation) {
throw new Error("Cache not found.");
}
core.setSecret(cacheResult.archiveLocation);
core.debug(`Cache Result:`);
core.debug(JSON.stringify(cacheResult));
return cacheResult;
}
export async function downloadCache(
cacheEntry: ArtifactCacheEntry,
archivePath: string
): Promise<void> {
const stream = fs.createWriteStream(archivePath);
const httpClient = new HttpClient("actions/cache");
const downloadResponse = await httpClient.get(cacheEntry.archiveLocation!);
await pipeResponseToStream(downloadResponse, stream);
}
async function pipeResponseToStream(
response: IHttpClientResponse,
stream: NodeJS.WritableStream
@@ -82,23 +64,7 @@ async function pipeResponseToStream(
});
}
export async function downloadCache(
cacheEntry: ArtifactCacheEntry,
archivePath: string
): Promise<void> {
const stream = fs.createWriteStream(archivePath);
const httpClient = new HttpClient("actions/cache");
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const downloadResponse = await httpClient.get(cacheEntry.archiveLocation!);
await pipeResponseToStream(downloadResponse, stream);
}
export async function saveCache(
key: string,
archivePath: string
): Promise<void> {
const stream = fs.createReadStream(archivePath);
export async function saveCache(stream: NodeJS.ReadableStream, key: string) {
const cacheUrl = getCacheUrl();
const token = process.env["ACTIONS_RUNTIME_TOKEN"] || "";
const bearerCredentialHandler = new BearerCredentialHandler(token);
@@ -127,3 +93,32 @@ export async function saveCache(
core.info("Cache saved successfully");
}
function getRequestOptions(): IRequestOptions {
const requestOptions: IRequestOptions = {
acceptHeader: createAcceptHeader("application/json", "5.2-preview.1")
};
return requestOptions;
}
function createAcceptHeader(type: string, apiVersion: string): string {
return `${type};api-version=${apiVersion}`;
}
function getCacheUrl(): string {
// Ideally we just use ACTIONS_CACHE_URL
let cacheUrl: string = (
process.env["ACTIONS_CACHE_URL"] ||
process.env["ACTIONS_RUNTIME_URL"] ||
""
).replace("pipelines", "artifactcache");
if (!cacheUrl) {
throw new Error(
"Cache Service Url not found, unable to restore cache."
);
}
core.debug(`Cache Url: ${cacheUrl}`);
return cacheUrl;
}
+9 -15
View File
@@ -1,20 +1,14 @@
export enum Inputs {
Key = "key",
Path = "path",
RestoreKeys = "restore-keys"
export namespace Inputs {
export const Key = "key";
export const Path = "path";
export const RestoreKeys = "restore-keys";
}
export enum Outputs {
CacheHit = "cache-hit"
export namespace Outputs {
export const CacheHit = "cache-hit";
}
export enum State {
CacheKey = "CACHE_KEY",
CacheResult = "CACHE_RESULT"
}
export enum Events {
Key = "GITHUB_EVENT_NAME",
Push = "push",
PullRequest = "pull_request"
export namespace State {
export const CacheKey = "CACHE_KEY";
export const CacheResult = "CACHE_RESULT";
}
+30 -24
View File
@@ -1,25 +1,18 @@
import * as core from "@actions/core";
import { exec } from "@actions/exec";
import * as io from "@actions/io";
import * as fs from "fs";
import * as path from "path";
import * as cacheHttpClient from "./cacheHttpClient";
import { Events, Inputs, State } from "./constants";
import { extractTar } from "./tar";
import { Inputs, State } from "./constants";
import * as utils from "./utils/actionUtils";
async function run(): Promise<void> {
async function run() {
try {
// Validate inputs, this can cause task failure
if (!utils.isValidEvent()) {
utils.logWarning(
`Event Validation Error: The event type ${
process.env[Events.Key]
} is not supported. Only ${utils
.getSupportedEvents()
.join(", ")} events are supported at this time.`
);
return;
}
const cachePath = utils.resolvePath(
let cachePath = utils.resolvePath(
core.getInput(Inputs.Path, { required: true })
);
core.debug(`Cache Path: ${cachePath}`);
@@ -67,7 +60,7 @@ async function run(): Promise<void> {
return;
}
const archivePath = path.join(
let archivePath = path.join(
await utils.createTempDirectory(),
"cache.tgz"
);
@@ -79,14 +72,27 @@ async function run(): Promise<void> {
// Download the cache from the cache entry
await cacheHttpClient.downloadCache(cacheEntry, archivePath);
const archiveFileSize = utils.getArchiveFileSize(archivePath);
core.info(
`Cache Size: ~${Math.round(
archiveFileSize / (1024 * 1024)
)} MB (${archiveFileSize} B)`
);
io.mkdirP(cachePath);
await extractTar(archivePath, cachePath);
// http://man7.org/linux/man-pages/man1/tar.1.html
// tar [-options] <name of the tar archive> [files or directories which to add into archive]
const args = ["-xz"];
const IS_WINDOWS = process.platform === "win32";
if (IS_WINDOWS) {
args.push("--force-local");
archivePath = archivePath.replace(/\\/g, "/");
cachePath = cachePath.replace(/\\/g, "/");
}
args.push(...["-f", archivePath, "-C", cachePath]);
const tarPath = await io.which("tar", true);
core.debug(`Tar Path: ${tarPath}`);
const archiveFileSize = fs.statSync(archivePath).size;
core.debug(`File Size: ${archiveFileSize}`);
await exec(`"${tarPath}"`, args);
const isExactKeyMatch = utils.isExactKeyMatch(
primaryKey,
@@ -98,7 +104,7 @@ async function run(): Promise<void> {
`Cache restored from key: ${cacheEntry && cacheEntry.cacheKey}`
);
} catch (error) {
utils.logWarning(error.message);
core.warning(error.message);
utils.setCacheHitOutput(false);
}
} catch (error) {
+31 -25
View File
@@ -1,29 +1,22 @@
import * as core from "@actions/core";
import { exec } from "@actions/exec";
import * as io from "@actions/io";
import * as fs from "fs";
import * as path from "path";
import * as cacheHttpClient from "./cacheHttpClient";
import { Events, Inputs, State } from "./constants";
import { createTar } from "./tar";
import { Inputs, State } from "./constants";
import * as utils from "./utils/actionUtils";
async function run(): Promise<void> {
async function run() {
try {
if (!utils.isValidEvent()) {
utils.logWarning(
`Event Validation Error: The event type ${
process.env[Events.Key]
} is not supported. Only ${utils
.getSupportedEvents()
.join(", ")} events are supported at this time.`
);
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.CacheKey);
if (!primaryKey) {
utils.logWarning(`Error retrieving key from state.`);
core.warning(`Error retrieving key from state.`);
return;
}
@@ -34,34 +27,47 @@ async function run(): Promise<void> {
return;
}
const cachePath = utils.resolvePath(
let cachePath = utils.resolvePath(
core.getInput(Inputs.Path, { required: true })
);
core.debug(`Cache Path: ${cachePath}`);
const archivePath = path.join(
let archivePath = path.join(
await utils.createTempDirectory(),
"cache.tgz"
);
core.debug(`Archive Path: ${archivePath}`);
await createTar(archivePath, cachePath);
// http://man7.org/linux/man-pages/man1/tar.1.html
// tar [-options] <name of the tar archive> [files or directories which to add into archive]
const args = ["-cz"];
const IS_WINDOWS = process.platform === "win32";
if (IS_WINDOWS) {
args.push("--force-local");
archivePath = archivePath.replace(/\\/g, "/");
cachePath = cachePath.replace(/\\/g, "/");
}
args.push(...["-f", archivePath, "-C", cachePath, "."]);
const tarPath = await io.which("tar", true);
core.debug(`Tar Path: ${tarPath}`);
await exec(`"${tarPath}"`, args);
const fileSizeLimit = 400 * 1024 * 1024; // 400MB
const archiveFileSize = utils.getArchiveFileSize(archivePath);
const archiveFileSize = fs.statSync(archivePath).size;
core.debug(`File Size: ${archiveFileSize}`);
if (archiveFileSize > fileSizeLimit) {
utils.logWarning(
`Cache size of ~${Math.round(
archiveFileSize / (1024 * 1024)
)} MB (${archiveFileSize} B) is over the 400MB limit, not saving cache.`
core.warning(
`Cache size of ${archiveFileSize} bytes is over the 400MB limit, not saving cache.`
);
return;
}
await cacheHttpClient.saveCache(primaryKey, archivePath);
const stream = fs.createReadStream(archivePath);
await cacheHttpClient.saveCache(stream, primaryKey);
} catch (error) {
utils.logWarning(error.message);
core.warning(error.message);
}
}
-49
View File
@@ -1,49 +0,0 @@
import { exec } from "@actions/exec";
import * as io from "@actions/io";
import { existsSync } from "fs";
async function getTarPath(): Promise<string> {
// Explicitly use BSD Tar on Windows
const IS_WINDOWS = process.platform === "win32";
if (IS_WINDOWS) {
const systemTar = `${process.env["windir"]}\\System32\\tar.exe`;
if (existsSync(systemTar)) {
return systemTar;
}
}
return await io.which("tar", true);
}
async function execTar(args: string[]): Promise<void> {
try {
const tarPath = await getTarPath();
const tarExec = process.platform !== "win32" ? `sudo ${tarPath}` : tarPath;
await exec(`"${tarExec}"`, args);
} catch (error) {
const IS_WINDOWS = process.platform === "win32";
if (IS_WINDOWS) {
throw new Error(
`Tar failed with error: ${error?.message}. Ensure BSD tar is installed and on the PATH.`
);
}
throw new Error(`Tar failed with error: ${error?.message}`);
}
}
export async function extractTar(
archivePath: string,
targetDirectory: string
): Promise<void> {
// Create directory to extract tar into
await io.mkdirP(targetDirectory);
const args = ["-xz", "-f", archivePath, "-C", targetDirectory];
await execTar(args);
}
export async function createTar(
archivePath: string,
sourceDirectory: string
): Promise<void> {
const args = ["-cz", "-f", archivePath, "-C", sourceDirectory, "."];
await execTar(args);
}
+9 -35
View File
@@ -1,11 +1,10 @@
import * as core from "@actions/core";
import * as io from "@actions/io";
import * as fs from "fs";
import * as os from "os";
import * as path from "path";
import * as uuidV4 from "uuid/v4";
import { Events, Outputs, State } from "../constants";
import { Outputs, State } from "../constants";
import { ArtifactCacheEntry } from "../contracts";
// From https://github.com/actions/toolkit/blob/master/packages/tool-cache/src/tool-cache.ts#L23
@@ -33,10 +32,6 @@ export async function createTempDirectory(): Promise<string> {
return dest;
}
export function getArchiveFileSize(path: string): number {
return fs.statSync(path).size;
}
export function isExactKeyMatch(
key: string,
cacheResult?: ArtifactCacheEntry
@@ -50,18 +45,10 @@ export function isExactKeyMatch(
);
}
export function setCacheState(state: ArtifactCacheEntry): void {
core.saveState(State.CacheResult, JSON.stringify(state));
}
export function setCacheHitOutput(isCacheHit: boolean): void {
core.setOutput(Outputs.CacheHit, isCacheHit.toString());
}
export function setOutputAndState(
key: string,
cacheResult?: ArtifactCacheEntry
): void {
) {
setCacheHitOutput(isExactKeyMatch(key, cacheResult));
// Store the cache result if it exists
cacheResult && setCacheState(cacheResult);
@@ -70,16 +57,15 @@ export function setOutputAndState(
export function getCacheState(): ArtifactCacheEntry | undefined {
const stateData = core.getState(State.CacheResult);
core.debug(`State: ${stateData}`);
if (stateData) {
return JSON.parse(stateData) as ArtifactCacheEntry;
}
return undefined;
return (stateData && JSON.parse(stateData)) as ArtifactCacheEntry;
}
export function logWarning(message: string): void {
const warningPrefix = "[warning]";
core.info(`${warningPrefix}${message}`);
export function setCacheState(state: ArtifactCacheEntry) {
core.saveState(State.CacheResult, JSON.stringify(state));
}
export function setCacheHitOutput(isCacheHit: boolean) {
core.setOutput(Outputs.CacheHit, isCacheHit.toString());
}
export function resolvePath(filePath: string): string {
@@ -93,15 +79,3 @@ export function resolvePath(filePath: string): string {
return path.resolve(filePath);
}
export function getSupportedEvents(): string[] {
return [Events.Push, Events.PullRequest];
}
// Currently the cache token is only authorized for push and pull_request events
// All other events will fail when reading and saving the cache
// See GitHub Context https://help.github.com/actions/automating-your-workflow-with-github-actions/contexts-and-expression-syntax-for-github-actions#github-context
export function isValidEvent(): boolean {
const githubEvent = process.env[Events.Key] || "";
return getSupportedEvents().includes(githubEvent);
}
+1 -23
View File
@@ -1,29 +1,7 @@
import { Inputs } from "../constants";
// See: https://github.com/actions/toolkit/blob/master/packages/core/src/core.ts#L67
function getInputName(name: string): string {
return `INPUT_${name.replace(/ /g, "_").toUpperCase()}`;
}
export function setInput(name: string, value: string): void {
export function setInput(name: string, value: string) {
process.env[getInputName(name)] = value;
}
interface CacheInput {
path: string;
key: string;
restoreKeys?: string[];
}
export function setInputs(input: CacheInput): void {
setInput(Inputs.Path, input.path);
setInput(Inputs.Key, input.key);
input.restoreKeys &&
setInput(Inputs.RestoreKeys, input.restoreKeys.join("\n"));
}
export function clearInputs(): void {
delete process.env[getInputName(Inputs.Path)];
delete process.env[getInputName(Inputs.Key)];
delete process.env[getInputName(Inputs.RestoreKeys)];
}