Skip to content

Commit

Permalink
chore(deps-dev): bump megalinter docker tag to v7
Browse files Browse the repository at this point in the history
MegaLinter recently added support for arrays to `*_CLI_EXECUTABLE` in
v7.0.0. Leverage this feature to run the version of ESLint installed in
our project via Yarn in lieu of the version of ESLint in the MegaLinter
Docker image via npm. This avoids many complications that arise from
ESLint being unable to access Yarn dependencies and allows us to stop
running ESLint in project mode as a workaround. Reorder pre-commit hooks
so that Yarn hooks precede MegaLinter hooks since `yarn install` must
now be run before MegaLinter so that ESLint can run.

Disable newly added linter ts-standard since we use Prettier, which is
incompatible with StandardJS.

Apply new Prettier v3 formatting.

Configure newly added link checker Lychee to ignore email addresses to
prevent false positives on GitHub Actions, which contain "@" symbols.
Increase network request retry limit from the default of 3 to 4 to avoid
false positives.

| datasource | package                          | from    | to     |
| ---------- | -------------------------------- | ------- | ------ |
| docker     | oxsecurity/megalinter-javascript | v6.22.2 | v7.2.1 |
  • Loading branch information
renovate-bot authored and Kurt-von-Laven committed Aug 7, 2023
1 parent b238066 commit 1325c3f
Show file tree
Hide file tree
Showing 11 changed files with 63 additions and 58 deletions.
8 changes: 4 additions & 4 deletions .mega-linter.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
APPLY_FIXES: all
CLEAR_REPORT_FOLDER: true
DEFAULT_BRANCH: main
DISABLE_LINTERS:
- TYPESCRIPT_STANDARD # We use Prettier instead.
FAIL_IF_MISSING_LINTER_IN_FLAVOR: true
FILTER_REGEX_EXCLUDE: \.pnp\.(c|loader\.m)js|\.yarn|dist
FORMATTERS_DISABLE_ERRORS: false
PRINT_ALPACA: false
SHOW_ELAPSED_TIME: true
CREDENTIALS_SECRETLINT_ARGUMENTS: --secretlintignore .gitignore
JAVASCRIPT_DEFAULT_STYLE: prettier
# Work around https://github.com/oxsecurity/megalinter/issues/1572.
JAVASCRIPT_ES_CLI_LINT_MODE: project
JAVASCRIPT_ES_CLI_EXECUTABLE: [node, .yarn/releases/yarn-3.6.1.cjs, run, eslint]
JAVASCRIPT_ES_CONFIG_FILE: LINTER_DEFAULT
JSON_PRETTIER_FILE_EXTENSIONS:
- .json
Expand All @@ -22,6 +23,5 @@ SPELL_CSPELL_PRE_COMMANDS:
- command: npm install @cspell/dict-win32@2.0.1
continue_if_failed: false
TYPESCRIPT_DEFAULT_STYLE: prettier
# Work around https://github.com/oxsecurity/megalinter/issues/1572.
TYPESCRIPT_ES_CLI_LINT_MODE: project
TYPESCRIPT_ES_CLI_EXECUTABLE: [node, .yarn/releases/yarn-3.6.1.cjs, run, eslint]
TYPESCRIPT_ES_CONFIG_FILE: LINTER_DEFAULT
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ repos:
- id: poetry-lock
- id: poetry-install
- id: pre-commit-install
- id: megalinter-incremental
args: &megalinter-args [--flavor, javascript, --release, v6.22.2]
- id: megalinter-full
args: *megalinter-args
- id: yarn-install
- id: yarn-dedupe
- id: yarn-audit
- id: yarn-build
- id: yarn-test
- id: megalinter-incremental
args: &megalinter-args [--flavor, javascript, --release, v7.2.1]
- id: megalinter-full
args: *megalinter-args

## Markdown
- repo: https://github.com/frnmst/md-toc
Expand Down
3 changes: 3 additions & 0 deletions lychee.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
exclude_mail = true

max_retries = 4
6 changes: 3 additions & 3 deletions src/arbitraries/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ export const dockerImages = (): Arbitrary<string[]> =>
uniqueArray(
stringOf(
fullUnicode().filter((char: string): boolean => char !== "\n"),
{ minLength: 1 }
)
{ minLength: 1 },
),
);

