mirror of
https://github.com/golangci/golangci-lint-action.git
synced 2025-12-14 23:11:14 +00:00
refactor: change the code to be more flexible
This commit is contained in:
parent
f3ae99f5f5
commit
3da8bd416a
5 changed files with 93 additions and 104 deletions
16
src/cache.ts
16
src/cache.ts
|
|
@ -74,7 +74,10 @@ async function buildCacheKeys(): Promise<string[]> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function restoreCache(): Promise<void> {
|
export async function restoreCache(): Promise<void> {
|
||||||
if (core.getBooleanInput(`skip-cache`, { required: true })) return
|
if (core.getBooleanInput(`skip-cache`, { required: true })) {
|
||||||
|
core.info(`Skipping cache restoration`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (!utils.isValidEvent()) {
|
if (!utils.isValidEvent()) {
|
||||||
utils.logWarning(
|
utils.logWarning(
|
||||||
|
|
@ -116,8 +119,15 @@ export async function restoreCache(): Promise<void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function saveCache(): Promise<void> {
|
export async function saveCache(): Promise<void> {
|
||||||
if (core.getBooleanInput(`skip-cache`, { required: true })) return
|
if (core.getBooleanInput(`skip-cache`, { required: true })) {
|
||||||
if (core.getBooleanInput(`skip-save-cache`, { required: true })) return
|
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
|
// Validate inputs, this can cause task failure
|
||||||
if (!utils.isValidEvent()) {
|
if (!utils.isValidEvent()) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import * as core from "@actions/core"
|
import * as core from "@actions/core"
|
||||||
import * as tc from "@actions/tool-cache"
|
import * as tc from "@actions/tool-cache"
|
||||||
import { exec, ExecOptionsWithStringEncoding } from "child_process"
|
import { exec, ExecOptionsWithStringEncoding } from "child_process"
|
||||||
|
import fs from "fs"
|
||||||
import os from "os"
|
import os from "os"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import { promisify } from "util"
|
import { promisify } from "util"
|
||||||
|
|
@ -8,7 +9,7 @@ import which from "which"
|
||||||
|
|
||||||
import { getVersion, VersionInfo } from "./version"
|
import { getVersion, VersionInfo } from "./version"
|
||||||
|
|
||||||
const execShellCommand = promisify(exec)
|
const execCommand = promisify(exec)
|
||||||
|
|
||||||
export enum InstallMode {
|
export enum InstallMode {
|
||||||
Binary = "binary",
|
Binary = "binary",
|
||||||
|
|
@ -21,13 +22,15 @@ type ExecRes = {
|
||||||
stderr: string
|
stderr: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const printOutput = (res: ExecRes): void => {
|
const printOutput = (res: ExecRes): ExecRes => {
|
||||||
if (res.stdout) {
|
if (res.stdout) {
|
||||||
core.info(res.stdout)
|
core.info(res.stdout)
|
||||||
}
|
}
|
||||||
if (res.stderr) {
|
if (res.stderr) {
|
||||||
core.info(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.
|
* @returns path to installed binary of golangci-lint.
|
||||||
*/
|
*/
|
||||||
export async function install(): Promise<string> {
|
export async function install(): Promise<string> {
|
||||||
|
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()
|
const mode = core.getInput("install-mode").toLowerCase()
|
||||||
|
|
||||||
if (mode === InstallMode.None) {
|
if (mode === InstallMode.None) {
|
||||||
|
|
@ -84,17 +98,14 @@ async function goInstall(versionInfo: VersionInfo): Promise<string> {
|
||||||
|
|
||||||
const options: ExecOptionsWithStringEncoding = { env: { ...process.env, CGO_ENABLED: "1" } }
|
const options: ExecOptionsWithStringEncoding = { env: { ...process.env, CGO_ENABLED: "1" } }
|
||||||
|
|
||||||
const exres = await execShellCommand(
|
await execCommand(`go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${versionInfo.TargetVersion}`, options).then(
|
||||||
`go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${versionInfo.TargetVersion}`,
|
printOutput
|
||||||
options
|
|
||||||
)
|
)
|
||||||
printOutput(exres)
|
|
||||||
|
|
||||||
const res = await execShellCommand(
|
const res = await execCommand(
|
||||||
`go install -n github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${versionInfo.TargetVersion}`,
|
`go install -n github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${versionInfo.TargetVersion}`,
|
||||||
options
|
options
|
||||||
)
|
).then(printOutput)
|
||||||
printOutput(res)
|
|
||||||
|
|
||||||
// The output of `go install -n` when the binary is already installed is `touch <path_to_the_binary>`.
|
// The output of `go install -n` when the binary is already installed is `touch <path_to_the_binary>`.
|
||||||
const binPath = res.stderr
|
const binPath = res.stderr
|
||||||
|
|
|
||||||
10
src/patch.ts
10
src/patch.ts
|
|
@ -17,10 +17,6 @@ export function isOnlyNewIssues(): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchPatch(): Promise<string> {
|
export async function fetchPatch(): Promise<string> {
|
||||||
if (!isOnlyNewIssues()) {
|
|
||||||
return ``
|
|
||||||
}
|
|
||||||
|
|
||||||
const ctx = github.context
|
const ctx = github.context
|
||||||
|
|
||||||
switch (ctx.eventName) {
|
switch (ctx.eventName) {
|
||||||
|
|
@ -70,8 +66,7 @@ async function fetchPullRequestPatch(ctx: Context): Promise<string> {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const tempDir = await createTempDir()
|
const patchPath = await createTempDir().then((tempDir) => path.join(tempDir, "pull.patch"))
|
||||||
const patchPath = path.join(tempDir, "pull.patch")
|
|
||||||
core.info(`Writing patch to ${patchPath}`)
|
core.info(`Writing patch to ${patchPath}`)
|
||||||
await writeFile(patchPath, alterDiffPatch(patch))
|
await writeFile(patchPath, alterDiffPatch(patch))
|
||||||
return patchPath
|
return patchPath
|
||||||
|
|
@ -108,8 +103,7 @@ async function fetchPushPatch(ctx: Context): Promise<string> {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const tempDir = await createTempDir()
|
const patchPath = await createTempDir().then((tempDir) => path.join(tempDir, "push.patch"))
|
||||||
const patchPath = path.join(tempDir, "push.patch")
|
|
||||||
core.info(`Writing patch to ${patchPath}`)
|
core.info(`Writing patch to ${patchPath}`)
|
||||||
await writeFile(patchPath, alterDiffPatch(patch))
|
await writeFile(patchPath, alterDiffPatch(patch))
|
||||||
return patchPath
|
return patchPath
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import * as path from "path"
|
||||||
import { promisify } from "util"
|
import { promisify } from "util"
|
||||||
import YAML from "yaml"
|
import YAML from "yaml"
|
||||||
|
|
||||||
const execShellCommand = promisify(exec)
|
const execCommand = promisify(exec)
|
||||||
|
|
||||||
type ExecRes = {
|
type ExecRes = {
|
||||||
stdout: string
|
stdout: string
|
||||||
|
|
@ -40,7 +40,7 @@ export async function install(binPath: string): Promise<string> {
|
||||||
.find((filePath) => fs.existsSync(filePath))
|
.find((filePath) => fs.existsSync(filePath))
|
||||||
|
|
||||||
if (!configFile || configFile === "") {
|
if (!configFile || configFile === "") {
|
||||||
return ""
|
return binPath
|
||||||
}
|
}
|
||||||
|
|
||||||
core.info(`Found configuration for the plugin module system : ${configFile}`)
|
core.info(`Found configuration for the plugin module system : ${configFile}`)
|
||||||
|
|
@ -74,18 +74,15 @@ export async function install(binPath: string): Promise<string> {
|
||||||
|
|
||||||
core.info(`Running [${cmd}] in [${rootDir}] ...`)
|
core.info(`Running [${cmd}] in [${rootDir}] ...`)
|
||||||
|
|
||||||
try {
|
const options: ExecOptionsWithStringEncoding = {
|
||||||
const options: ExecOptionsWithStringEncoding = {
|
cwd: rootDir,
|
||||||
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}`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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}`)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
115
src/run.ts
115
src/run.ts
|
|
@ -10,37 +10,7 @@ import { install } from "./install"
|
||||||
import { fetchPatch, isOnlyNewIssues } from "./patch"
|
import { fetchPatch, isOnlyNewIssues } from "./patch"
|
||||||
import * as plugins from "./plugins"
|
import * as plugins from "./plugins"
|
||||||
|
|
||||||
const execShellCommand = promisify(exec)
|
const execCommand = promisify(exec)
|
||||||
|
|
||||||
type Env = {
|
|
||||||
binPath: string
|
|
||||||
patchPath: string
|
|
||||||
}
|
|
||||||
|
|
||||||
async function prepareEnv(installOnly: boolean): Promise<Env> {
|
|
||||||
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 }
|
|
||||||
}
|
|
||||||
|
|
||||||
type ExecRes = {
|
type ExecRes = {
|
||||||
stdout: string
|
stdout: string
|
||||||
|
|
@ -56,13 +26,7 @@ const printOutput = (res: ExecRes): void => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function runLint(binPath: string, patchPath: string): Promise<void> {
|
async function runLint(binPath: string): Promise<void> {
|
||||||
const debug = core.getInput(`debug`)
|
|
||||||
if (debug.split(`,`).includes(`cache`)) {
|
|
||||||
const res = await execShellCommand(`${binPath} cache status`)
|
|
||||||
printOutput(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
const userArgs = core.getInput(`args`)
|
const userArgs = core.getInput(`args`)
|
||||||
const addedArgs: string[] = []
|
const addedArgs: string[] = []
|
||||||
|
|
||||||
|
|
@ -77,17 +41,6 @@ async function runLint(binPath: string, patchPath: string): Promise<void> {
|
||||||
const userArgsMap = new Map<string, string>(userArgsList)
|
const userArgsMap = new Map<string, string>(userArgsList)
|
||||||
const userArgNames = new Set<string>(userArgsList.map(([key]) => key))
|
const userArgNames = new Set<string>(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 (isOnlyNewIssues()) {
|
||||||
if (
|
if (
|
||||||
userArgNames.has(`new`) ||
|
userArgNames.has(`new`) ||
|
||||||
|
|
@ -99,6 +52,7 @@ async function runLint(binPath: string, patchPath: string): Promise<void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ctx = github.context
|
const ctx = github.context
|
||||||
|
const patchPath = await fetchPatch()
|
||||||
|
|
||||||
core.info(`only new issues on ${ctx.eventName}: ${patchPath}`)
|
core.info(`only new issues on ${ctx.eventName}: ${patchPath}`)
|
||||||
|
|
||||||
|
|
@ -150,22 +104,21 @@ async function runLint(binPath: string, patchPath: string): Promise<void> {
|
||||||
core.info(`Running [${cmd}] in [${cmdArgs.cwd || process.cwd()}] ...`)
|
core.info(`Running [${cmd}] in [${cmdArgs.cwd || process.cwd()}] ...`)
|
||||||
|
|
||||||
const startedAt = Date.now()
|
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) {
|
return execCommand(cmd, cmdArgs)
|
||||||
core.setFailed(`issues found`)
|
.then(printOutput)
|
||||||
} else {
|
.then(() => core.info(`golangci-lint found no issues`))
|
||||||
core.setFailed(`golangci-lint exit with code ${exc.code}`)
|
.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<string, string>, cmdArgs: ExecOptionsWithStringEncoding): Promise<void> {
|
async function runVerify(binPath: string, userArgsMap: Map<string, string>, cmdArgs: ExecOptionsWithStringEncoding): Promise<void> {
|
||||||
|
|
@ -186,8 +139,7 @@ async function runVerify(binPath: string, userArgsMap: Map<string, string>, cmdA
|
||||||
|
|
||||||
core.info(`Running [${cmdVerify}] in [${cmdArgs.cwd || process.cwd()}] ...`)
|
core.info(`Running [${cmdVerify}] in [${cmdArgs.cwd || process.cwd()}] ...`)
|
||||||
|
|
||||||
const res = await execShellCommand(cmdVerify, cmdArgs)
|
await execCommand(cmdVerify, cmdArgs).then(printOutput)
|
||||||
printOutput(res)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getConfigPath(binPath: string, userArgsMap: Map<string, string>, cmdArgs: ExecOptionsWithStringEncoding): Promise<string> {
|
async function getConfigPath(binPath: string, userArgsMap: Map<string, string>, cmdArgs: ExecOptionsWithStringEncoding): Promise<string> {
|
||||||
|
|
@ -199,26 +151,51 @@ async function getConfigPath(binPath: string, userArgsMap: Map<string, string>,
|
||||||
core.info(`Running [${cmdConfigPath}] in [${cmdArgs.cwd || process.cwd()}] ...`)
|
core.info(`Running [${cmdConfigPath}] in [${cmdArgs.cwd || process.cwd()}] ...`)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resPath = await execShellCommand(cmdConfigPath, cmdArgs)
|
const resPath = await execCommand(cmdConfigPath, cmdArgs)
|
||||||
return resPath.stderr.trim()
|
return resPath.stderr.trim()
|
||||||
} catch {
|
} catch {
|
||||||
return ``
|
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<void> {
|
export async function run(): Promise<void> {
|
||||||
try {
|
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))
|
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) {
|
if (installOnly) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
await core.group(`run golangci-lint`, () => runLint(binPath, patchPath))
|
await core.group(`run golangci-lint`, () => runLint(binPath))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
core.error(`Failed to run: ${error}, ${error.stack}`)
|
core.error(`Failed to run: ${error}, ${error.stack}`)
|
||||||
core.setFailed(error.message)
|
core.setFailed(error.message)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue