Sergey Vilgelm d9f0e73c04
Check that go.mod exists in reading the version (#173)
Add additional tests in github actions
Support working directory for reading the version from go.mod
2021-02-23 23:51:00 -06:00

160 lines
4.7 KiB
TypeScript

import * as core from "@actions/core"
import * as httpm from "@actions/http-client"
import * as fs from "fs"
import path from "path"
// TODO: make a class
export type Version = {
major: number
minor: number
patch: number | null
} | null
const versionRe = /^v(\d+)\.(\d+)(?:\.(\d+))?$/
const modVersionRe = /github.com\/golangci\/golangci-lint\s(v.+)/
const parseVersion = (s: string): Version => {
if (s == "latest" || s == "") {
return null
}
const match = s.match(versionRe)
if (!match) {
throw new Error(`invalid version string '${s}', expected format v1.2 or v1.2.3`)
}
return {
major: parseInt(match[1]),
minor: parseInt(match[2]),
patch: match[3] === undefined ? null : parseInt(match[3]),
}
}
export const stringifyVersion = (v: Version): string => {
if (v == null) {
return "latest"
}
return `v${v.major}.${v.minor}${v.patch !== null ? `.${v.patch}` : ``}`
}
const minVersion = {
major: 1,
minor: 28,
patch: 3,
}
const isLessVersion = (a: Version, b: Version): boolean => {
if (a == null) {
return true
}
if (b == null) {
return false
}
if (a.major != b.major) {
return a.major < b.major
}
// Do not compare patch parts because if the min version has a non zero value
// then it returns false, since the patch version of requested is always zero
return a.minor < b.minor
}
const getRequestedLintVersion = (): Version => {
let requestedLintVersion = core.getInput(`version`)
const workingDirectory = core.getInput(`working-directory`)
let goMod = "go.mod"
if (workingDirectory) {
goMod = path.join(workingDirectory, goMod)
}
if (requestedLintVersion == "" && fs.existsSync(goMod)) {
const content = fs.readFileSync(goMod, "utf-8")
const match = content.match(modVersionRe)
if (match) {
requestedLintVersion = match[1]
core.info(`Found golangci-lint version '${requestedLintVersion}' in '${goMod}' file`)
}
}
const parsedRequestedLintVersion = parseVersion(requestedLintVersion)
if (parsedRequestedLintVersion == null) {
return null
}
if (isLessVersion(parsedRequestedLintVersion, minVersion)) {
throw new Error(
`requested golangci-lint version '${requestedLintVersion}' isn't supported: we support only ${stringifyVersion(
minVersion
)} and later versions`
)
}
return parsedRequestedLintVersion
}
export type VersionConfig = {
Error?: string
TargetVersion: string
AssetURL: string
}
type Config = {
MinorVersionToConfig: {
[minorVersion: string]: VersionConfig
}
}
const getConfig = async (): Promise<Config> => {
const http = new httpm.HttpClient(`golangci/golangci-lint-action`, [], {
allowRetries: true,
maxRetries: 5,
})
try {
const url = `https://raw.githubusercontent.com/golangci/golangci-lint/master/assets/github-action-config.json`
const response: httpm.HttpClientResponse = await http.get(url)
if (response.message.statusCode !== 200) {
throw new Error(`failed to download from "${url}". Code(${response.message.statusCode}) Message(${response.message.statusMessage})`)
}
const body = await response.readBody()
return JSON.parse(body)
} catch (exc) {
throw new Error(`failed to get action config: ${exc.message}`)
}
}
export async function findLintVersion(): Promise<VersionConfig> {
core.info(`Finding needed golangci-lint version...`)
const reqLintVersion = getRequestedLintVersion()
// if the patched version is passed, just use it
if (reqLintVersion?.major !== null && reqLintVersion?.minor != null && reqLintVersion?.patch !== null) {
return new Promise((resolve) => {
const versionWithoutV = `${reqLintVersion.major}.${reqLintVersion.minor}.${reqLintVersion.patch}`
resolve({
TargetVersion: `v${versionWithoutV}`,
AssetURL: `https://github.com/golangci/golangci-lint/releases/download/v${versionWithoutV}/golangci-lint-${versionWithoutV}-linux-amd64.tar.gz`,
})
})
}
const startedAt = Date.now()
const config = await getConfig()
if (!config.MinorVersionToConfig) {
core.warning(JSON.stringify(config))
throw new Error(`invalid config: no MinorVersionToConfig field`)
}
const versionConfig = config.MinorVersionToConfig[stringifyVersion(reqLintVersion)]
if (!versionConfig) {
throw new Error(`requested golangci-lint version '${stringifyVersion(reqLintVersion)}' doesn't exist`)
}
if (versionConfig.Error) {
throw new Error(`failed to use requested golangci-lint version '${stringifyVersion(reqLintVersion)}': ${versionConfig.Error}`)
}
core.info(
`Requested golangci-lint '${stringifyVersion(reqLintVersion)}', using '${versionConfig.TargetVersion}', calculation took ${
Date.now() - startedAt
}ms`
)
return versionConfig
}