Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/actions/cache
Browse files Browse the repository at this point in the history
  • Loading branch information
pat-s committed May 26, 2020
2 parents f04f5a5 + b820478 commit be04252
Show file tree
Hide file tree
Showing 19 changed files with 7,672 additions and 8,541 deletions.
8 changes: 5 additions & 3 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ on:
pull_request:
branches:
- master
- releases/**
paths-ignore:
- '**.md'
push:
branches:
- master
- releases/**
paths-ignore:
- '**.md'

Expand All @@ -17,7 +19,7 @@ jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
os: [ubuntu-latest, ubuntu-16.04, windows-latest, macOS-latest]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
Expand Down Expand Up @@ -61,7 +63,7 @@ jobs:
test-save:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
os: [ubuntu-latest, ubuntu-16.04, windows-latest, macOS-latest]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
Expand All @@ -84,7 +86,7 @@ jobs:
needs: test-save
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
os: [ubuntu-latest, ubuntu-16.04, windows-latest, macOS-latest]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
Expand Down
247 changes: 28 additions & 219 deletions __tests__/actionUtils.test.ts
Original file line number Diff line number Diff line change
@@ -1,98 +1,65 @@
import * as core from "@actions/core";
import * as io from "@actions/io";
import { promises as fs } from "fs";
import * as os from "os";
import * as path from "path";

import { Events, Outputs, RefKey, State } from "../src/constants";
import { ArtifactCacheEntry } from "../src/contracts";
import * as actionUtils from "../src/utils/actionUtils";

import uuid = require("uuid");

jest.mock("@actions/core");
jest.mock("os");

function getTempDir(): string {
return path.join(__dirname, "_temp", "actionUtils");
}

afterEach(() => {
delete process.env[Events.Key];
delete process.env[RefKey];
});

afterAll(async () => {
delete process.env["GITHUB_WORKSPACE"];
await io.rmRF(getTempDir());
});

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", () => {
test("isExactKeyMatch with undefined cache key returns false", () => {
const key = "linux-rust";
const cacheEntry = undefined;
const cacheKey = undefined;

expect(actionUtils.isExactKeyMatch(key, cacheEntry)).toBe(false);
expect(actionUtils.isExactKeyMatch(key, cacheKey)).toBe(false);
});

test("isExactKeyMatch with empty cache entry returns false", () => {
test("isExactKeyMatch with empty cache key returns false", () => {
const key = "linux-rust";
const cacheEntry: ArtifactCacheEntry = {};
const cacheKey = "";

expect(actionUtils.isExactKeyMatch(key, cacheEntry)).toBe(false);
expect(actionUtils.isExactKeyMatch(key, cacheKey)).toBe(false);
});

test("isExactKeyMatch with different keys returns false", () => {
const key = "linux-rust";
const cacheEntry: ArtifactCacheEntry = {
cacheKey: "linux-"
};
const cacheKey = "linux-";

expect(actionUtils.isExactKeyMatch(key, cacheEntry)).toBe(false);
expect(actionUtils.isExactKeyMatch(key, cacheKey)).toBe(false);
});

test("isExactKeyMatch with different key accents returns false", () => {
const key = "linux-áccent";
const cacheEntry: ArtifactCacheEntry = {
cacheKey: "linux-accent"
};
const cacheKey = "linux-accent";

expect(actionUtils.isExactKeyMatch(key, cacheEntry)).toBe(false);
expect(actionUtils.isExactKeyMatch(key, cacheKey)).toBe(false);
});

test("isExactKeyMatch with same key returns true", () => {
const key = "linux-rust";
const cacheEntry: ArtifactCacheEntry = {
cacheKey: "linux-rust"
};
const cacheKey = "linux-rust";

expect(actionUtils.isExactKeyMatch(key, cacheEntry)).toBe(true);
expect(actionUtils.isExactKeyMatch(key, cacheKey)).toBe(true);
});

test("isExactKeyMatch with same key and different casing returns true", () => {
const key = "linux-rust";
const cacheEntry: ArtifactCacheEntry = {
cacheKey: "LINUX-RUST"
};
const cacheKey = "LINUX-RUST";

expect(actionUtils.isExactKeyMatch(key, cacheEntry)).toBe(true);
expect(actionUtils.isExactKeyMatch(key, cacheKey)).toBe(true);
});

test("setOutputAndState with undefined entry to set cache-hit output", () => {
const key = "linux-rust";
const cacheEntry = undefined;
const cacheKey = undefined;

const setOutputMock = jest.spyOn(core, "setOutput");
const saveStateMock = jest.spyOn(core, "saveState");

actionUtils.setOutputAndState(key, cacheEntry);
actionUtils.setOutputAndState(key, cacheKey);

expect(setOutputMock).toHaveBeenCalledWith(Outputs.CacheHit, "false");
expect(setOutputMock).toHaveBeenCalledTimes(1);
Expand All @@ -102,43 +69,33 @@ test("setOutputAndState with undefined entry to set cache-hit output", () => {

test("setOutputAndState with exact match to set cache-hit output and state", () => {
const key = "linux-rust";
const cacheEntry: ArtifactCacheEntry = {
cacheKey: "linux-rust"
};
const cacheKey = "linux-rust";

const setOutputMock = jest.spyOn(core, "setOutput");
const saveStateMock = jest.spyOn(core, "saveState");

actionUtils.setOutputAndState(key, cacheEntry);
actionUtils.setOutputAndState(key, cacheKey);

expect(setOutputMock).toHaveBeenCalledWith(Outputs.CacheHit, "true");
expect(setOutputMock).toHaveBeenCalledTimes(1);

expect(saveStateMock).toHaveBeenCalledWith(
State.CacheResult,
JSON.stringify(cacheEntry)
);
expect(saveStateMock).toHaveBeenCalledWith(State.CacheMatchedKey, cacheKey);
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 cacheKey = "linux-rust-bb828da54c148048dd17899ba9fda624811cfb43";

const setOutputMock = jest.spyOn(core, "setOutput");
const saveStateMock = jest.spyOn(core, "saveState");

actionUtils.setOutputAndState(key, cacheEntry);
actionUtils.setOutputAndState(key, cacheKey);

expect(setOutputMock).toHaveBeenCalledWith(Outputs.CacheHit, "false");
expect(setOutputMock).toHaveBeenCalledTimes(1);

expect(saveStateMock).toHaveBeenCalledWith(
State.CacheResult,
JSON.stringify(cacheEntry)
);
expect(saveStateMock).toHaveBeenCalledWith(State.CacheMatchedKey, cacheKey);
expect(saveStateMock).toHaveBeenCalledTimes(1);
});

Expand All @@ -152,27 +109,23 @@ test("getCacheState with no state returns undefined", () => {

expect(state).toBe(undefined);

expect(getStateMock).toHaveBeenCalledWith(State.CacheResult);
expect(getStateMock).toHaveBeenCalledWith(State.CacheMatchedKey);
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 cacheKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";

const getStateMock = jest.spyOn(core, "getState");
getStateMock.mockImplementation(() => {
return JSON.stringify(cacheEntry);
return cacheKey;
});

const state = actionUtils.getCacheState();

expect(state).toEqual(cacheEntry);
expect(state).toEqual(cacheKey);

expect(getStateMock).toHaveBeenCalledWith(State.CacheResult);
expect(getStateMock).toHaveBeenCalledWith(State.CacheMatchedKey);
expect(getStateMock).toHaveBeenCalledTimes(1);
});

Expand All @@ -195,137 +148,6 @@ test("isValidEvent returns false for event that does not have a branch or tag",
expect(isValidEvent).toBe(false);
});

test("resolvePaths with no ~ in path", async () => {
const filePath = ".cache";

// Create the following layout:
// cwd
// cwd/.cache
// cwd/.cache/file.txt

const root = path.join(getTempDir(), "no-tilde");
// tarball entries will be relative to workspace
process.env["GITHUB_WORKSPACE"] = root;

await fs.mkdir(root, { recursive: true });
const cache = path.join(root, ".cache");
await fs.mkdir(cache, { recursive: true });
await fs.writeFile(path.join(cache, "file.txt"), "cached");

const originalCwd = process.cwd();

try {
process.chdir(root);

const resolvedPath = await actionUtils.resolvePaths([filePath]);

const expectedPath = [filePath];
expect(resolvedPath).toStrictEqual(expectedPath);
} finally {
process.chdir(originalCwd);
}
});

test("resolvePaths with ~ in path", async () => {
const cacheDir = uuid();
const filePath = `~/${cacheDir}`;
// Create the following layout:
// ~/uuid
// ~/uuid/file.txt

const homedir = jest.requireActual("os").homedir();
const homedirMock = jest.spyOn(os, "homedir");
homedirMock.mockImplementation(() => {
return homedir;
});

const target = path.join(homedir, cacheDir);
await fs.mkdir(target, { recursive: true });
await fs.writeFile(path.join(target, "file.txt"), "cached");

const root = getTempDir();
process.env["GITHUB_WORKSPACE"] = root;

try {
const resolvedPath = await actionUtils.resolvePaths([filePath]);

const expectedPath = [path.relative(root, target)];
expect(resolvedPath).toStrictEqual(expectedPath);
} finally {
await io.rmRF(target);
}
});

test("resolvePaths with home not found", async () => {
const filePath = "~/.cache/yarn";
const homedirMock = jest.spyOn(os, "homedir");
homedirMock.mockImplementation(() => {
return "";
});

await expect(actionUtils.resolvePaths([filePath])).rejects.toThrow(
"Unable to determine HOME directory"
);
});

test("resolvePaths inclusion pattern returns found", async () => {
const pattern = "*.ts";
// Create the following layout:
// inclusion-patterns
// inclusion-patterns/miss.txt
// inclusion-patterns/test.ts

const root = path.join(getTempDir(), "inclusion-patterns");
// tarball entries will be relative to workspace
process.env["GITHUB_WORKSPACE"] = root;

await fs.mkdir(root, { recursive: true });
await fs.writeFile(path.join(root, "miss.txt"), "no match");
await fs.writeFile(path.join(root, "test.ts"), "match");

const originalCwd = process.cwd();

try {
process.chdir(root);

const resolvedPath = await actionUtils.resolvePaths([pattern]);

const expectedPath = ["test.ts"];
expect(resolvedPath).toStrictEqual(expectedPath);
} finally {
process.chdir(originalCwd);
}
});

test("resolvePaths exclusion pattern returns not found", async () => {
const patterns = ["*.ts", "!test.ts"];
// Create the following layout:
// exclusion-patterns
// exclusion-patterns/miss.txt
// exclusion-patterns/test.ts

const root = path.join(getTempDir(), "exclusion-patterns");
// tarball entries will be relative to workspace
process.env["GITHUB_WORKSPACE"] = root;

await fs.mkdir(root, { recursive: true });
await fs.writeFile(path.join(root, "miss.txt"), "no match");
await fs.writeFile(path.join(root, "test.ts"), "no match");

const originalCwd = process.cwd();

try {
process.chdir(root);

const resolvedPath = await actionUtils.resolvePaths(patterns);

const expectedPath = [];
expect(resolvedPath).toStrictEqual(expectedPath);
} finally {
process.chdir(originalCwd);
}
});

test("isValidEvent returns true for event that has a ref", () => {
const event = Events.Push;
process.env[Events.Key] = event;
Expand All @@ -335,16 +157,3 @@ test("isValidEvent returns true for event that has a ref", () => {

expect(isValidEvent).toBe(true);
});

test("unlinkFile unlinks file", async () => {
const testDirectory = await fs.mkdtemp("unlinkFileTest");
const testFile = path.join(testDirectory, "test.txt");
await fs.writeFile(testFile, "hello world");

await actionUtils.unlinkFile(testFile);

// This should throw as testFile should not exist
await expect(fs.stat(testFile)).rejects.toThrow();

await fs.rmdir(testDirectory);
});
Loading

0 comments on commit be04252

Please sign in to comment.