Merge pull request #13 from golangci/feature/action-config
use action config, don't require github token
This commit is contained in:
		
						commit
						e4cc61e5b1
					
				
							
								
								
									
										3
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							@ -15,7 +15,7 @@ jobs:
 | 
				
			|||||||
        npm install
 | 
					        npm install
 | 
				
			||||||
        npm run prepare-deps
 | 
					        npm run prepare-deps
 | 
				
			||||||
        npm run all
 | 
					        npm run all
 | 
				
			||||||
        git diff && git diff --cached
 | 
					        git diff --exit-code
 | 
				
			||||||
  test: # make sure the action works on a clean machine without building
 | 
					  test: # make sure the action works on a clean machine without building
 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
@ -24,4 +24,3 @@ jobs:
 | 
				
			|||||||
      with:
 | 
					      with:
 | 
				
			||||||
        version: v1.26
 | 
					        version: v1.26
 | 
				
			||||||
        args: --issues-exit-code=0 ./sample/...
 | 
					        args: --issues-exit-code=0 ./sample/...
 | 
				
			||||||
        github-token: ${{ secrets.GITHUB_TOKEN }}
 | 
					 | 
				
			||||||
							
								
								
									
										12
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								README.md
									
									
									
									
									
								
							@ -27,19 +27,13 @@ jobs:
 | 
				
			|||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - uses: actions/checkout@v2
 | 
					      - uses: actions/checkout@v2
 | 
				
			||||||
      - name: golangci-lint
 | 
					      - name: golangci-lint
 | 
				
			||||||
        uses: golangci/golangci-lint-action@v0.1.7
 | 
					        uses: golangci/golangci-lint-action@v0.2.0
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
 | 
					          # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
 | 
				
			||||||
          version: v1.26
 | 
					          version: v1.26
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          # Optional: golangci-lint command line arguments.
 | 
					          # Optional: golangci-lint command line arguments.
 | 
				
			||||||
          # args: ./the-only-dir-to-analyze/...
 | 
					          # args: ./the-only-dir-to-analyze/...
 | 
				
			||||||
 | 
					 | 
				
			||||||
          # Required: the token is used for fetching a list of releases of golangci-lint.
 | 
					 | 
				
			||||||
          # The secret `GITHUB_TOKEN` is automatically created by GitHub,
 | 
					 | 
				
			||||||
          # no need to create it manually.
 | 
					 | 
				
			||||||
          # https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token#about-the-github_token-secret
 | 
					 | 
				
			||||||
          github-token: ${{ secrets.GITHUB_TOKEN }}
 | 
					 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Comments and Annotations
 | 
					## Comments and Annotations
 | 
				
			||||||
@ -77,8 +71,8 @@ Inside our action we perform 3 steps:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
1. Setup environment running in parallel:
 | 
					1. Setup environment running in parallel:
 | 
				
			||||||
  * restore [cache](https://github.com/actions/cache) of previous analyzes
 | 
					  * restore [cache](https://github.com/actions/cache) of previous analyzes
 | 
				
			||||||
  * list [releases of golangci-lint](https://github.com/golangci/golangci-lint/releases) and find the latest patch version
 | 
					  * fetch [action config](https://github.com/golangci/golangci-lint/blob/master/assets/github-action-config.json) and find the latest `golangci-lint` patch version
 | 
				
			||||||
    for needed version (users of this action can specify only minor version). After that install [golangci-lint](https://github.com/golangci/golangci-lint) using [@actions/tool-cache](https://github.com/actions/toolkit/tree/master/packages/tool-cache)
 | 
					    for needed version (users of this action can specify only minor version of `golangci-lint`). After that install [golangci-lint](https://github.com/golangci/golangci-lint) using [@actions/tool-cache](https://github.com/actions/toolkit/tree/master/packages/tool-cache)
 | 
				
			||||||
  * install the latest Go 1.x version using [@actions/setup-go](https://github.com/actions/setup-go)
 | 
					  * install the latest Go 1.x version using [@actions/setup-go](https://github.com/actions/setup-go)
 | 
				
			||||||
2. Run `golangci-lint` with specified by user `args`
 | 
					2. Run `golangci-lint` with specified by user `args`
 | 
				
			||||||
3. Save cache for later builds
 | 
					3. Save cache for later builds
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										24101
									
								
								dist/post_run/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										24101
									
								
								dist/post_run/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										24101
									
								
								dist/run/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										24101
									
								
								dist/run/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -10,12 +10,12 @@
 | 
				
			|||||||
    "prepare-deps": "npm run prepare-setup-go && npm run prepare-cache",
 | 
					    "prepare-deps": "npm run prepare-setup-go && npm run prepare-cache",
 | 
				
			||||||
    "build": "tsc && ncc build -o dist/run/ src/main.ts && ncc build -o dist/post_run/ src/post_main.ts",
 | 
					    "build": "tsc && ncc build -o dist/run/ src/main.ts && ncc build -o dist/post_run/ src/post_main.ts",
 | 
				
			||||||
    "type-check": "tsc",
 | 
					    "type-check": "tsc",
 | 
				
			||||||
    "lint": "eslint **/*.ts --cache",
 | 
					    "lint": "eslint --max-warnings 1 **/*.ts --cache",
 | 
				
			||||||
    "lint-fix": "eslint **/*.ts --cache --fix",
 | 
					    "lint-fix": "eslint **/*.ts --cache --fix",
 | 
				
			||||||
    "format": "prettier --write **/*.ts",
 | 
					    "format": "prettier --write **/*.ts",
 | 
				
			||||||
    "format-check": "prettier --check **/*.ts",
 | 
					    "format-check": "prettier --check **/*.ts",
 | 
				
			||||||
    "all": "npm run build && npm run format-check && npm run lint",
 | 
					    "all": "npm run build && npm run format-check && npm run lint",
 | 
				
			||||||
    "local": "npm run build && act -j test -s GOLANGCI_LINT_GITHUB_TOKEN=$GITHUB_TOKEN"
 | 
					    "local": "npm run build && act -j test -b"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "repository": {
 | 
					  "repository": {
 | 
				
			||||||
    "type": "git",
 | 
					    "type": "git",
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@ import save from "cache/lib/save"
 | 
				
			|||||||
import * as crypto from "crypto"
 | 
					import * as crypto from "crypto"
 | 
				
			||||||
import * as fs from "fs"
 | 
					import * as fs from "fs"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function checksumFile(hashName: string, path: string) {
 | 
					function checksumFile(hashName: string, path: string): Promise<string> {
 | 
				
			||||||
  return new Promise((resolve, reject) => {
 | 
					  return new Promise((resolve, reject) => {
 | 
				
			||||||
    const hash = crypto.createHash(hashName)
 | 
					    const hash = crypto.createHash(hashName)
 | 
				
			||||||
    const stream = fs.createReadStream(path)
 | 
					    const stream = fs.createReadStream(path)
 | 
				
			||||||
@ -14,7 +14,7 @@ function checksumFile(hashName: string, path: string) {
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const pathExists = async (path: string) => !!(await fs.promises.stat(path).catch(e => false))
 | 
					const pathExists = async (path: string): Promise<boolean> => !!(await fs.promises.stat(path).catch(() => false))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getLintCacheDir = (): string => `${process.env.HOME}/.cache/golangci-lint`
 | 
					const getLintCacheDir = (): string => `${process.env.HOME}/.cache/golangci-lint`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,17 +3,19 @@ import * as tc from "@actions/tool-cache"
 | 
				
			|||||||
import path from "path"
 | 
					import path from "path"
 | 
				
			||||||
import { run as setupGo } from "setup-go/lib/main"
 | 
					import { run as setupGo } from "setup-go/lib/main"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { stringifyVersion, Version } from "./version"
 | 
					import { VersionConfig } from "./version"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The installLint returns path to installed binary of golangci-lint.
 | 
					// The installLint returns path to installed binary of golangci-lint.
 | 
				
			||||||
export async function installLint(ver: Version): Promise<string> {
 | 
					export async function installLint(versionConfig: VersionConfig): Promise<string> {
 | 
				
			||||||
  core.info(`Installing golangci-lint ${stringifyVersion(ver)}...`)
 | 
					  core.info(`Installing golangci-lint ${versionConfig.TargetVersion}...`)
 | 
				
			||||||
  const startedAt = Date.now()
 | 
					  const startedAt = Date.now()
 | 
				
			||||||
  const dirName = `golangci-lint-${ver.major}.${ver.minor}.${ver.patch}-linux-amd64`
 | 
					 | 
				
			||||||
  const assetUrl = `https://github.com/golangci/golangci-lint/releases/download/${stringifyVersion(ver)}/${dirName}.tar.gz`
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const tarGzPath = await tc.downloadTool(assetUrl)
 | 
					  core.info(`Downloading ${versionConfig.AssetURL} ...`)
 | 
				
			||||||
 | 
					  const tarGzPath = await tc.downloadTool(versionConfig.AssetURL)
 | 
				
			||||||
  const extractedDir = await tc.extractTar(tarGzPath, process.env.HOME)
 | 
					  const extractedDir = await tc.extractTar(tarGzPath, process.env.HOME)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const urlParts = versionConfig.AssetURL.split(`/`)
 | 
				
			||||||
 | 
					  const dirName = urlParts[urlParts.length - 1].replace(/\.tar\.gz$/, ``)
 | 
				
			||||||
  const lintPath = path.join(extractedDir, dirName, `golangci-lint`)
 | 
					  const lintPath = path.join(extractedDir, dirName, `golangci-lint`)
 | 
				
			||||||
  core.info(`Installed golangci-lint into ${lintPath} in ${Date.now() - startedAt}ms`)
 | 
					  core.info(`Installed golangci-lint into ${lintPath} in ${Date.now() - startedAt}ms`)
 | 
				
			||||||
  return lintPath
 | 
					  return lintPath
 | 
				
			||||||
 | 
				
			|||||||
@ -9,8 +9,8 @@ import { findLintVersion } from "./version"
 | 
				
			|||||||
const execShellCommand = promisify(exec)
 | 
					const execShellCommand = promisify(exec)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function prepareLint(): Promise<string> {
 | 
					async function prepareLint(): Promise<string> {
 | 
				
			||||||
  const lintVersion = await findLintVersion()
 | 
					  const versionConfig = await findLintVersion()
 | 
				
			||||||
  return await installLint(lintVersion)
 | 
					  return await installLint(versionConfig)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function prepareEnv(): Promise<string> {
 | 
					async function prepareEnv(): Promise<string> {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,24 +1,5 @@
 | 
				
			|||||||
import * as core from "@actions/core"
 | 
					import * as core from "@actions/core"
 | 
				
			||||||
import * as github from "@actions/github"
 | 
					import * as httpm from "@actions/http-client"
 | 
				
			||||||
import { Octokit } from "@actions/github/node_modules/@octokit/rest"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async function performResilientGitHubRequest<T>(opName: string, execFn: () => Promise<Octokit.Response<T>>): Promise<T> {
 | 
					 | 
				
			||||||
  let lastError = ``
 | 
					 | 
				
			||||||
  for (let i = 0; i < 3; i++) {
 | 
					 | 
				
			||||||
    // TODO: configurable params, timeouts, random jitters, exponential back-off, etc
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
      const res = await execFn()
 | 
					 | 
				
			||||||
      if (res.status === 200) {
 | 
					 | 
				
			||||||
        return res.data
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      lastError = `GitHub returned HTTP code ${res.status}`
 | 
					 | 
				
			||||||
    } catch (exc) {
 | 
					 | 
				
			||||||
      lastError = exc.message
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  throw new Error(`failed to execute github operation '${opName}': ${lastError}`)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: make a class
 | 
					// TODO: make a class
 | 
				
			||||||
export type Version = {
 | 
					export type Version = {
 | 
				
			||||||
@ -84,40 +65,61 @@ const getRequestedLintVersion = (): Version => {
 | 
				
			|||||||
  return parsedRequestedLintVersion
 | 
					  return parsedRequestedLintVersion
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function findLintVersion(): Promise<Version> {
 | 
					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...`)
 | 
					  core.info(`Finding needed golangci-lint version...`)
 | 
				
			||||||
  const startedAt = Date.now()
 | 
					  const startedAt = Date.now()
 | 
				
			||||||
  const reqLintVersion = getRequestedLintVersion()
 | 
					  const reqLintVersion = getRequestedLintVersion()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const githubToken = core.getInput(`github-token`, { required: true })
 | 
					  const config = await getConfig()
 | 
				
			||||||
  const octokit = new github.GitHub(githubToken)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // TODO: fetch all pages, not only the first one.
 | 
					  if (!config.MinorVersionToConfig) {
 | 
				
			||||||
  const releasesPage = await performResilientGitHubRequest(`fetch releases of golangci-lint`, function() {
 | 
					    core.warning(JSON.stringify(config))
 | 
				
			||||||
    return octokit.repos.listReleases({ owner: `golangci`, repo: `golangci-lint`, [`per_page`]: 100 })
 | 
					    throw new Error(`invalid config: no MinorVersionToConfig field`)
 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // TODO: use semver and semver.satisfies
 | 
					 | 
				
			||||||
  let latestPatchVersion: number | null = null
 | 
					 | 
				
			||||||
  for (const rel of releasesPage) {
 | 
					 | 
				
			||||||
    const ver = parseVersion(rel.tag_name)
 | 
					 | 
				
			||||||
    if (ver.patch === null) {
 | 
					 | 
				
			||||||
      // < minVersion
 | 
					 | 
				
			||||||
      continue
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (ver.major == reqLintVersion.major && ver.minor == reqLintVersion.minor) {
 | 
					  const versionConfig = config.MinorVersionToConfig[stringifyVersion(reqLintVersion)]
 | 
				
			||||||
      latestPatchVersion = latestPatchVersion !== null ? Math.max(latestPatchVersion, ver.patch) : ver.patch
 | 
					  if (!versionConfig) {
 | 
				
			||||||
    }
 | 
					    throw new Error(`requested golangci-lint version '${stringifyVersion(reqLintVersion)}' doesn't exist`)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (latestPatchVersion === null) {
 | 
					  if (versionConfig.Error) {
 | 
				
			||||||
    throw new Error(
 | 
					    throw new Error(`failed to use requested golangci-lint version '${stringifyVersion(reqLintVersion)}': ${versionConfig.Error}`)
 | 
				
			||||||
      `requested golangci-lint lint version ${stringifyVersion(reqLintVersion)} doesn't exist in list of golangci-lint releases`
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  core.info(
 | 
				
			||||||
 | 
					    `Requested golangci-lint '${stringifyVersion(reqLintVersion)}', using '${versionConfig.TargetVersion}', calculation took ${Date.now() -
 | 
				
			||||||
 | 
					      startedAt}ms`
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
  }
 | 
					  return versionConfig
 | 
				
			||||||
 | 
					 | 
				
			||||||
  const neededVersion = { ...reqLintVersion, patch: latestPatchVersion }
 | 
					 | 
				
			||||||
  core.info(`Calculated needed golangci-lint version ${stringifyVersion(neededVersion)} in ${Date.now() - startedAt}ms`)
 | 
					 | 
				
			||||||
  return neededVersion
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user