mirror of
https://code.forgejo.org/actions/cache.git
synced 2025-04-16 16:01:22 +02:00
Use @actions/glob for pattern matching
This commit is contained in:
parent
1e233443e8
commit
db235cfc56
12 changed files with 4427 additions and 176 deletions
34
.github/workflows/cache.yml
vendored
Normal file
34
.github/workflows/cache.yml
vendored
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
name: Cache
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Build and unit test
|
||||||
|
build:
|
||||||
|
runs-on: self-hosted
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: '12.x'
|
||||||
|
- run: npm install
|
||||||
|
- run: npm run build
|
||||||
|
- name: Restore npm cache
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
~/Desktop/cache-me
|
||||||
|
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||||
|
- name: Prettier Format Check
|
||||||
|
run: npm run format-check
|
||||||
|
- name: ESLint Check
|
||||||
|
run: npm run lint
|
||||||
|
- name: Build & Test
|
||||||
|
run: npm run test
|
|
@ -1,4 +1,5 @@
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
|
import * as os from "os";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
|
|
||||||
import { Events, Outputs, State } from "../src/constants";
|
import { Events, Outputs, State } from "../src/constants";
|
||||||
|
@ -180,6 +181,42 @@ test("isValidEvent returns false for unknown event", () => {
|
||||||
expect(isValidEvent).toBe(false);
|
expect(isValidEvent).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("expandPaths with no ~ in path", () => {
|
||||||
|
const filePath = ".cache/yarn";
|
||||||
|
|
||||||
|
const resolvedPath = actionUtils.expandPaths([filePath]);
|
||||||
|
|
||||||
|
const expectedPath = [path.resolve(filePath)];
|
||||||
|
expect(resolvedPath).toStrictEqual(expectedPath);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("expandPaths 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.expandPaths([filePath]);
|
||||||
|
|
||||||
|
const expectedPath = [path.join(homedir, ".cache/yarn")];
|
||||||
|
expect(resolvedPath).toStrictEqual(expectedPath);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("expandPaths with home not found", () => {
|
||||||
|
const filePath = "~/.cache/yarn";
|
||||||
|
const homedirMock = jest.spyOn(os, "homedir");
|
||||||
|
homedirMock.mockImplementation(() => {
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(() => actionUtils.expandPaths([filePath])).toThrow(
|
||||||
|
"Unable to resolve `~` to HOME"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test("isValidEvent returns true for push event", () => {
|
test("isValidEvent returns true for push event", () => {
|
||||||
const event = Events.Push;
|
const event = Events.Push;
|
||||||
process.env[Events.Key] = event;
|
process.env[Events.Key] = event;
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
import * as path from "path";
|
|
||||||
import * as os from "os";
|
|
||||||
import * as pathUtils from "../src/utils/pathUtils";
|
|
||||||
|
|
||||||
jest.mock("@actions/core");
|
|
||||||
jest.mock("os");
|
|
||||||
|
|
||||||
test("expandPaths with no ~ in path", () => {
|
|
||||||
const filePath = ".cache/yarn";
|
|
||||||
|
|
||||||
const resolvedPath = pathUtils.expandPaths([filePath]);
|
|
||||||
|
|
||||||
const expectedPath = [path.resolve(filePath)];
|
|
||||||
expect(resolvedPath).toStrictEqual(expectedPath);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("expandPaths 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 = pathUtils.expandPaths([filePath]);
|
|
||||||
|
|
||||||
const expectedPath = [path.join(homedir, ".cache/yarn")];
|
|
||||||
expect(resolvedPath).toStrictEqual(expectedPath);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("expandPaths with home not found", () => {
|
|
||||||
const filePath = "~/.cache/yarn";
|
|
||||||
const homedirMock = jest.spyOn(os, "homedir");
|
|
||||||
homedirMock.mockImplementation(() => {
|
|
||||||
return "";
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(() => pathUtils.expandPaths([filePath])).toThrow(
|
|
||||||
"Unable to resolve `~` to HOME"
|
|
||||||
);
|
|
||||||
});
|
|
|
@ -7,18 +7,12 @@ import run from "../src/restore";
|
||||||
import * as tar from "../src/tar";
|
import * as tar from "../src/tar";
|
||||||
import * as actionUtils from "../src/utils/actionUtils";
|
import * as actionUtils from "../src/utils/actionUtils";
|
||||||
import * as testUtils from "../src/utils/testUtils";
|
import * as testUtils from "../src/utils/testUtils";
|
||||||
// import * as pathUtils from "../src/utils/pathUtils";
|
|
||||||
|
|
||||||
jest.mock("../src/cacheHttpClient");
|
jest.mock("../src/cacheHttpClient");
|
||||||
jest.mock("../src/tar");
|
jest.mock("../src/tar");
|
||||||
jest.mock("../src/utils/actionUtils");
|
jest.mock("../src/utils/actionUtils");
|
||||||
// jest.mock("../src/utils/pathUtils");
|
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
// jest.spyOn(pathUtils, "expandPaths").mockImplementation(filePaths => {
|
|
||||||
// return filePaths.map(x => path.resolve(x));
|
|
||||||
// });
|
|
||||||
|
|
||||||
jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
|
jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
|
||||||
(key, cacheResult) => {
|
(key, cacheResult) => {
|
||||||
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
||||||
|
|
|
@ -7,13 +7,11 @@ import run from "../src/save";
|
||||||
import * as tar from "../src/tar";
|
import * as tar from "../src/tar";
|
||||||
import * as actionUtils from "../src/utils/actionUtils";
|
import * as actionUtils from "../src/utils/actionUtils";
|
||||||
import * as testUtils from "../src/utils/testUtils";
|
import * as testUtils from "../src/utils/testUtils";
|
||||||
import * as pathUtils from "../src/utils/pathUtils";
|
|
||||||
|
|
||||||
jest.mock("@actions/core");
|
jest.mock("@actions/core");
|
||||||
jest.mock("../src/cacheHttpClient");
|
jest.mock("../src/cacheHttpClient");
|
||||||
jest.mock("../src/tar");
|
jest.mock("../src/tar");
|
||||||
jest.mock("../src/utils/actionUtils");
|
jest.mock("../src/utils/actionUtils");
|
||||||
jest.mock("../src/utils/pathUtils");
|
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
jest.spyOn(core, "getInput").mockImplementation((name, options) => {
|
jest.spyOn(core, "getInput").mockImplementation((name, options) => {
|
||||||
|
@ -42,9 +40,11 @@ beforeAll(() => {
|
||||||
return actualUtils.getSupportedEvents();
|
return actualUtils.getSupportedEvents();
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.spyOn(pathUtils, "expandPaths").mockImplementation(filePaths => {
|
jest.spyOn(actionUtils, "expandPaths").mockImplementation(
|
||||||
|
async filePaths => {
|
||||||
return filePaths.map(x => path.resolve(x));
|
return filePaths.map(x => path.resolve(x));
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
jest.spyOn(actionUtils, "createTempDirectory").mockImplementation(() => {
|
jest.spyOn(actionUtils, "createTempDirectory").mockImplementation(() => {
|
||||||
return Promise.resolve("/foo/bar");
|
return Promise.resolve("/foo/bar");
|
||||||
|
|
2169
dist/restore/index.js
vendored
2169
dist/restore/index.js
vendored
File diff suppressed because it is too large
Load diff
2195
dist/save/index.js
vendored
2195
dist/save/index.js
vendored
File diff suppressed because it is too large
Load diff
15
package-lock.json
generated
15
package-lock.json
generated
|
@ -14,6 +14,15 @@
|
||||||
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.0.1.tgz",
|
||||||
"integrity": "sha512-nvFkxwiicvpzNiCBF4wFBDfnBvi7xp/as7LE1hBxBxKG2L29+gkIPBiLKMVORL+Hg3JNf07AKRfl0V5djoypjQ=="
|
"integrity": "sha512-nvFkxwiicvpzNiCBF4wFBDfnBvi7xp/as7LE1hBxBxKG2L29+gkIPBiLKMVORL+Hg3JNf07AKRfl0V5djoypjQ=="
|
||||||
},
|
},
|
||||||
|
"@actions/glob": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/glob/-/glob-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-lx8SzyQ2FE9+UUvjqY1f28QbTJv+w8qP7kHHbfQRhphrlcx0Mdmm1tZdGJzfxv1jxREa/sLW4Oy8CbGQKCJySA==",
|
||||||
|
"requires": {
|
||||||
|
"@actions/core": "^1.2.0",
|
||||||
|
"minimatch": "^3.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@actions/http-client": {
|
"@actions/http-client": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.6.tgz",
|
||||||
|
@ -537,12 +546,6 @@
|
||||||
"integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==",
|
"integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/minimatch": {
|
|
||||||
"version": "3.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
|
|
||||||
"integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"@types/nock": {
|
"@types/nock": {
|
||||||
"version": "11.1.0",
|
"version": "11.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/nock/-/nock-11.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/nock/-/nock-11.1.0.tgz",
|
||||||
|
|
|
@ -25,14 +25,13 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.2.0",
|
"@actions/core": "^1.2.0",
|
||||||
"@actions/exec": "^1.0.1",
|
"@actions/exec": "^1.0.1",
|
||||||
|
"@actions/glob": "^0.1.0",
|
||||||
"@actions/http-client": "^1.0.6",
|
"@actions/http-client": "^1.0.6",
|
||||||
"@actions/io": "^1.0.1",
|
"@actions/io": "^1.0.1",
|
||||||
"minimatch": "^3.0.4",
|
|
||||||
"uuid": "^3.3.3"
|
"uuid": "^3.3.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^24.0.13",
|
"@types/jest": "^24.0.13",
|
||||||
"@types/minimatch": "^3.0.3",
|
|
||||||
"@types/nock": "^11.1.0",
|
"@types/nock": "^11.1.0",
|
||||||
"@types/node": "^12.0.4",
|
"@types/node": "^12.0.4",
|
||||||
"@types/uuid": "^3.4.5",
|
"@types/uuid": "^3.4.5",
|
||||||
|
|
|
@ -4,7 +4,6 @@ import * as cacheHttpClient from "./cacheHttpClient";
|
||||||
import { Events, Inputs, State } from "./constants";
|
import { Events, Inputs, State } from "./constants";
|
||||||
import { createTar } from "./tar";
|
import { createTar } from "./tar";
|
||||||
import * as utils from "./utils/actionUtils";
|
import * as utils from "./utils/actionUtils";
|
||||||
import * as pathUtils from "./utils/pathUtils";
|
|
||||||
|
|
||||||
async function run(): Promise<void> {
|
async function run(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
|
@ -44,7 +43,7 @@ async function run(): Promise<void> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
core.debug(`Cache ID: ${cacheId}`);
|
core.debug(`Cache ID: ${cacheId}`);
|
||||||
const cachePaths = pathUtils.expandPaths(
|
const cachePaths = await utils.expandPaths(
|
||||||
core
|
core
|
||||||
.getInput(Inputs.Path)
|
.getInput(Inputs.Path)
|
||||||
.split("\n")
|
.split("\n")
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import * as io from "@actions/io";
|
import * as io from "@actions/io";
|
||||||
|
import * as glob from "@actions/glob";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import * as uuidV4 from "uuid/v4";
|
import * as uuidV4 from "uuid/v4";
|
||||||
|
@ -81,6 +82,19 @@ export function logWarning(message: string): void {
|
||||||
core.info(`${warningPrefix}${message}`);
|
core.info(`${warningPrefix}${message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function expandPaths(patterns: string[]): Promise<string[]> {
|
||||||
|
const paths: string[] = [];
|
||||||
|
const workspace = process.env["GITHUB_WORKSPACE"] ?? process.cwd();
|
||||||
|
|
||||||
|
const globber = await glob.create(patterns.join("\n"));
|
||||||
|
const files = await globber.glob();
|
||||||
|
|
||||||
|
paths.push(...files);
|
||||||
|
|
||||||
|
// Convert paths to relative paths here?
|
||||||
|
return paths.map(x => path.relative(workspace, x));
|
||||||
|
}
|
||||||
|
|
||||||
export function getSupportedEvents(): string[] {
|
export function getSupportedEvents(): string[] {
|
||||||
return [Events.Push, Events.PullRequest];
|
return [Events.Push, Events.PullRequest];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
import * as os from "os";
|
|
||||||
import * as path from "path";
|
|
||||||
import { readdirSync } from "fs";
|
|
||||||
import { IOptions, Minimatch } from "minimatch";
|
|
||||||
|
|
||||||
const globCharacters: string[] = ["*", "?", "[", "]"];
|
|
||||||
const options: IOptions = {
|
|
||||||
nocase: true,
|
|
||||||
dot: true,
|
|
||||||
nobrace: true
|
|
||||||
};
|
|
||||||
|
|
||||||
// export function resolvePath(filePath: string): string {
|
|
||||||
// if (filePath[0] === "~") {
|
|
||||||
// const home = os.homedir();
|
|
||||||
// if (!home) {
|
|
||||||
// throw new Error("Unable to resolve `~` to HOME");
|
|
||||||
// }
|
|
||||||
// return path.join(home, filePath.slice(1));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return path.resolve(filePath);
|
|
||||||
// }
|
|
||||||
|
|
||||||
export function isMinimatchPattern(pattern: string): boolean {
|
|
||||||
if (globCharacters.some(x => pattern.includes(x))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function matchDirectories(pattern: string, workspace: string): string[] {
|
|
||||||
const directories = readdirSync(workspace, { withFileTypes: true })
|
|
||||||
.filter(dirent => dirent.isDirectory())
|
|
||||||
.map(dirent => dirent.name);
|
|
||||||
|
|
||||||
const minimatch = new Minimatch(pattern, options);
|
|
||||||
const matches = directories.filter(x => minimatch.match(x));
|
|
||||||
|
|
||||||
return matches;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function expandPaths(filePaths: string[]): string[] {
|
|
||||||
const paths: string[] = [];
|
|
||||||
const workspace = process.env["GITHUB_WORKSPACE"] ?? process.cwd();
|
|
||||||
|
|
||||||
for (const filePath of filePaths) {
|
|
||||||
if (isMinimatchPattern(filePath)) {
|
|
||||||
paths.push(...matchDirectories(filePath, workspace));
|
|
||||||
} else if (filePath[0] === "~") {
|
|
||||||
const home = os.homedir();
|
|
||||||
if (!home) {
|
|
||||||
throw new Error("Unable to resolve `~` to HOME");
|
|
||||||
}
|
|
||||||
paths.push(path.join(home, filePath.slice(1)));
|
|
||||||
} else {
|
|
||||||
paths.push(path.resolve(filePath));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return paths;
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue