From 3da8bd416a854285c502ba9663ff115627f3169e Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Thu, 20 Nov 2025 17:12:16 +0100 Subject: [PATCH] refactor: change the code to be more flexible --- src/cache.ts | 16 +++++-- src/install.ts | 29 +++++++++---- src/patch.ts | 10 +---- src/plugins.ts | 27 ++++++------ src/run.ts | 115 ++++++++++++++++++++----------------------------- 5 files changed, 93 insertions(+), 104 deletions(-) diff --git a/src/cache.ts b/src/cache.ts index 57b817e..2e51782 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -74,7 +74,10 @@ async function buildCacheKeys(): Promise { } export async function restoreCache(): Promise { - if (core.getBooleanInput(`skip-cache`, { required: true })) return + if (core.getBooleanInput(`skip-cache`, { required: true })) { + core.info(`Skipping cache restoration`) + return + } if (!utils.isValidEvent()) { utils.logWarning( @@ -116,8 +119,15 @@ export async function restoreCache(): Promise { } export async function saveCache(): Promise { - if (core.getBooleanInput(`skip-cache`, { required: true })) return - if (core.getBooleanInput(`skip-save-cache`, { required: true })) return + if (core.getBooleanInput(`skip-cache`, { required: true })) { + core.info(`Skipping cache saving`) + return + } + + if (core.getBooleanInput(`skip-save-cache`, { required: true })) { + core.info(`Skipping cache saving`) + return + } // Validate inputs, this can cause task failure if (!utils.isValidEvent()) { diff --git a/src/install.ts b/src/install.ts index 8d71ec7..f8b2b18 100644 --- a/src/install.ts +++ b/src/install.ts @@ -1,6 +1,7 @@ import * as core from "@actions/core" import * as tc from "@actions/tool-cache" import { exec, ExecOptionsWithStringEncoding } from "child_process" +import fs from "fs" import os from "os" import path from "path" import { promisify } from "util" @@ -8,7 +9,7 @@ import which from "which" import { getVersion, VersionInfo } from "./version" -const execShellCommand = promisify(exec) +const execCommand = promisify(exec) export enum InstallMode { Binary = "binary", @@ -21,13 +22,15 @@ type ExecRes = { stderr: string } -const printOutput = (res: ExecRes): void => { +const printOutput = (res: ExecRes): ExecRes => { if (res.stdout) { core.info(res.stdout) } if (res.stderr) { core.info(res.stderr) } + + return res } /** @@ -36,6 +39,17 @@ const printOutput = (res: ExecRes): void => { * @returns path to installed binary of golangci-lint. */ export async function install(): Promise { + const problemMatchers = core.getBooleanInput(`problem-matchers`) + + if (problemMatchers) { + const matchersPath = path.join(__dirname, "../..", "problem-matchers.json") + if (fs.existsSync(matchersPath)) { + // Adds problem matchers. + // https://github.com/actions/setup-go/blob/cdcb36043654635271a94b9a6d1392de5bb323a7/src/main.ts#L81-L83 + core.info(`##[add-matcher]${matchersPath}`) + } + } + const mode = core.getInput("install-mode").toLowerCase() if (mode === InstallMode.None) { @@ -84,17 +98,14 @@ async function goInstall(versionInfo: VersionInfo): Promise { const options: ExecOptionsWithStringEncoding = { env: { ...process.env, CGO_ENABLED: "1" } } - const exres = await execShellCommand( - `go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${versionInfo.TargetVersion}`, - options + await execCommand(`go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${versionInfo.TargetVersion}`, options).then( + printOutput ) - printOutput(exres) - const res = await execShellCommand( + const res = await execCommand( `go install -n github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${versionInfo.TargetVersion}`, options - ) - printOutput(res) + ).then(printOutput) // The output of `go install -n` when the binary is already installed is `touch `. const binPath = res.stderr diff --git a/src/patch.ts b/src/patch.ts index f2bb412..bbe89c5 100644 --- a/src/patch.ts +++ b/src/patch.ts @@ -17,10 +17,6 @@ export function isOnlyNewIssues(): boolean { } export async function fetchPatch(): Promise { - if (!isOnlyNewIssues()) { - return `` - } - const ctx = github.context switch (ctx.eventName) { @@ -70,8 +66,7 @@ async function fetchPullRequestPatch(ctx: Context): Promise { } try { - const tempDir = await createTempDir() - const patchPath = path.join(tempDir, "pull.patch") + const patchPath = await createTempDir().then((tempDir) => path.join(tempDir, "pull.patch")) core.info(`Writing patch to ${patchPath}`) await writeFile(patchPath, alterDiffPatch(patch)) return patchPath @@ -108,8 +103,7 @@ async function fetchPushPatch(ctx: Context): Promise { } try { - const tempDir = await createTempDir() - const patchPath = path.join(tempDir, "push.patch") + const patchPath = await createTempDir().then((tempDir) => path.join(tempDir, "push.patch")) core.info(`Writing patch to ${patchPath}`) await writeFile(patchPath, alterDiffPatch(patch)) return patchPath diff --git a/src/plugins.ts b/src/plugins.ts index 97a624f..6d11d6d 100644 --- a/src/plugins.ts +++ b/src/plugins.ts @@ -5,7 +5,7 @@ import * as path from "path" import { promisify } from "util" import YAML from "yaml" -const execShellCommand = promisify(exec) +const execCommand = promisify(exec) type ExecRes = { stdout: string @@ -40,7 +40,7 @@ export async function install(binPath: string): Promise { .find((filePath) => fs.existsSync(filePath)) if (!configFile || configFile === "") { - return "" + return binPath } core.info(`Found configuration for the plugin module system : ${configFile}`) @@ -74,18 +74,15 @@ export async function install(binPath: string): Promise { core.info(`Running [${cmd}] in [${rootDir}] ...`) - try { - const options: ExecOptionsWithStringEncoding = { - cwd: rootDir, - } - - const res = await execShellCommand(cmd, options) - printOutput(res) - - core.info(`Built custom golangci-lint binary in ${Date.now() - startedAt}ms`) - - return path.join(rootDir, config.destination, config.name) - } catch (exc) { - throw new Error(`Failed to build custom golangci-lint binary: ${exc.message}`) + const options: ExecOptionsWithStringEncoding = { + cwd: rootDir, } + + return execCommand(cmd, options) + .then(printOutput) + .then(() => core.info(`Built custom golangci-lint binary in ${Date.now() - startedAt}ms`)) + .then(() => path.join(rootDir, config.destination, config.name)) + .catch((exc) => { + throw new Error(`Failed to build custom golangci-lint binary: ${exc.message}`) + }) } diff --git a/src/run.ts b/src/run.ts index 8687b1e..34426d6 100644 --- a/src/run.ts +++ b/src/run.ts @@ -10,37 +10,7 @@ import { install } from "./install" import { fetchPatch, isOnlyNewIssues } from "./patch" import * as plugins from "./plugins" -const execShellCommand = promisify(exec) - -type Env = { - binPath: string - patchPath: string -} - -async function prepareEnv(installOnly: boolean): Promise { - const startedAt = Date.now() - - // Prepare cache, lint and go in parallel. - await restoreCache() - - let binPath = await install() - - // Build custom golangci-lint if needed. - const customBinPath = await plugins.install(binPath) - if (customBinPath !== "") { - binPath = customBinPath - } - - if (installOnly) { - return { binPath, patchPath: `` } - } - - const patchPath = await fetchPatch() - - core.info(`Prepared env in ${Date.now() - startedAt}ms`) - - return { binPath, patchPath } -} +const execCommand = promisify(exec) type ExecRes = { stdout: string @@ -56,13 +26,7 @@ const printOutput = (res: ExecRes): void => { } } -async function runLint(binPath: string, patchPath: string): Promise { - const debug = core.getInput(`debug`) - if (debug.split(`,`).includes(`cache`)) { - const res = await execShellCommand(`${binPath} cache status`) - printOutput(res) - } - +async function runLint(binPath: string): Promise { const userArgs = core.getInput(`args`) const addedArgs: string[] = [] @@ -77,17 +41,6 @@ async function runLint(binPath: string, patchPath: string): Promise { const userArgsMap = new Map(userArgsList) const userArgNames = new Set(userArgsList.map(([key]) => key)) - const problemMatchers = core.getBooleanInput(`problem-matchers`) - - if (problemMatchers) { - const matchersPath = path.join(__dirname, "../..", "problem-matchers.json") - if (fs.existsSync(matchersPath)) { - // Adds problem matchers. - // https://github.com/actions/setup-go/blob/cdcb36043654635271a94b9a6d1392de5bb323a7/src/main.ts#L81-L83 - core.info(`##[add-matcher]${matchersPath}`) - } - } - if (isOnlyNewIssues()) { if ( userArgNames.has(`new`) || @@ -99,6 +52,7 @@ async function runLint(binPath: string, patchPath: string): Promise { } const ctx = github.context + const patchPath = await fetchPatch() core.info(`only new issues on ${ctx.eventName}: ${patchPath}`) @@ -150,22 +104,21 @@ async function runLint(binPath: string, patchPath: string): Promise { core.info(`Running [${cmd}] in [${cmdArgs.cwd || process.cwd()}] ...`) const startedAt = Date.now() - try { - const res = await execShellCommand(cmd, cmdArgs) - printOutput(res) - core.info(`golangci-lint found no issues`) - } catch (exc) { - // This logging passes issues to GitHub annotations but comments can be more convenient for some users. - printOutput(exc) - if (exc.code === 1) { - core.setFailed(`issues found`) - } else { - core.setFailed(`golangci-lint exit with code ${exc.code}`) - } - } + return execCommand(cmd, cmdArgs) + .then(printOutput) + .then(() => core.info(`golangci-lint found no issues`)) + .catch((exc) => { + // This logging passes issues to GitHub annotations. + printOutput(exc) - core.info(`Ran golangci-lint in ${Date.now() - startedAt}ms`) + if (exc.code === 1) { + core.setFailed(`issues found`) + } else { + core.setFailed(`golangci-lint exit with code ${exc.code}`) + } + }) + .finally(() => core.info(`Ran golangci-lint in ${Date.now() - startedAt}ms`)) } async function runVerify(binPath: string, userArgsMap: Map, cmdArgs: ExecOptionsWithStringEncoding): Promise { @@ -186,8 +139,7 @@ async function runVerify(binPath: string, userArgsMap: Map, cmdA core.info(`Running [${cmdVerify}] in [${cmdArgs.cwd || process.cwd()}] ...`) - const res = await execShellCommand(cmdVerify, cmdArgs) - printOutput(res) + await execCommand(cmdVerify, cmdArgs).then(printOutput) } async function getConfigPath(binPath: string, userArgsMap: Map, cmdArgs: ExecOptionsWithStringEncoding): Promise { @@ -199,26 +151,51 @@ async function getConfigPath(binPath: string, userArgsMap: Map, core.info(`Running [${cmdConfigPath}] in [${cmdArgs.cwd || process.cwd()}] ...`) try { - const resPath = await execShellCommand(cmdConfigPath, cmdArgs) + const resPath = await execCommand(cmdConfigPath, cmdArgs) return resPath.stderr.trim() } catch { return `` } } +async function debugAction(binPath: string) { + const flags = core.getInput(`debug`).split(`,`) + + if (flags.includes(`clean`)) { + const cmd = `${binPath} cache clean` + + core.info(`Running [${cmd}] ...`) + + await execCommand(cmd).then(printOutput) + } + + if (flags.includes(`cache`)) { + const cmd = `${binPath} cache status` + + core.info(`Running [${cmd}] ...`) + + await execCommand(cmd).then(printOutput) + } +} + export async function run(): Promise { try { - const installOnly = core.getBooleanInput(`install-only`, { required: true }) + await core.group(`Restore cache`, restoreCache) - const { binPath, patchPath } = await core.group(`prepare environment`, () => prepareEnv(installOnly)) + const binPath = await core.group(`Install`, () => install().then(plugins.install)) core.addPath(path.dirname(binPath)) + if (core.getInput(`debug`)) { + await core.group(`Debug`, () => debugAction(binPath)) + } + + const installOnly = core.getBooleanInput(`install-only`, { required: true }) if (installOnly) { return } - await core.group(`run golangci-lint`, () => runLint(binPath, patchPath)) + await core.group(`run golangci-lint`, () => runLint(binPath)) } catch (error) { core.error(`Failed to run: ${error}, ${error.stack}`) core.setFailed(error.message)