export const platform = (): Arbitrary<NodeJS.Platform> =>
Expand All @@ -37,7 +37,7 @@ export const platform = (): Arbitrary<NodeJS.Platform> =>
*/
export const uniquePair = <T>(
arrArbA: Arbitrary<T[]>,
arrArbB: Arbitrary<T[]>
arrArbB: Arbitrary<T[]>,
): Arbitrary<[T[], T[]]> =>
tuple(arrArbA, arrArbB).map(([arrayA, arrayB]: [T[], T[]]): [T[], T[]] => {
const setA = new Set(arrayA);
Expand Down
46 changes: 24 additions & 22 deletions src/docker.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jest.mock("@actions/core");

jest.unstable_mockModule(
"./util.js",
(): Util => ({ execBashCommand: jest.fn<typeof execBashCommand>() })
(): Util => ({ execBashCommand: jest.fn<typeof execBashCommand>() }),
);

const cache = jest.mocked(await import("@actions/cache"));
Expand All @@ -40,11 +40,11 @@ const assertCalledInOrder = <T extends FunctionLike>(
currentMock.mock.invocationCallOrder[callCount] ??
fail(`Mock function ${index} was called too few times: ${callCount}.`)
);
}
},
);

const sortedCallOrders = [...callOrders].sort(
(a: number, b: number): number => a - b
(a: number, b: number): number => a - b,
);
expect(callOrders).toStrictEqual(sortedCallOrders);
};
Expand All @@ -56,16 +56,16 @@ describe("Docker images", (): void => {
expect(core.saveState).nthCalledWith<[string, boolean]>(
1,
docker.CACHE_HIT,
cacheHit
cacheHit,
);
expect(core.setOutput).lastCalledWith(docker.CACHE_HIT, cacheHit);
if (cacheHit) {
expect(util.execBashCommand).lastCalledWith(
`docker load --input ${docker.DOCKER_IMAGES_PATH}`
`docker load --input ${docker.DOCKER_IMAGES_PATH}`,
);
} else {
expect(util.execBashCommand).lastCalledWith(
'docker image list --format "{{ .Repository }}:{{ .Tag }}"'
'docker image list --format "{{ .Repository }}:{{ .Tag }}"',
);
}
expect(util.execBashCommand).toHaveBeenCalledTimes(1);
Expand All @@ -74,7 +74,7 @@ describe("Docker images", (): void => {
const mockedLoadDockerImages = async (
key: string,
cacheHit: boolean,
images = ""
images = "",
): Promise<void> => {
core.getInput.mockReturnValue(key);
cache.restoreCache.mockResolvedValueOnce(cacheHit ? key : undefined);
Expand All @@ -86,7 +86,7 @@ describe("Docker images", (): void => {

const assertSaveDockerImages = (
cacheHit: boolean,
readOnly = false
readOnly = false,
): void => {
expect(core.getInput).nthCalledWith<[string, InputOptions]>(1, "key", {
required: true,
Expand All @@ -99,7 +99,7 @@ describe("Docker images", (): void => {
expect(core.info).nthCalledWith<[string]>(1, "Listing Docker images.");
expect(util.execBashCommand).nthCalledWith<[string]>(
1,
'docker image list --format "{{ .Repository }}:{{ .Tag }}"'
'docker image list --format "{{ .Repository }}:{{ .Tag }}"',
);
}
}
Expand All @@ -110,7 +110,7 @@ describe("Docker images", (): void => {
cacheHit: boolean,
readOnly: boolean,
preexistingImages: string[],
newImages: string[]
newImages: string[],
): Promise<void> => {
core.getInput.mockReturnValueOnce(key);
core.getState.mockReturnValueOnce(cacheHit.toString());
Expand All @@ -134,15 +134,15 @@ describe("Docker images", (): void => {

const assertSaveCacheHit = (key: string): void => {
expect(core.info).lastCalledWith(
`Cache hit occurred on the primary key ${key}, not saving cache.`
`Cache hit occurred on the primary key ${key}, not saving cache.`,
);
assertCacheNotSaved();
};

const assertSaveReadOnly = (key: string): void => {
expect(core.info).lastCalledWith(
`Cache miss occurred on the primary key ${key}. ` +
"Not saving cache as read-only option was selected."
"Not saving cache as read-only option was selected.",
);
assertCacheNotSaved();
};
Expand All @@ -156,10 +156,12 @@ describe("Docker images", (): void => {
const assertSaveCacheMiss = (key: string, newImages: string[]): void => {
expect(core.info).lastCalledWith(
"Images present before restore step will be skipped; only new images " +
"will be saved."
"will be saved.",
);
expect(util.execBashCommand).lastCalledWith(
`docker save --output ${docker.DOCKER_IMAGES_PATH} ${newImages.join(" ")}`
`docker save --output ${docker.DOCKER_IMAGES_PATH} ${newImages.join(
" ",
)}`,
);
expect(cache.saveCache).lastCalledWith([docker.DOCKER_IMAGES_PATH], key);

Expand All @@ -174,7 +176,7 @@ describe("Docker images", (): void => {
core.getState,
util.execBashCommand,
util.execBashCommand,
cache.saveCache
cache.saveCache,
);
};

Expand Down Expand Up @@ -207,9 +209,9 @@ describe("Docker images", (): void => {
assertCalledInOrder<FunctionLike>(
core.getInput,
cache.restoreCache,
util.execBashCommand
util.execBashCommand,
);
}
},
);

testProp(
Expand All @@ -221,10 +223,10 @@ describe("Docker images", (): void => {

expect(core.info).lastCalledWith(
"Recording preexisting Docker images. These include standard images " +
"pre-cached by GitHub Actions when Docker is run as root."
"pre-cached by GitHub Actions when Docker is run as root.",
);
expect(core.saveState).lastCalledWith(docker.DOCKER_IMAGES_LIST, images);
}
},
);

testProp(
Expand All @@ -239,15 +241,15 @@ describe("Docker images", (): void => {
key: string,
cacheHit: boolean,
readOnly: boolean,
[preexistingImages, newImages]: [string[], string[]]
[preexistingImages, newImages]: [string[], string[]],
): Promise<void> => {
jest.clearAllMocks();
await mockedSaveDockerImages(
key,
cacheHit,
readOnly,
preexistingImages,
newImages
newImages,
);

if (cacheHit) {
Expand All @@ -267,6 +269,6 @@ describe("Docker images", (): void => {
["my-key", false, true, [["preexisting-image"], ["new-image"]]],
["my-key", true, false, [["preexisting-image"], ["new-image"]]],
],
}
},
);
});
8 changes: 4 additions & 4 deletions src/docker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const loadDockerImages = async (): Promise<void> => {
} else {
info(
"Recording preexisting Docker images. These include standard images " +
"pre-cached by GitHub Actions when Docker is run as root."
"pre-cached by GitHub Actions when Docker is run as root.",
);
const dockerImages = await execBashCommand(LIST_COMMAND);
saveState(DOCKER_IMAGES_LIST, dockerImages);
Expand All @@ -34,22 +34,22 @@ const saveDockerImages = async (): Promise<void> => {
} else if (getInput("read-only") === "true") {
info(
`Cache miss occurred on the primary key ${key}. Not saving cache as ` +
"read-only option was selected."
"read-only option was selected.",
);
} else {
const preexistingImages = getState(DOCKER_IMAGES_LIST).split("\n");
info("Listing Docker images.");
const images = await execBashCommand(LIST_COMMAND);
const imagesList = images.split("\n");
const newImages = imagesList.filter(
(image: string): boolean => !preexistingImages.includes(image)
(image: string): boolean => !preexistingImages.includes(image),
);
if (newImages.length === 0) {
info("No Docker images to save");
} else {
info(
"Images present before restore step will be skipped; only new images " +
"will be saved."
"will be saved.",
);
const newImagesArgs = newImages.join(" ");
const cmd = `docker save --output ${DOCKER_IMAGES_PATH} ${newImagesArgs}`;
Expand Down
24 changes: 12 additions & 12 deletions src/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ describe("Integration Test", (): void => {
const key = getKey(paths, primaryKey);
inMemoryCache.set(key, primaryKey);
return Promise.resolve(0);
}
},
);

cache.restoreCache.mockImplementation(
(paths: string[], primaryKey: string): Promise<string | undefined> => {
const key = getKey(paths, primaryKey);
return Promise.resolve(inMemoryCache.get(key));
}
},
);

core.getState.mockImplementation((key: string): string => {
Expand Down Expand Up @@ -100,14 +100,14 @@ describe("Integration Test", (): void => {
infoCallNum: number,
execCallNum: number,
command: string,
output: ConsoleOutput
output: ConsoleOutput,
): void => {
expect(core.info).nthCalledWith<[string]>(infoCallNum, command);
expect(nodeUtil.promisify).nthCalledWith<[typeof exec]>(execCallNum, exec);
expect(execMock).nthCalledWith<[string, ExecOptions]>(
execCallNum,
command,
EXEC_OPTIONS
EXEC_OPTIONS,
);
expect(core.info).nthCalledWith<[string]>(infoCallNum + 1, output.stdout);
expect(core.error).nthCalledWith<[string]>(execCallNum, output.stderr);
Expand All @@ -117,7 +117,7 @@ describe("Integration Test", (): void => {
const assertLoadDockerImages = (
cacheHit: boolean,
listStderr: string,
loadOutput: ConsoleOutput
loadOutput: ConsoleOutput,
): void => {
expect(core.getInput).nthCalledWith<[string, InputOptions]>(1, "key", {
required: true,
Expand All @@ -130,7 +130,7 @@ describe("Integration Test", (): void => {
expect(core.info).nthCalledWith<[string]>(
1,
"Recording preexisting Docker images. These include standard images " +
"pre-cached by GitHub Actions when Docker is run as root."
"pre-cached by GitHub Actions when Docker is run as root.",
);
const listOutput = joinOutput(dockerImages, listStderr);
assertExecBashCommand(2, 1, LIST_COMMAND, listOutput);
Expand All @@ -140,7 +140,7 @@ describe("Integration Test", (): void => {

const assertSaveCacheHit = (key: string): void => {
expect(core.info).lastCalledWith(
`Cache hit occurred on the primary key ${key}, not saving cache.`
`Cache hit occurred on the primary key ${key}, not saving cache.`,
);
expect(execMock).not.toHaveBeenCalled();
expect(core.setFailed).not.toHaveBeenCalled();
Expand All @@ -149,7 +149,7 @@ describe("Integration Test", (): void => {

const assertSaveCacheMiss = (
listStderr: string,
saveOutput: ConsoleOutput
saveOutput: ConsoleOutput,
): void => {
expect(core.getInput).lastCalledWith("read-only");
expect(core.info).nthCalledWith<[string]>(1, "Listing Docker images.");
Expand All @@ -158,7 +158,7 @@ describe("Integration Test", (): void => {
expect(core.info).nthCalledWith<[string]>(
4,
"Images present before restore step will be skipped; only new images " +
"will be saved."
"will be saved.",
);
const saveCommand = `docker save --output ${docker.DOCKER_IMAGES_PATH} test-docker-image:v2`;
assertExecBashCommand(5, 2, saveCommand, saveOutput);
Expand All @@ -168,7 +168,7 @@ describe("Integration Test", (): void => {
cacheHit: boolean,
key: string,
listStderr: string,
saveOutput: ConsoleOutput
saveOutput: ConsoleOutput,
): void => {
expect(core.getInput).nthCalledWith<[string, InputOptions]>(1, "key", {
required: true,
Expand All @@ -184,7 +184,7 @@ describe("Integration Test", (): void => {
async (
key: string,
listStderr: string,
otherOutput: ConsoleOutput
otherOutput: ConsoleOutput,
): Promise<void> => {
jest.clearAllMocks();
inMemoryCache = new Map<string, string>();
Expand Down Expand Up @@ -216,6 +216,6 @@ describe("Integration Test", (): void => {
await docker.saveDockerImages();
// Expect cache not to have been saved on cache hit.
assertSaveDockerImages(true, key, listStderr, otherOutput);
}
},
);
});
2 changes: 1 addition & 1 deletion src/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jest.unstable_mockModule(
"./docker.js",
(): Partial<Docker> => ({
loadDockerImages: jest.fn<typeof loadDockerImages>(),
})
}),
);

const docker = jest.mocked(await import("./docker.js"));
Expand Down
Loading

0 comments on commit 1325c3f

Please sign in to comment.