mirror of
https://github.com/actions/cache.git
synced 2025-04-19 02:26:45 +00:00
Cache multiple paths and add glob pattern support (#212)
* Allow for multiple line-delimited paths to cache * Add initial minimatch support * Use @actions/glob for pattern matching * Cache multiple entries using --files-from tar input remove known failing test Quote tar paths Add salt to test cache Try reading input files from manifest bump salt Run test on macos more testing Run caching tests on 3 platforms Run tests on self-hosted Apparently cant reference hosted runners by name Bump salt wait for some time after save more timing out smarter waiting Cache in tmp dir that won't be deleted Use child_process instead of actions/exec Revert tempDir hack bump salt more logging More console logging Use filepath to with cacheHttpClient Test cache restoration Revert temp dir hack debug logging clean up cache.yml testing Bump salt change debug output build actions * unit test coverage for caching multiple dirs * Ensure there's a locateable test folder at homedir * Clean up code * Version cache with all inputs * Unit test getCacheVersion * Include keys in getCacheEntry request * Clean import orders * Use fs promises in actionUtils tests * Update import order for to fix linter errors * Fix remaining linter error * Remove platform-specific test code * Add lerna example for caching multiple dirs * Lerna example updated to v2 Co-Authored-By: Josh Gross <joshmgross@github.com> Co-authored-by: Josh Gross <joshmgross@github.com>
This commit is contained in:
parent
22d71e33ad
commit
eb78578266
16 changed files with 4820 additions and 160 deletions
|
@ -1,5 +1,6 @@
|
|||
import * as core from "@actions/core";
|
||||
import * as fs from "fs";
|
||||
import * as io from "@actions/io";
|
||||
import { promises as fs } from "fs";
|
||||
import * as os from "os";
|
||||
import * as path from "path";
|
||||
|
||||
|
@ -7,13 +8,24 @@ import { Events, Outputs, 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];
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
delete process.env["GITHUB_WORKSPACE"];
|
||||
await io.rmRF(getTempDir());
|
||||
});
|
||||
|
||||
test("getArchiveFileSize returns file size", () => {
|
||||
const filePath = path.join(__dirname, "__fixtures__", "helloWorld.txt");
|
||||
|
||||
|
@ -182,17 +194,43 @@ test("isValidEvent returns false for unknown event", () => {
|
|||
expect(isValidEvent).toBe(false);
|
||||
});
|
||||
|
||||
test("resolvePath with no ~ in path", () => {
|
||||
const filePath = ".cache/yarn";
|
||||
test("resolvePaths with no ~ in path", async () => {
|
||||
const filePath = ".cache";
|
||||
|
||||
const resolvedPath = actionUtils.resolvePath(filePath);
|
||||
// Create the following layout:
|
||||
// cwd
|
||||
// cwd/.cache
|
||||
// cwd/.cache/file.txt
|
||||
|
||||
const expectedPath = path.resolve(filePath);
|
||||
expect(resolvedPath).toBe(expectedPath);
|
||||
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("resolvePath with ~ in path", () => {
|
||||
const filePath = "~/.cache/yarn";
|
||||
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");
|
||||
|
@ -200,24 +238,93 @@ test("resolvePath with ~ in path", () => {
|
|||
return homedir;
|
||||
});
|
||||
|
||||
const resolvedPath = actionUtils.resolvePath(filePath);
|
||||
const target = path.join(homedir, cacheDir);
|
||||
await fs.mkdir(target, { recursive: true });
|
||||
await fs.writeFile(path.join(target, "file.txt"), "cached");
|
||||
|
||||
const expectedPath = path.join(homedir, ".cache/yarn");
|
||||
expect(resolvedPath).toBe(expectedPath);
|
||||
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("resolvePath with home not found", () => {
|
||||
test("resolvePaths with home not found", async () => {
|
||||
const filePath = "~/.cache/yarn";
|
||||
const homedirMock = jest.spyOn(os, "homedir");
|
||||
homedirMock.mockImplementation(() => {
|
||||
return "";
|
||||
});
|
||||
|
||||
expect(() => actionUtils.resolvePath(filePath)).toThrow(
|
||||
"Unable to resolve `~` to HOME"
|
||||
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 push event", () => {
|
||||
const event = Events.Push;
|
||||
process.env[Events.Key] = event;
|
||||
|
@ -237,13 +344,14 @@ test("isValidEvent returns true for pull request event", () => {
|
|||
});
|
||||
|
||||
test("unlinkFile unlinks file", async () => {
|
||||
const testDirectory = fs.mkdtempSync("unlinkFileTest");
|
||||
const testDirectory = await fs.mkdtemp("unlinkFileTest");
|
||||
const testFile = path.join(testDirectory, "test.txt");
|
||||
fs.writeFileSync(testFile, "hello world");
|
||||
await fs.writeFile(testFile, "hello world");
|
||||
|
||||
await actionUtils.unlinkFile(testFile);
|
||||
|
||||
expect(fs.existsSync(testFile)).toBe(false);
|
||||
// This should throw as testFile should not exist
|
||||
await expect(fs.stat(testFile)).rejects.toThrow();
|
||||
|
||||
fs.rmdirSync(testDirectory);
|
||||
await fs.rmdir(testDirectory);
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue