diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 7bdca28..0000000 --- a/.eslintignore +++ /dev/null @@ -1,4 +0,0 @@ -/.yarn/** -/lib/** -/coverage/** -/node_modules/** diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 205b3e1..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "env": { - "node": true, - "es6": true, - "mocha": true, - "jest": true - }, - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended", - "plugin:import/errors", - "plugin:import/typescript", // this is needed to allow importing typescript files from JS - "plugin:import/warnings", - "plugin:jest/recommended", - "plugin:prettier/recommended" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": 2023, - "sourceType": "module" - }, - "plugins": [ - "@typescript-eslint", - "jest", - "prettier" - ], - "rules": { - "import/no-unresolved": [ - "error", { - "ignore": ["csv-parse/sync", "@octokit/openapi-types"] - } - ], - "jest/no-disabled-tests": 0 - } -} diff --git a/__tests__/buildx/builder.test.ts b/__tests__/buildx/builder.test.ts index b888505..2b5c7a7 100644 --- a/__tests__/buildx/builder.test.ts +++ b/__tests__/buildx/builder.test.ts @@ -49,7 +49,6 @@ describe('exists', () => { const execSpy = jest.spyOn(Exec, 'getExecOutput'); const builder = new Builder(); await builder.exists('foo'); - // eslint-disable-next-line jest/no-standalone-expect expect(execSpy).toHaveBeenCalledWith(`docker`, ['buildx', 'inspect', 'foo'], { silent: true, ignoreReturnCode: true diff --git a/__tests__/buildx/buildx.test.ts b/__tests__/buildx/buildx.test.ts index 3fa41a4..8d538c1 100644 --- a/__tests__/buildx/buildx.test.ts +++ b/__tests__/buildx/buildx.test.ts @@ -91,7 +91,6 @@ describe('isAvailable', () => { standalone: false }); await buildx.isAvailable(); - // eslint-disable-next-line jest/no-standalone-expect expect(execSpy).toHaveBeenCalledWith(`docker`, ['buildx'], { silent: true, ignoreReturnCode: true @@ -103,7 +102,6 @@ describe('isAvailable', () => { standalone: true }); await buildx.isAvailable(); - // eslint-disable-next-line jest/no-standalone-expect expect(execSpy).toHaveBeenCalledWith(`buildx`, [], { silent: true, ignoreReturnCode: true diff --git a/__tests__/buildx/install.test.ts b/__tests__/buildx/install.test.ts index 2043026..9defe18 100644 --- a/__tests__/buildx/install.test.ts +++ b/__tests__/buildx/install.test.ts @@ -94,7 +94,6 @@ describe('download', () => { }); describe('build', () => { - // eslint-disable-next-line jest/no-disabled-tests it.skip('builds refs/pull/648/head', async () => { const install = new Install(); const toolPath = await install.build('https://github.com/docker/buildx.git#refs/pull/648/head'); @@ -103,7 +102,6 @@ describe('build', () => { expect(fs.existsSync(buildxBin)).toBe(true); }, 100000); - // eslint-disable-next-line jest/no-disabled-tests it.skip('builds 67bd6f4dc82a9cd96f34133dab3f6f7af803bb14', async () => { const install = new Install(); const toolPath = await install.build('https://github.com/docker/buildx.git#67bd6f4dc82a9cd96f34133dab3f6f7af803bb14'); diff --git a/__tests__/compose/compose.test.ts b/__tests__/compose/compose.test.ts index e738ebf..a292ac2 100644 --- a/__tests__/compose/compose.test.ts +++ b/__tests__/compose/compose.test.ts @@ -49,7 +49,6 @@ describe('isAvailable', () => { standalone: false }); await compose.isAvailable(); - // eslint-disable-next-line jest/no-standalone-expect expect(execSpy).toHaveBeenCalledWith(`docker`, ['compose'], { silent: true, ignoreReturnCode: true @@ -61,7 +60,6 @@ describe('isAvailable', () => { standalone: true }); await compose.isAvailable(); - // eslint-disable-next-line jest/no-standalone-expect expect(execSpy).toHaveBeenCalledWith(`compose`, [], { silent: true, ignoreReturnCode: true diff --git a/__tests__/cosign/cosign.test.ts b/__tests__/cosign/cosign.test.ts index ec1e1e2..108abeb 100644 --- a/__tests__/cosign/cosign.test.ts +++ b/__tests__/cosign/cosign.test.ts @@ -29,7 +29,6 @@ describe('isAvailable', () => { const execSpy = jest.spyOn(Exec, 'getExecOutput'); const cosign = new Cosign(); await cosign.isAvailable(); - // eslint-disable-next-line jest/no-standalone-expect expect(execSpy).toHaveBeenCalledWith(`cosign`, [], { silent: true, ignoreReturnCode: true diff --git a/__tests__/git.test.ts b/__tests__/git.test.ts index 9b16184..70659bd 100644 --- a/__tests__/git.test.ts +++ b/__tests__/git.test.ts @@ -57,7 +57,7 @@ describe('isInsideWorkTree', () => { const execSpy = jest.spyOn(Exec, 'getExecOutput'); try { await Git.isInsideWorkTree(); - } catch (err) { + } catch { // noop } expect(execSpy).toHaveBeenCalledWith(`git`, ['rev-parse', '--is-inside-work-tree'], { @@ -81,7 +81,7 @@ describe('remoteURL', () => { const execSpy = jest.spyOn(Exec, 'getExecOutput'); try { await Git.remoteURL(); - } catch (err) { + } catch { // noop } expect(execSpy).toHaveBeenCalledWith(`git`, ['remote', 'get-url', 'origin'], { @@ -415,7 +415,7 @@ describe('fullCommit', () => { const execSpy = jest.spyOn(Exec, 'getExecOutput'); try { await Git.fullCommit(); - } catch (err) { + } catch { // noop } expect(execSpy).toHaveBeenCalledWith(`git`, ['show', '--format=%H', 'HEAD', '--quiet', '--'], { @@ -430,7 +430,7 @@ describe('shortCommit', () => { const execSpy = jest.spyOn(Exec, 'getExecOutput'); try { await Git.shortCommit(); - } catch (err) { + } catch { // noop } expect(execSpy).toHaveBeenCalledWith(`git`, ['show', '--format=%h', 'HEAD', '--quiet', '--'], { @@ -445,7 +445,7 @@ describe('tag', () => { const execSpy = jest.spyOn(Exec, 'getExecOutput'); try { await Git.tag(); - } catch (err) { + } catch { // noop } expect(execSpy).toHaveBeenCalledWith(`git`, ['tag', '--points-at', 'HEAD', '--sort', '-version:creatordate'], { diff --git a/__tests__/github.test.ts b/__tests__/github.test.ts index 7ec7748..93f9fd6 100644 --- a/__tests__/github.test.ts +++ b/__tests__/github.test.ts @@ -141,6 +141,7 @@ describe('actionsRuntimeToken', () => { it('malformed', async () => { process.env.ACTIONS_RUNTIME_TOKEN = 'foo'; expect(() => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions GitHub.actionsRuntimeToken; }).toThrow(); }); diff --git a/__tests__/regclient/regctl.test.ts b/__tests__/regclient/regctl.test.ts index c6604da..1dce5ad 100644 --- a/__tests__/regclient/regctl.test.ts +++ b/__tests__/regclient/regctl.test.ts @@ -85,7 +85,6 @@ describe('isAvailable', () => { const execSpy = jest.spyOn(Exec, 'getExecOutput'); const regctl = new Regctl(); await regctl.isAvailable(); - // eslint-disable-next-line jest/no-standalone-expect expect(execSpy).toHaveBeenCalledWith(`regctl`, [], { silent: true, ignoreReturnCode: true diff --git a/__tests__/testResultsProcessor.ts b/__tests__/testResultsProcessor.ts index ac53feb..60ef63e 100644 --- a/__tests__/testResultsProcessor.ts +++ b/__tests__/testResultsProcessor.ts @@ -14,8 +14,7 @@ * limitations under the License. */ -// eslint-disable-next-line @typescript-eslint/no-var-requires -const fs = require('fs'); +import fs = require('fs'); module.exports = results => { const allSkipped = results.testResults.every(result => { diff --git a/__tests__/undock/undock.test.ts b/__tests__/undock/undock.test.ts index 59e6b05..ce55316 100644 --- a/__tests__/undock/undock.test.ts +++ b/__tests__/undock/undock.test.ts @@ -46,7 +46,6 @@ describe('isAvailable', () => { const execSpy = jest.spyOn(Exec, 'getExecOutput'); const undock = new Undock(); await undock.isAvailable(); - // eslint-disable-next-line jest/no-standalone-expect expect(execSpy).toHaveBeenCalledWith(`undock`, [], { silent: true, ignoreReturnCode: true diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..dfaf93e --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,84 @@ +/** + * Copyright 2025 actions-toolkit authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* eslint-disable @typescript-eslint/no-require-imports */ +const {defineConfig, globalIgnores} = require('eslint/config'); +const {fixupConfigRules, fixupPluginRules} = require('@eslint/compat'); +const typescriptEslint = require('@typescript-eslint/eslint-plugin'); +const jestPlugin = require('eslint-plugin-jest'); +const prettier = require('eslint-plugin-prettier'); +const globals = require('globals'); +const tsParser = require('@typescript-eslint/parser'); +const js = require('@eslint/js'); +const {FlatCompat} = require('@eslint/eslintrc'); + +// __dirname and __filename exist natively in CommonJS +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all +}); + +module.exports = defineConfig([ + globalIgnores(['.yarn/**/*', 'lib/**/*', 'coverage/**/*', 'node_modules/**/*']), + { + extends: fixupConfigRules( + compat.extends( + 'eslint:recommended', + 'plugin:@typescript-eslint/eslint-recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:import/errors', + 'plugin:import/typescript', + 'plugin:import/warnings', + 'plugin:jest/recommended', + 'plugin:prettier/recommended' + ) + ), + + plugins: { + '@typescript-eslint': fixupPluginRules(typescriptEslint), + jest: fixupPluginRules(jestPlugin), + prettier: fixupPluginRules(prettier) + }, + + languageOptions: { + globals: { + ...globals.node, + ...globals.mocha, + ...globals.jest + }, + parser: tsParser, + ecmaVersion: 2023, + sourceType: 'commonjs' + }, + + rules: { + '@typescript-eslint/no-require-imports': [ + 'error', + { + allowAsImport: true + } + ], + 'import/no-unresolved': [ + 'error', + { + ignore: ['csv-parse/sync', '@octokit/openapi-types'] + } + ], + 'jest/no-disabled-tests': 0 + } + } +]); diff --git a/jest.config.ts b/jest.config.ts index fb873b5..bfb1da5 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -14,9 +14,9 @@ * limitations under the License. */ -import fs from 'fs'; -import os from 'os'; -import path from 'path'; +import fs = require('fs'); +import os = require('os'); +import path = require('path'); const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-actions-toolkit-')); diff --git a/package.json b/package.json index 5d36afa..3689f6c 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,9 @@ "tmp": "^0.2.5" }, "devDependencies": { + "@eslint/compat": "^2.0.0", + "@eslint/eslintrc": "^3.3.3", + "@eslint/js": "^9.39.2", "@sigstore/rekor-types": "^3.0.0", "@types/gunzip-maybe": "^1.4.3", "@types/he": "^1.2.3", diff --git a/src/buildkit/buildkit.ts b/src/buildkit/buildkit.ts index aa604be..ee90ab4 100644 --- a/src/buildkit/buildkit.ts +++ b/src/buildkit/buildkit.ts @@ -85,7 +85,7 @@ export class BuildKit { if (!bkversion) { try { bkversion = await this.getVersionWithinImage(node.name || ''); - } catch (e) { + } catch { core.debug(`BuildKit.versionSatisfies ${node.name}: can't get version`); return false; } diff --git a/src/buildx/build.ts b/src/buildx/build.ts index 65c8b33..cd385e8 100644 --- a/src/buildx/build.ts +++ b/src/buildx/build.ts @@ -169,7 +169,7 @@ export class Build { } try { return core.getBooleanInput(name) ? `builder-id=${GitHub.workflowRunURL(true)}` : 'false'; - } catch (err) { + } catch { // not a valid boolean, so we assume it's a string return Build.resolveProvenanceAttrs(input); } @@ -302,7 +302,7 @@ export class Build { // https://github.com/docker/buildx/blob/8abef5908705e49f7ba88ef8c957e1127b597a2a/util/buildflags/attests.go#L13-L21 const v = Util.parseBool(attr); res.push(`disabled=${!v}`); - } catch (err) { + } catch { res.push(attr); } } diff --git a/src/buildx/buildx.ts b/src/buildx/buildx.ts index db7ad17..ef5f41c 100644 --- a/src/buildx/buildx.ts +++ b/src/buildx/buildx.ts @@ -148,7 +148,7 @@ export class Buildx { let url: URL; try { url = new URL(endpoint); - } catch (e) { + } catch { return []; } if (url.protocol != 'tcp:') { @@ -280,7 +280,7 @@ export class Buildx { const fnGitURL = function (inp: string): GitURL | undefined { try { return Git.parseURL(inp); - } catch (e) { + } catch { // noop } }; diff --git a/src/docker/docker.ts b/src/docker/docker.ts index 517b0d8..7bb978e 100644 --- a/src/docker/docker.ts +++ b/src/docker/docker.ts @@ -60,7 +60,7 @@ export class Docker { silent: true }); return true; - } catch (e) { + } catch { return false; } } diff --git a/src/types/docker/docker.ts b/src/types/docker/docker.ts index efc3658..af9b6e9 100644 --- a/src/types/docker/docker.ts +++ b/src/types/docker/docker.ts @@ -69,7 +69,6 @@ export interface ContextInfo { Name: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any Metadata: any; - // eslint-disable-next-line @typescript-eslint/no-explicit-any Endpoints: Record; TLSMaterial: Record>; Storage: StorageInfo; diff --git a/src/util.ts b/src/util.ts index e082da7..d484a6d 100644 --- a/src/util.ts +++ b/src/util.ts @@ -82,7 +82,7 @@ export class Util { let url; try { url = new URL(urlStr); - } catch (e) { + } catch { return false; } return url.protocol === 'http:' || url.protocol === 'https:'; @@ -115,10 +115,10 @@ export class Util { }; } - public static isDirectory(p) { + public static isDirectory(p: string) { try { return fs.lstatSync(p).isDirectory(); - } catch (_) { + } catch { // noop } return false; diff --git a/yarn.lock b/yarn.lock index 611b6b9..678cddb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1177,6 +1177,9 @@ __metadata: "@actions/io": "npm:^2.0.0" "@actions/tool-cache": "npm:^2.0.2" "@azure/storage-blob": "npm:^12.29.1" + "@eslint/compat": "npm:^2.0.0" + "@eslint/eslintrc": "npm:^3.3.3" + "@eslint/js": "npm:^9.39.2" "@octokit/core": "npm:^5.2.2" "@octokit/plugin-rest-endpoint-methods": "npm:^10.4.1" "@sigstore/bundle": "npm:^4.0.0" @@ -1280,6 +1283,20 @@ __metadata: languageName: node linkType: hard +"@eslint/compat@npm:^2.0.0": + version: 2.0.0 + resolution: "@eslint/compat@npm:2.0.0" + dependencies: + "@eslint/core": "npm:^1.0.0" + peerDependencies: + eslint: ^8.40 || 9 + peerDependenciesMeta: + eslint: + optional: true + checksum: 10/b1f63053ac643d47ce44d354a65e095e2b59f6b6aee4d6ca08cfa3b0800fc784bbd6895494ba726479faf9591e8e2887dc13c7a776f0d9627f0fdbf7faa34fdb + languageName: node + linkType: hard + "@eslint/config-array@npm:^0.21.1": version: 0.21.1 resolution: "@eslint/config-array@npm:0.21.1" @@ -1309,7 +1326,16 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:^3.3.1": +"@eslint/core@npm:^1.0.0": + version: 1.0.0 + resolution: "@eslint/core@npm:1.0.0" + dependencies: + "@types/json-schema": "npm:^7.0.15" + checksum: 10/0e2fc001ec3a12a9d6cd5de8eaf6c9eb1deec892777fed04e59eae0f3073c69988451eda32623524db76adaa7075747a8de5aa39b91b9084c711db452194eae9 + languageName: node + linkType: hard + +"@eslint/eslintrc@npm:^3.3.1, @eslint/eslintrc@npm:^3.3.3": version: 3.3.3 resolution: "@eslint/eslintrc@npm:3.3.3" dependencies: @@ -1326,7 +1352,7 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:9.39.2": +"@eslint/js@npm:9.39.2, @eslint/js@npm:^9.39.2": version: 9.39.2 resolution: "@eslint/js@npm:9.39.2" checksum: 10/6b7f676746f3111b5d1b23715319212ab9297868a0fa9980d483c3da8965d5841673aada2d5653e85a3f7156edee0893a7ae7035211b4efdcb2848154bb947f2