From aaa42aa0628b4ae2578232a66b541047968fac86 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Tue, 30 Jul 2024 00:16:22 +0200 Subject: [PATCH] feat: allow to skip golangci-lint installation (#1079) --- README.md | 8 +- action.yml | 8 +- dist/post_run/index.js | 344 +++++++++++++++++++++++++++++++++++++++++ dist/run/index.js | 344 +++++++++++++++++++++++++++++++++++++++++ package-lock.json | 53 +++++-- package.json | 4 +- src/install.ts | 1 + src/run.ts | 10 ++ 8 files changed, 753 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index c90e85cdb3..cd71242b17 100644 --- a/README.md +++ b/README.md @@ -261,8 +261,10 @@ You will also likely need to add the following `.gitattributes` file to ensure t The version of golangci-lint to use. -* When `install-mode` is `binary` (default) the value can be v1.2 or v1.2.3 or `latest` to use the latest version. -* When `install-mode` is `goinstall` the value can be v1.2.3, `latest`, or the hash of a commit. +When `install-mode` is: +* `binary` (default): the value can be v1.2 or v1.2.3 or `latest` to use the latest version. +* `goinstall`: the value can be v1.2.3, `latest`, or the hash of a commit. +* `none`: the value is ignored.
Example @@ -280,7 +282,7 @@ with: (optional) -The mode to install golangci-lint: it can be `binary` or `goinstall`. +The mode to install golangci-lint: it can be `binary`, `goinstall`, or `none`. The default value is `binary`. diff --git a/action.yml b/action.yml index 6a5d1ed648..f4bdaaa181 100644 --- a/action.yml +++ b/action.yml @@ -6,11 +6,13 @@ inputs: version: description: | The version of golangci-lint to use. - When `install-mode` is `binary` (default) the value can be v1.2 or v1.2.3 or `latest` to use the latest version. - When `install-mode` is `goinstall` the value can be v1.2.3, `latest`, or the hash of a commit. + When `install-mode` is: + - `binary` (default): the value can be v1.2 or v1.2.3 or `latest` to use the latest version. + - `goinstall`: the value can be v1.2.3, `latest`, or the hash of a commit. + - `none`: the value is ignored. required: false install-mode: - description: "The mode to install golangci-lint. It can be 'binary' or 'goinstall'." + description: "The mode to install golangci-lint. It can be 'binary', 'goinstall', or 'none'." default: "binary" required: false working-directory: diff --git a/dist/post_run/index.js b/dist/post_run/index.js index bd7629eb1a..bdb2b3ece9 100644 --- a/dist/post_run/index.js +++ b/dist/post_run/index.js @@ -79831,6 +79831,124 @@ module.exports.implForWrapper = function (wrapper) { +/***/ }), + +/***/ 6143: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const { isexe, sync: isexeSync } = __nccwpck_require__(5200) +const { join, delimiter, sep, posix } = __nccwpck_require__(1017) + +const isWindows = process.platform === 'win32' + +// used to check for slashed in commands passed in. always checks for the posix +// seperator on all platforms, and checks for the current separator when not on +// a posix platform. don't use the isWindows check for this since that is mocked +// in tests but we still need the code to actually work when called. that is also +// why it is ignored from coverage. +/* istanbul ignore next */ +const rSlash = new RegExp(`[${posix.sep}${sep === posix.sep ? '' : sep}]`.replace(/(\\)/g, '\\$1')) +const rRel = new RegExp(`^\\.${rSlash.source}`) + +const getNotFoundError = (cmd) => + Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' }) + +const getPathInfo = (cmd, { + path: optPath = process.env.PATH, + pathExt: optPathExt = process.env.PATHEXT, + delimiter: optDelimiter = delimiter, +}) => { + // If it has a slash, then we don't bother searching the pathenv. + // just check the file itself, and that's it. + const pathEnv = cmd.match(rSlash) ? [''] : [ + // windows always checks the cwd first + ...(isWindows ? [process.cwd()] : []), + ...(optPath || /* istanbul ignore next: very unusual */ '').split(optDelimiter), + ] + + if (isWindows) { + const pathExtExe = optPathExt || + ['.EXE', '.CMD', '.BAT', '.COM'].join(optDelimiter) + const pathExt = pathExtExe.split(optDelimiter).flatMap((item) => [item, item.toLowerCase()]) + if (cmd.includes('.') && pathExt[0] !== '') { + pathExt.unshift('') + } + return { pathEnv, pathExt, pathExtExe } + } + + return { pathEnv, pathExt: [''] } +} + +const getPathPart = (raw, cmd) => { + const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw + const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : '' + return prefix + join(pathPart, cmd) +} + +const which = async (cmd, opt = {}) => { + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) + const found = [] + + for (const envPart of pathEnv) { + const p = getPathPart(envPart, cmd) + + for (const ext of pathExt) { + const withExt = p + ext + const is = await isexe(withExt, { pathExt: pathExtExe, ignoreErrors: true }) + if (is) { + if (!opt.all) { + return withExt + } + found.push(withExt) + } + } + } + + if (opt.all && found.length) { + return found + } + + if (opt.nothrow) { + return null + } + + throw getNotFoundError(cmd) +} + +const whichSync = (cmd, opt = {}) => { + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) + const found = [] + + for (const pathEnvPart of pathEnv) { + const p = getPathPart(pathEnvPart, cmd) + + for (const ext of pathExt) { + const withExt = p + ext + const is = isexeSync(withExt, { pathExt: pathExtExe, ignoreErrors: true }) + if (is) { + if (!opt.all) { + return withExt + } + found.push(withExt) + } + } + } + + if (opt.all && found.length) { + return found + } + + if (opt.nothrow) { + return null + } + + throw getNotFoundError(cmd) +} + +module.exports = which +which.sync = whichSync + + /***/ }), /***/ 2940: @@ -85148,6 +85266,7 @@ var InstallMode; (function (InstallMode) { InstallMode["Binary"] = "binary"; InstallMode["GoInstall"] = "goinstall"; + InstallMode["None"] = "none"; })(InstallMode || (exports.InstallMode = InstallMode = {})); const printOutput = (res) => { if (res.stdout) { @@ -85258,6 +85377,9 @@ var __importStar = (this && this.__importStar) || function (mod) { __setModuleDefault(result, mod); return result; }; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.run = run; exports.postRun = postRun; @@ -85268,6 +85390,7 @@ const fs = __importStar(__nccwpck_require__(7147)); const path = __importStar(__nccwpck_require__(1017)); const tmp_1 = __nccwpck_require__(8517); const util_1 = __nccwpck_require__(3837); +const which_1 = __importDefault(__nccwpck_require__(6143)); const cache_1 = __nccwpck_require__(4810); const install_1 = __nccwpck_require__(1649); const diffUtils_1 = __nccwpck_require__(3617); @@ -85280,6 +85403,13 @@ function isOnlyNewIssues() { } async function prepareLint() { const mode = core.getInput("install-mode").toLowerCase(); + if (mode === install_1.InstallMode.None) { + const bin = await (0, which_1.default)("golangci-lint", { nothrow: true }); + if (!bin) { + throw new Error("golangci-lint binary not found in the PATH"); + } + return bin; + } const versionConfig = await (0, version_1.findLintVersion)(mode); return await (0, install_1.installLint)(versionConfig, mode); } @@ -85897,6 +86027,14 @@ module.exports = require("fs"); /***/ }), +/***/ 3292: +/***/ ((module) => { + +"use strict"; +module.exports = require("fs/promises"); + +/***/ }), + /***/ 3685: /***/ ((module) => { @@ -90238,6 +90376,212 @@ function parseParams (str) { module.exports = parseParams +/***/ }), + +/***/ 5200: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.sync = exports.isexe = exports.posix = exports.win32 = void 0; +const posix = __importStar(__nccwpck_require__(5523)); +exports.posix = posix; +const win32 = __importStar(__nccwpck_require__(4323)); +exports.win32 = win32; +__exportStar(__nccwpck_require__(7252), exports); +const platform = process.env._ISEXE_TEST_PLATFORM_ || process.platform; +const impl = platform === 'win32' ? win32 : posix; +/** + * Determine whether a path is executable on the current platform. + */ +exports.isexe = impl.isexe; +/** + * Synchronously determine whether a path is executable on the + * current platform. + */ +exports.sync = impl.sync; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 7252: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +//# sourceMappingURL=options.js.map + +/***/ }), + +/***/ 5523: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +/** + * This is the Posix implementation of isexe, which uses the file + * mode and uid/gid values. + * + * @module + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.sync = exports.isexe = void 0; +const fs_1 = __nccwpck_require__(7147); +const promises_1 = __nccwpck_require__(3292); +/** + * Determine whether a path is executable according to the mode and + * current (or specified) user and group IDs. + */ +const isexe = async (path, options = {}) => { + const { ignoreErrors = false } = options; + try { + return checkStat(await (0, promises_1.stat)(path), options); + } + catch (e) { + const er = e; + if (ignoreErrors || er.code === 'EACCES') + return false; + throw er; + } +}; +exports.isexe = isexe; +/** + * Synchronously determine whether a path is executable according to + * the mode and current (or specified) user and group IDs. + */ +const sync = (path, options = {}) => { + const { ignoreErrors = false } = options; + try { + return checkStat((0, fs_1.statSync)(path), options); + } + catch (e) { + const er = e; + if (ignoreErrors || er.code === 'EACCES') + return false; + throw er; + } +}; +exports.sync = sync; +const checkStat = (stat, options) => stat.isFile() && checkMode(stat, options); +const checkMode = (stat, options) => { + const myUid = options.uid ?? process.getuid?.(); + const myGroups = options.groups ?? process.getgroups?.() ?? []; + const myGid = options.gid ?? process.getgid?.() ?? myGroups[0]; + if (myUid === undefined || myGid === undefined) { + throw new Error('cannot get uid or gid'); + } + const groups = new Set([myGid, ...myGroups]); + const mod = stat.mode; + const uid = stat.uid; + const gid = stat.gid; + const u = parseInt('100', 8); + const g = parseInt('010', 8); + const o = parseInt('001', 8); + const ug = u | g; + return !!(mod & o || + (mod & g && groups.has(gid)) || + (mod & u && uid === myUid) || + (mod & ug && myUid === 0)); +}; +//# sourceMappingURL=posix.js.map + +/***/ }), + +/***/ 4323: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +/** + * This is the Windows implementation of isexe, which uses the file + * extension and PATHEXT setting. + * + * @module + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.sync = exports.isexe = void 0; +const fs_1 = __nccwpck_require__(7147); +const promises_1 = __nccwpck_require__(3292); +/** + * Determine whether a path is executable based on the file extension + * and PATHEXT environment variable (or specified pathExt option) + */ +const isexe = async (path, options = {}) => { + const { ignoreErrors = false } = options; + try { + return checkStat(await (0, promises_1.stat)(path), path, options); + } + catch (e) { + const er = e; + if (ignoreErrors || er.code === 'EACCES') + return false; + throw er; + } +}; +exports.isexe = isexe; +/** + * Synchronously determine whether a path is executable based on the file + * extension and PATHEXT environment variable (or specified pathExt option) + */ +const sync = (path, options = {}) => { + const { ignoreErrors = false } = options; + try { + return checkStat((0, fs_1.statSync)(path), path, options); + } + catch (e) { + const er = e; + if (ignoreErrors || er.code === 'EACCES') + return false; + throw er; + } +}; +exports.sync = sync; +const checkPathExt = (path, options) => { + const { pathExt = process.env.PATHEXT || '' } = options; + const peSplit = pathExt.split(';'); + if (peSplit.indexOf('') !== -1) { + return true; + } + for (let i = 0; i < peSplit.length; i++) { + const p = peSplit[i].toLowerCase(); + const ext = path.substring(path.length - p.length).toLowerCase(); + if (p && ext === p) { + return true; + } + } + return false; +}; +const checkStat = (stat, path, options) => stat.isFile() && checkPathExt(path, options); +//# sourceMappingURL=win32.js.map + /***/ }), /***/ 3765: diff --git a/dist/run/index.js b/dist/run/index.js index 3cd1233ae9..049d9318c4 100644 --- a/dist/run/index.js +++ b/dist/run/index.js @@ -79831,6 +79831,124 @@ module.exports.implForWrapper = function (wrapper) { +/***/ }), + +/***/ 6143: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const { isexe, sync: isexeSync } = __nccwpck_require__(5200) +const { join, delimiter, sep, posix } = __nccwpck_require__(1017) + +const isWindows = process.platform === 'win32' + +// used to check for slashed in commands passed in. always checks for the posix +// seperator on all platforms, and checks for the current separator when not on +// a posix platform. don't use the isWindows check for this since that is mocked +// in tests but we still need the code to actually work when called. that is also +// why it is ignored from coverage. +/* istanbul ignore next */ +const rSlash = new RegExp(`[${posix.sep}${sep === posix.sep ? '' : sep}]`.replace(/(\\)/g, '\\$1')) +const rRel = new RegExp(`^\\.${rSlash.source}`) + +const getNotFoundError = (cmd) => + Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' }) + +const getPathInfo = (cmd, { + path: optPath = process.env.PATH, + pathExt: optPathExt = process.env.PATHEXT, + delimiter: optDelimiter = delimiter, +}) => { + // If it has a slash, then we don't bother searching the pathenv. + // just check the file itself, and that's it. + const pathEnv = cmd.match(rSlash) ? [''] : [ + // windows always checks the cwd first + ...(isWindows ? [process.cwd()] : []), + ...(optPath || /* istanbul ignore next: very unusual */ '').split(optDelimiter), + ] + + if (isWindows) { + const pathExtExe = optPathExt || + ['.EXE', '.CMD', '.BAT', '.COM'].join(optDelimiter) + const pathExt = pathExtExe.split(optDelimiter).flatMap((item) => [item, item.toLowerCase()]) + if (cmd.includes('.') && pathExt[0] !== '') { + pathExt.unshift('') + } + return { pathEnv, pathExt, pathExtExe } + } + + return { pathEnv, pathExt: [''] } +} + +const getPathPart = (raw, cmd) => { + const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw + const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : '' + return prefix + join(pathPart, cmd) +} + +const which = async (cmd, opt = {}) => { + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) + const found = [] + + for (const envPart of pathEnv) { + const p = getPathPart(envPart, cmd) + + for (const ext of pathExt) { + const withExt = p + ext + const is = await isexe(withExt, { pathExt: pathExtExe, ignoreErrors: true }) + if (is) { + if (!opt.all) { + return withExt + } + found.push(withExt) + } + } + } + + if (opt.all && found.length) { + return found + } + + if (opt.nothrow) { + return null + } + + throw getNotFoundError(cmd) +} + +const whichSync = (cmd, opt = {}) => { + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) + const found = [] + + for (const pathEnvPart of pathEnv) { + const p = getPathPart(pathEnvPart, cmd) + + for (const ext of pathExt) { + const withExt = p + ext + const is = isexeSync(withExt, { pathExt: pathExtExe, ignoreErrors: true }) + if (is) { + if (!opt.all) { + return withExt + } + found.push(withExt) + } + } + } + + if (opt.all && found.length) { + return found + } + + if (opt.nothrow) { + return null + } + + throw getNotFoundError(cmd) +} + +module.exports = which +which.sync = whichSync + + /***/ }), /***/ 2940: @@ -85148,6 +85266,7 @@ var InstallMode; (function (InstallMode) { InstallMode["Binary"] = "binary"; InstallMode["GoInstall"] = "goinstall"; + InstallMode["None"] = "none"; })(InstallMode || (exports.InstallMode = InstallMode = {})); const printOutput = (res) => { if (res.stdout) { @@ -85258,6 +85377,9 @@ var __importStar = (this && this.__importStar) || function (mod) { __setModuleDefault(result, mod); return result; }; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.run = run; exports.postRun = postRun; @@ -85268,6 +85390,7 @@ const fs = __importStar(__nccwpck_require__(7147)); const path = __importStar(__nccwpck_require__(1017)); const tmp_1 = __nccwpck_require__(8517); const util_1 = __nccwpck_require__(3837); +const which_1 = __importDefault(__nccwpck_require__(6143)); const cache_1 = __nccwpck_require__(4810); const install_1 = __nccwpck_require__(1649); const diffUtils_1 = __nccwpck_require__(3617); @@ -85280,6 +85403,13 @@ function isOnlyNewIssues() { } async function prepareLint() { const mode = core.getInput("install-mode").toLowerCase(); + if (mode === install_1.InstallMode.None) { + const bin = await (0, which_1.default)("golangci-lint", { nothrow: true }); + if (!bin) { + throw new Error("golangci-lint binary not found in the PATH"); + } + return bin; + } const versionConfig = await (0, version_1.findLintVersion)(mode); return await (0, install_1.installLint)(versionConfig, mode); } @@ -85897,6 +86027,14 @@ module.exports = require("fs"); /***/ }), +/***/ 3292: +/***/ ((module) => { + +"use strict"; +module.exports = require("fs/promises"); + +/***/ }), + /***/ 3685: /***/ ((module) => { @@ -90238,6 +90376,212 @@ function parseParams (str) { module.exports = parseParams +/***/ }), + +/***/ 5200: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.sync = exports.isexe = exports.posix = exports.win32 = void 0; +const posix = __importStar(__nccwpck_require__(5523)); +exports.posix = posix; +const win32 = __importStar(__nccwpck_require__(4323)); +exports.win32 = win32; +__exportStar(__nccwpck_require__(7252), exports); +const platform = process.env._ISEXE_TEST_PLATFORM_ || process.platform; +const impl = platform === 'win32' ? win32 : posix; +/** + * Determine whether a path is executable on the current platform. + */ +exports.isexe = impl.isexe; +/** + * Synchronously determine whether a path is executable on the + * current platform. + */ +exports.sync = impl.sync; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 7252: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +//# sourceMappingURL=options.js.map + +/***/ }), + +/***/ 5523: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +/** + * This is the Posix implementation of isexe, which uses the file + * mode and uid/gid values. + * + * @module + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.sync = exports.isexe = void 0; +const fs_1 = __nccwpck_require__(7147); +const promises_1 = __nccwpck_require__(3292); +/** + * Determine whether a path is executable according to the mode and + * current (or specified) user and group IDs. + */ +const isexe = async (path, options = {}) => { + const { ignoreErrors = false } = options; + try { + return checkStat(await (0, promises_1.stat)(path), options); + } + catch (e) { + const er = e; + if (ignoreErrors || er.code === 'EACCES') + return false; + throw er; + } +}; +exports.isexe = isexe; +/** + * Synchronously determine whether a path is executable according to + * the mode and current (or specified) user and group IDs. + */ +const sync = (path, options = {}) => { + const { ignoreErrors = false } = options; + try { + return checkStat((0, fs_1.statSync)(path), options); + } + catch (e) { + const er = e; + if (ignoreErrors || er.code === 'EACCES') + return false; + throw er; + } +}; +exports.sync = sync; +const checkStat = (stat, options) => stat.isFile() && checkMode(stat, options); +const checkMode = (stat, options) => { + const myUid = options.uid ?? process.getuid?.(); + const myGroups = options.groups ?? process.getgroups?.() ?? []; + const myGid = options.gid ?? process.getgid?.() ?? myGroups[0]; + if (myUid === undefined || myGid === undefined) { + throw new Error('cannot get uid or gid'); + } + const groups = new Set([myGid, ...myGroups]); + const mod = stat.mode; + const uid = stat.uid; + const gid = stat.gid; + const u = parseInt('100', 8); + const g = parseInt('010', 8); + const o = parseInt('001', 8); + const ug = u | g; + return !!(mod & o || + (mod & g && groups.has(gid)) || + (mod & u && uid === myUid) || + (mod & ug && myUid === 0)); +}; +//# sourceMappingURL=posix.js.map + +/***/ }), + +/***/ 4323: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +/** + * This is the Windows implementation of isexe, which uses the file + * extension and PATHEXT setting. + * + * @module + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.sync = exports.isexe = void 0; +const fs_1 = __nccwpck_require__(7147); +const promises_1 = __nccwpck_require__(3292); +/** + * Determine whether a path is executable based on the file extension + * and PATHEXT environment variable (or specified pathExt option) + */ +const isexe = async (path, options = {}) => { + const { ignoreErrors = false } = options; + try { + return checkStat(await (0, promises_1.stat)(path), path, options); + } + catch (e) { + const er = e; + if (ignoreErrors || er.code === 'EACCES') + return false; + throw er; + } +}; +exports.isexe = isexe; +/** + * Synchronously determine whether a path is executable based on the file + * extension and PATHEXT environment variable (or specified pathExt option) + */ +const sync = (path, options = {}) => { + const { ignoreErrors = false } = options; + try { + return checkStat((0, fs_1.statSync)(path), path, options); + } + catch (e) { + const er = e; + if (ignoreErrors || er.code === 'EACCES') + return false; + throw er; + } +}; +exports.sync = sync; +const checkPathExt = (path, options) => { + const { pathExt = process.env.PATHEXT || '' } = options; + const peSplit = pathExt.split(';'); + if (peSplit.indexOf('') !== -1) { + return true; + } + for (let i = 0; i < peSplit.length; i++) { + const p = peSplit[i].toLowerCase(); + const ext = path.substring(path.length - p.length).toLowerCase(); + if (p && ext === p) { + return true; + } + } + return false; +}; +const checkStat = (stat, path, options) => stat.isFile() && checkPathExt(path, options); +//# sourceMappingURL=win32.js.map + /***/ }), /***/ 3765: diff --git a/package-lock.json b/package-lock.json index 71b550d3f4..a030e42399 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,9 @@ "@types/node": "^22.0.0", "@types/semver": "^7.5.8", "@types/tmp": "^0.2.6", - "tmp": "^0.2.3" + "@types/which": "^3.0.4", + "tmp": "^0.2.3", + "which": "^4.0.0" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^7.17.0", @@ -680,6 +682,11 @@ "@types/node": "*" } }, + "node_modules/@types/which": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/which/-/which-3.0.4.tgz", + "integrity": "sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w==" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "7.17.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.17.0.tgz", @@ -1260,6 +1267,27 @@ "node": ">= 8" } }, + "node_modules/cross-spawn/node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/data-view-buffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", @@ -2584,10 +2612,12 @@ "dev": true }, "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "engines": { + "node": ">=16" + } }, "node_modules/js-yaml": { "version": "4.1.0", @@ -3643,18 +3673,17 @@ } }, "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", "dependencies": { - "isexe": "^2.0.0" + "isexe": "^3.1.1" }, "bin": { - "node-which": "bin/node-which" + "node-which": "bin/which.js" }, "engines": { - "node": ">= 8" + "node": "^16.13.0 || >=18.0.0" } }, "node_modules/which-boxed-primitive": { diff --git a/package.json b/package.json index e9dd4e592d..d6a41ccc8b 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,9 @@ "@types/node": "^22.0.0", "@types/semver": "^7.5.8", "@types/tmp": "^0.2.6", - "tmp": "^0.2.3" + "@types/which": "^3.0.4", + "tmp": "^0.2.3", + "which": "^4.0.0" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^7.17.0", diff --git a/src/install.ts b/src/install.ts index f98d87c876..a0621436d4 100644 --- a/src/install.ts +++ b/src/install.ts @@ -38,6 +38,7 @@ const getAssetURL = (versionConfig: VersionConfig): string => { export enum InstallMode { Binary = "binary", GoInstall = "goinstall", + None = "none", } type ExecRes = { diff --git a/src/run.ts b/src/run.ts index 7e3fa1c1a3..b60ed9bf88 100644 --- a/src/run.ts +++ b/src/run.ts @@ -6,6 +6,7 @@ import * as fs from "fs" import * as path from "path" import { dir } from "tmp" import { promisify } from "util" +import which from "which" import { restoreCache, saveCache } from "./cache" import { installLint, InstallMode } from "./install" @@ -22,6 +23,15 @@ function isOnlyNewIssues(): boolean { async function prepareLint(): Promise { const mode = core.getInput("install-mode").toLowerCase() + + if (mode === InstallMode.None) { + const bin = await which("golangci-lint", { nothrow: true }) + if (!bin) { + throw new Error("golangci-lint binary not found in the PATH") + } + return bin + } + const versionConfig = await findLintVersion(mode) return await installLint(versionConfig, mode)