Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
cf72500b28 | |||
d737e6d962 | |||
8870cfbcd4 | |||
3395f777a4 | |||
04eca20383 | |||
10cbc929b3 |
11
.github/workflows/test.yml
vendored
11
.github/workflows/test.yml
vendored
@ -10,18 +10,17 @@ jobs:
|
||||
build: # make sure build/ci work properly
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- run: |
|
||||
npm install
|
||||
npm run prepare-deps
|
||||
npm run all
|
||||
git diff --exit-code
|
||||
test: # make sure the action works on a clean machine without building
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./
|
||||
with:
|
||||
version: v1.26
|
||||
args: --issues-exit-code=0 ./...
|
||||
working-directory: sample
|
||||
version: v1.28
|
||||
args: --issues-exit-code=0 ./sample/...
|
||||
only-new-issues: true
|
||||
|
@ -37,6 +37,9 @@ jobs:
|
||||
|
||||
# Optional: golangci-lint command line arguments.
|
||||
# args: --issues-exit-code=0
|
||||
|
||||
# Optional: show only new issues if it's a pull request. The default value is `false`.
|
||||
# only-new-issues: true
|
||||
```
|
||||
|
||||
We recommend running this action in a job separate from other jobs (`go test`, etc)
|
||||
@ -55,7 +58,7 @@ The restrictions of annotations are the following:
|
||||
|
||||
The action was implemented with performance in mind:
|
||||
|
||||
1. We cache data by [@actions/cache](https://github.com/actions/cache) between builds: Go build cache, Go modules cache, golangci-lint analysis cache.
|
||||
1. We cache data by [@actions/cache](https://github.com/actions/toolkit/tree/master/packages/cache) between builds: Go build cache, Go modules cache, golangci-lint analysis cache.
|
||||
2. We don't use Docker because image pulling is slow.
|
||||
3. We do as much as we can in parallel, e.g. we download cache, go and golangci-lint binary in parallel.
|
||||
|
||||
@ -71,7 +74,7 @@ For example, in a repository of [golangci-lint](https://github.com/golangci/gola
|
||||
We use JavaScript-based action. We don't use Docker-based action because:
|
||||
|
||||
1. docker pulling is slow currently
|
||||
2. it's easier to use caching from [@actions/cache](https://github.com/actions/cache) until GitHub team hasn't supported reusing actions from actions
|
||||
2. it's easier to use caching from [@actions/cache](https://github.com/actions/toolkit/tree/master/packages/cache)
|
||||
|
||||
Inside our action we perform 3 steps:
|
||||
|
||||
|
10
action.yml
10
action.yml
@ -4,7 +4,7 @@ description: 'Official golangci-lint action with line-attached annotations for f
|
||||
author: 'golangci'
|
||||
inputs:
|
||||
version:
|
||||
description: 'version of golangci-lint to use in form of v1.2.3'
|
||||
description: 'version of golangci-lint to use in form of v1.2'
|
||||
required: true
|
||||
args:
|
||||
description: 'golangci-lint command line arguments'
|
||||
@ -13,6 +13,14 @@ inputs:
|
||||
working-directory:
|
||||
description: 'golangci-lint working directory, default is project root'
|
||||
required: false
|
||||
github-token:
|
||||
description: 'the token is used for fetching patch of a pull request to show only new issues'
|
||||
default: ${{ github.token }}
|
||||
required: true
|
||||
only-new-issues:
|
||||
description: 'if set to true and the action runs on a pull request - the action outputs only newly found issues'
|
||||
default: false
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: 'node12'
|
||||
|
36725
dist/post_run/index.js
vendored
36725
dist/post_run/index.js
vendored
File diff suppressed because it is too large
Load Diff
36725
dist/run/index.js
vendored
36725
dist/run/index.js
vendored
File diff suppressed because it is too large
Load Diff
95
package-lock.json
generated
95
package-lock.json
generated
@ -4,6 +4,20 @@
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@actions/cache": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/cache/-/cache-0.2.1.tgz",
|
||||
"integrity": "sha512-CV2D9zp+d+nL7o6XK/I7vVh350JglPMp/jHi9ppRUkdBHPUeP0UHVUfygZaAs8WmxhhWY1MI0gWah+t0QYu3Fg==",
|
||||
"requires": {
|
||||
"@actions/core": "^1.2.4",
|
||||
"@actions/exec": "^1.0.1",
|
||||
"@actions/glob": "^0.1.0",
|
||||
"@actions/http-client": "^1.0.8",
|
||||
"@actions/io": "^1.0.1",
|
||||
"semver": "^6.1.0",
|
||||
"uuid": "^3.3.3"
|
||||
}
|
||||
},
|
||||
"@actions/core": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.4.tgz",
|
||||
@ -257,6 +271,11 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/tmp": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.0.tgz",
|
||||
"integrity": "sha512-flgpHJjntpBAdJD43ShRosQvNC0ME97DCfGvZEDlAThQmnerRXrLbX6YgzRBQCZTthET9eAWFAMaYP0m0Y4HzQ=="
|
||||
},
|
||||
"@types/uuid": {
|
||||
"version": "3.4.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.9.tgz",
|
||||
@ -441,18 +460,6 @@
|
||||
"resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz",
|
||||
"integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc="
|
||||
},
|
||||
"cache": {
|
||||
"version": "git+https://github.com/golangci/cache.git#3df9f001c2d6c950a3deb6f2c1f88ddc2a609d25",
|
||||
"from": "git+https://github.com/golangci/cache.git",
|
||||
"requires": {
|
||||
"@actions/core": "^1.2.0",
|
||||
"@actions/exec": "^1.0.1",
|
||||
"@actions/glob": "^0.1.0",
|
||||
"@actions/http-client": "^1.0.8",
|
||||
"@actions/io": "^1.0.1",
|
||||
"uuid": "^3.3.3"
|
||||
}
|
||||
},
|
||||
"callsites": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
||||
@ -923,6 +930,17 @@
|
||||
"chardet": "^0.7.0",
|
||||
"iconv-lite": "^0.4.24",
|
||||
"tmp": "^0.0.33"
|
||||
},
|
||||
"dependencies": {
|
||||
"tmp": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"os-tmpdir": "~1.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
@ -996,8 +1014,7 @@
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
||||
"dev": true
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"function-bind": {
|
||||
"version": "1.1.1",
|
||||
@ -1029,7 +1046,6 @@
|
||||
"version": "7.1.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
@ -1125,7 +1141,6 @@
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
@ -1134,8 +1149,7 @@
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"inquirer": {
|
||||
"version": "7.1.0",
|
||||
@ -1625,8 +1639,7 @@
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
||||
"dev": true
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
||||
},
|
||||
"path-key": {
|
||||
"version": "2.0.1",
|
||||
@ -1793,14 +1806,29 @@
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
},
|
||||
"setup-go": {
|
||||
"version": "git+https://github.com/actions/setup-go.git#0f551ac199fb202fc2c3bf3612df37a2f074ef66",
|
||||
"from": "git+https://github.com/actions/setup-go.git",
|
||||
"version": "git+https://github.com/actions/setup-go.git#1616116e1b39417f86ba049745f1a8946d4d00e7",
|
||||
"from": "git+https://github.com/actions/setup-go.git#v2.1.0",
|
||||
"requires": {
|
||||
"@actions/core": "^1.2.2",
|
||||
"@actions/core": "^1.2.3",
|
||||
"@actions/http-client": "^1.0.6",
|
||||
"@actions/io": "^1.0.2",
|
||||
"@actions/tool-cache": "^1.3.3",
|
||||
"@actions/tool-cache": "^1.5.5",
|
||||
"semver": "^6.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/tool-cache": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-1.5.5.tgz",
|
||||
"integrity": "sha512-y/YO37BOaXzOEHpvoGZDLCwvg6XZWQ7Ala4Np4xzrKD1r48mff+K/GAmzXMejnApU7kgqC6lL/aCKTZDCrhdmw==",
|
||||
"requires": {
|
||||
"@actions/core": "^1.2.3",
|
||||
"@actions/exec": "^1.0.0",
|
||||
"@actions/http-client": "^1.0.8",
|
||||
"@actions/io": "^1.0.1",
|
||||
"semver": "^6.1.0",
|
||||
"uuid": "^3.3.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"shebang-command": {
|
||||
@ -2035,12 +2063,21 @@
|
||||
"dev": true
|
||||
},
|
||||
"tmp": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
||||
"dev": true,
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
|
||||
"integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
|
||||
"requires": {
|
||||
"os-tmpdir": "~1.0.2"
|
||||
"rimraf": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
|
11
package.json
11
package.json
@ -6,9 +6,10 @@
|
||||
"main": "dist/main.js",
|
||||
"scripts": {
|
||||
"prepare-setup-go": "cd node_modules/setup-go && npm run build",
|
||||
"prepare-cache": "cd node_modules/cache && npm run build",
|
||||
"prepare-deps": "npm run prepare-setup-go && npm run prepare-cache",
|
||||
"prepare-deps": "npm run prepare-setup-go",
|
||||
"build": "tsc && ncc build -o dist/run/ src/main.ts && ncc build -o dist/post_run/ src/post_main.ts",
|
||||
"watched_build_main": "tsc && ncc build -w -o dist/run/ src/main.ts",
|
||||
"watched_build_post_main": "tsc && ncc build -w -o dist/post_run/ src/post_main.ts",
|
||||
"type-check": "tsc",
|
||||
"lint": "eslint --max-warnings 1 **/*.ts --cache",
|
||||
"lint-fix": "eslint **/*.ts --cache --fix",
|
||||
@ -28,9 +29,11 @@
|
||||
"@actions/exec": "^1.0.1",
|
||||
"@actions/github": "^2.1.1",
|
||||
"@actions/tool-cache": "^1.3.4",
|
||||
"@actions/cache": "^0.2.1",
|
||||
"@types/semver": "^7.1.0",
|
||||
"cache": "git+https://github.com/golangci/cache.git",
|
||||
"setup-go": "git+https://github.com/actions/setup-go.git"
|
||||
"@types/tmp": "^0.2.0",
|
||||
"setup-go": "git+https://github.com/actions/setup-go.git#v2.1.0",
|
||||
"tmp": "^0.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.0.4",
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
// Hash~
|
||||
func Hash(data string) string {
|
||||
retError()
|
||||
retError2()
|
||||
|
||||
h := md5.New()
|
||||
h.Write([]byte(data))
|
||||
@ -19,3 +20,7 @@ func Hash(data string) string {
|
||||
func retError() error {
|
||||
return errors.New("err")
|
||||
}
|
||||
|
||||
func retError2() error {
|
||||
return errors.New("err2")
|
||||
}
|
||||
|
76
src/cache.ts
76
src/cache.ts
@ -1,9 +1,11 @@
|
||||
import * as cache from "@actions/cache"
|
||||
import * as core from "@actions/core"
|
||||
import restore from "cache/lib/restore"
|
||||
import save from "cache/lib/save"
|
||||
import * as crypto from "crypto"
|
||||
import * as fs from "fs"
|
||||
|
||||
import { Events, State } from "./constants"
|
||||
import * as utils from "./utils/actionUtils"
|
||||
|
||||
function checksumFile(hashName: string, path: string): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const hash = crypto.createHash(hashName)
|
||||
@ -52,30 +54,80 @@ async function buildCacheKeys(): Promise<string[]> {
|
||||
}
|
||||
|
||||
export async function restoreCache(): Promise<void> {
|
||||
if (!utils.isValidEvent()) {
|
||||
utils.logWarning(
|
||||
`Event Validation Error: The event type ${process.env[Events.Key]} is not supported because it's not tied to a branch or tag ref.`
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const startedAt = Date.now()
|
||||
|
||||
const keys = await buildCacheKeys()
|
||||
const primaryKey = keys.pop()
|
||||
const restoreKeys = keys.reverse()
|
||||
core.info(`Primary analysis cache key is '${primaryKey}', restore keys are '${restoreKeys.join(` | `)}'`)
|
||||
process.env[`INPUT_RESTORE-KEYS`] = restoreKeys.join(`\n`)
|
||||
process.env.INPUT_KEY = primaryKey
|
||||
|
||||
process.env.INPUT_PATH = getCacheDirs().join(`\n`)
|
||||
|
||||
// Tell golangci-lint to use our cache directory.
|
||||
process.env.GOLANGCI_LINT_CACHE = getLintCacheDir()
|
||||
|
||||
await restore()
|
||||
core.info(`Restored cache for golangci-lint from key '${primaryKey}' in ${Date.now() - startedAt}ms`)
|
||||
if (!primaryKey) {
|
||||
utils.logWarning(`Invalid primary key`)
|
||||
return
|
||||
}
|
||||
core.saveState(State.CachePrimaryKey, primaryKey)
|
||||
try {
|
||||
const cacheKey = await cache.restoreCache(getCacheDirs(), primaryKey, restoreKeys)
|
||||
if (!cacheKey) {
|
||||
core.info(`Cache not found for input keys: ${[primaryKey, ...restoreKeys].join(", ")}`)
|
||||
return
|
||||
}
|
||||
// Store the matched cache key
|
||||
utils.setCacheState(cacheKey)
|
||||
core.info(`Restored cache for golangci-lint from key '${primaryKey}' in ${Date.now() - startedAt}ms`)
|
||||
} catch (error) {
|
||||
if (error.name === cache.ValidationError.name) {
|
||||
throw error
|
||||
} else {
|
||||
core.warning(error.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function saveCache(): Promise<void> {
|
||||
// Validate inputs, this can cause task failure
|
||||
if (!utils.isValidEvent()) {
|
||||
utils.logWarning(
|
||||
`Event Validation Error: The event type ${process.env[Events.Key]} is not supported because it's not tied to a branch or tag ref.`
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const startedAt = Date.now()
|
||||
|
||||
const cacheDirs = getCacheDirs()
|
||||
process.env.INPUT_PATH = cacheDirs.join(`\n`)
|
||||
const primaryKey = core.getState(State.CachePrimaryKey)
|
||||
if (!primaryKey) {
|
||||
utils.logWarning(`Error retrieving key from state.`)
|
||||
return
|
||||
}
|
||||
|
||||
await save()
|
||||
core.info(`Saved cache for golangci-lint from paths '${cacheDirs.join(`, `)}' in ${Date.now() - startedAt}ms`)
|
||||
const state = utils.getCacheState()
|
||||
|
||||
if (utils.isExactKeyMatch(primaryKey, state)) {
|
||||
core.info(`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await cache.saveCache(cacheDirs, primaryKey)
|
||||
core.info(`Saved cache for golangci-lint from paths '${cacheDirs.join(`, `)}' in ${Date.now() - startedAt}ms`)
|
||||
} catch (error) {
|
||||
if (error.name === cache.ValidationError.name) {
|
||||
throw error
|
||||
} else if (error.name === cache.ReserveCacheError.name) {
|
||||
core.info(error.message)
|
||||
} else {
|
||||
core.info(`[warning] ${error.message}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
18
src/constants.ts
Normal file
18
src/constants.ts
Normal file
@ -0,0 +1,18 @@
|
||||
export enum Inputs {
|
||||
Key = "key",
|
||||
Path = "path",
|
||||
RestoreKeys = "restore-keys",
|
||||
}
|
||||
|
||||
export enum State {
|
||||
CachePrimaryKey = "CACHE_KEY",
|
||||
CacheMatchedKey = "CACHE_RESULT",
|
||||
}
|
||||
|
||||
export enum Events {
|
||||
Key = "GITHUB_EVENT_NAME",
|
||||
Push = "push",
|
||||
PullRequest = "pull_request",
|
||||
}
|
||||
|
||||
export const RefKey = "GITHUB_REF"
|
118
src/run.ts
118
src/run.ts
@ -1,7 +1,9 @@
|
||||
import * as core from "@actions/core"
|
||||
import * as github from "@actions/github"
|
||||
import { exec, ExecOptions } from "child_process"
|
||||
import * as fs from "fs"
|
||||
import * as path from "path"
|
||||
import { dir } from "tmp"
|
||||
import { promisify } from "util"
|
||||
|
||||
import { restoreCache, saveCache } from "./cache"
|
||||
@ -9,26 +11,91 @@ import { installGo, installLint } from "./install"
|
||||
import { findLintVersion } from "./version"
|
||||
|
||||
const execShellCommand = promisify(exec)
|
||||
const writeFile = promisify(fs.writeFile)
|
||||
const createTempDir = promisify(dir)
|
||||
|
||||
async function prepareLint(): Promise<string> {
|
||||
const versionConfig = await findLintVersion()
|
||||
return await installLint(versionConfig)
|
||||
}
|
||||
|
||||
async function prepareEnv(): Promise<string> {
|
||||
async function fetchPatch(): Promise<string> {
|
||||
const onlyNewIssues = core.getInput(`only-new-issues`, { required: true }).trim()
|
||||
if (onlyNewIssues !== `false` && onlyNewIssues !== `true`) {
|
||||
throw new Error(`invalid value of "only-new-issues": "${onlyNewIssues}", expected "true" or "false"`)
|
||||
}
|
||||
if (onlyNewIssues === `false`) {
|
||||
return ``
|
||||
}
|
||||
|
||||
const ctx = github.context
|
||||
if (ctx.eventName !== `pull_request`) {
|
||||
core.info(`Not fetching patch for showing only new issues because it's not a pull request context: event name is ${ctx.eventName}`)
|
||||
return ``
|
||||
}
|
||||
const pull = ctx.payload.pull_request
|
||||
if (!pull) {
|
||||
core.warning(`No pull request in context`)
|
||||
return ``
|
||||
}
|
||||
|
||||
const octokit = new github.GitHub(core.getInput(`github-token`, { required: true }))
|
||||
let patch: string
|
||||
try {
|
||||
const patchResp = await octokit.pulls.get({
|
||||
owner: ctx.repo.owner,
|
||||
repo: ctx.repo.repo,
|
||||
[`pull_number`]: pull.number,
|
||||
mediaType: {
|
||||
format: `diff`,
|
||||
},
|
||||
})
|
||||
|
||||
if (patchResp.status !== 200) {
|
||||
core.warning(`failed to fetch pull request patch: response status is ${patchResp.status}`)
|
||||
return `` // don't fail the action, but analyze without patch
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
patch = patchResp.data as any
|
||||
} catch (err) {
|
||||
console.warn(`failed to fetch pull request patch:`, err)
|
||||
return `` // don't fail the action, but analyze without patch
|
||||
}
|
||||
|
||||
try {
|
||||
const tempDir = await createTempDir()
|
||||
const patchPath = path.join(tempDir, "pull.patch")
|
||||
core.info(`Writing patch to ${patchPath}`)
|
||||
await writeFile(patchPath, patch)
|
||||
return patchPath
|
||||
} catch (err) {
|
||||
console.warn(`failed to save pull request patch:`, err)
|
||||
return `` // don't fail the action, but analyze without patch
|
||||
}
|
||||
}
|
||||
|
||||
type Env = {
|
||||
lintPath: string
|
||||
patchPath: string
|
||||
}
|
||||
|
||||
async function prepareEnv(): Promise<Env> {
|
||||
const startedAt = Date.now()
|
||||
|
||||
// Prepare cache, lint and go in parallel.
|
||||
const restoreCachePromise = restoreCache()
|
||||
const prepareLintPromise = prepareLint()
|
||||
const installGoPromise = installGo()
|
||||
const patchPromise = fetchPatch()
|
||||
|
||||
const lintPath = await prepareLintPromise
|
||||
await installGoPromise
|
||||
await restoreCachePromise
|
||||
const patchPath = await patchPromise
|
||||
|
||||
core.info(`Prepared env in ${Date.now() - startedAt}ms`)
|
||||
return lintPath
|
||||
return { lintPath, patchPath }
|
||||
}
|
||||
|
||||
type ExecRes = {
|
||||
@ -45,30 +112,59 @@ const printOutput = (res: ExecRes): void => {
|
||||
}
|
||||
}
|
||||
|
||||
async function runLint(lintPath: string): Promise<void> {
|
||||
async function runLint(lintPath: string, patchPath: string): Promise<void> {
|
||||
const debug = core.getInput(`debug`)
|
||||
if (debug.split(`,`).includes(`cache`)) {
|
||||
const res = await execShellCommand(`${lintPath} cache status`)
|
||||
printOutput(res)
|
||||
}
|
||||
|
||||
const args = core.getInput(`args`)
|
||||
if (args.includes(`-out-format`)) {
|
||||
const userArgs = core.getInput(`args`)
|
||||
const addedArgs: string[] = []
|
||||
|
||||
const userArgNames = new Set<string>()
|
||||
userArgs
|
||||
.split(/\s/)
|
||||
.map(arg => arg.split(`=`)[0])
|
||||
.filter(arg => arg.startsWith(`-`))
|
||||
.forEach(arg => {
|
||||
userArgNames.add(arg.replace(`-`, ``))
|
||||
})
|
||||
|
||||
if (userArgNames.has(`out-format`)) {
|
||||
throw new Error(`please, don't change out-format for golangci-lint: it can be broken in a future`)
|
||||
}
|
||||
addedArgs.push(`--out-format=github-actions`)
|
||||
|
||||
if (patchPath) {
|
||||
if (userArgNames.has(`new`) || userArgNames.has(`new-from-rev`) || userArgNames.has(`new-from-patch`)) {
|
||||
throw new Error(`please, don't specify manually --new* args when requesting only new issues`)
|
||||
}
|
||||
addedArgs.push(`--new-from-patch=${patchPath}`)
|
||||
|
||||
// Override config values.
|
||||
addedArgs.push(`--new=false`)
|
||||
addedArgs.push(`--new-from-rev=`)
|
||||
}
|
||||
|
||||
const workingDirectory = core.getInput(`working-directory`)
|
||||
const cmdArgs: ExecOptions = {}
|
||||
if (workingDirectory != ``) {
|
||||
if (workingDirectory) {
|
||||
if (patchPath) {
|
||||
// TODO: make them compatible
|
||||
throw new Error(`options working-directory and only-new-issues aren't compatible`)
|
||||
}
|
||||
if (!fs.existsSync(workingDirectory) || !fs.lstatSync(workingDirectory).isDirectory()) {
|
||||
throw new Error(`working-directory (${workingDirectory}) was not a path`)
|
||||
}
|
||||
|
||||
if (!userArgNames.has(`path-prefix`)) {
|
||||
addedArgs.push(`--path-prefix=${workingDirectory}`)
|
||||
}
|
||||
cmdArgs.cwd = path.resolve(workingDirectory)
|
||||
}
|
||||
|
||||
const cmd = `${lintPath} run --out-format=github-actions ${args}`.trimRight()
|
||||
core.info(`Running [${cmd}] in [${cmdArgs.cwd}] ...`)
|
||||
const cmd = `${lintPath} run ${addedArgs.join(` `)} ${userArgs}`.trimRight()
|
||||
core.info(`Running [${cmd}] in [${cmdArgs.cwd || ``}] ...`)
|
||||
const startedAt = Date.now()
|
||||
try {
|
||||
const res = await execShellCommand(cmd, cmdArgs)
|
||||
@ -91,8 +187,8 @@ async function runLint(lintPath: string): Promise<void> {
|
||||
|
||||
export async function run(): Promise<void> {
|
||||
try {
|
||||
const lintPath = await core.group(`prepare environment`, prepareEnv)
|
||||
await core.group(`run golangci-lint`, () => runLint(lintPath))
|
||||
const { lintPath, patchPath } = await core.group(`prepare environment`, prepareEnv)
|
||||
await core.group(`run golangci-lint`, () => runLint(lintPath, patchPath))
|
||||
} catch (error) {
|
||||
core.error(`Failed to run: ${error}, ${error.stack}`)
|
||||
core.setFailed(error.message)
|
||||
|
37
src/utils/actionUtils.ts
Normal file
37
src/utils/actionUtils.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import * as core from "@actions/core"
|
||||
|
||||
import { RefKey, State } from "../constants"
|
||||
|
||||
export function isExactKeyMatch(key: string, cacheKey?: string): boolean {
|
||||
return !!(
|
||||
cacheKey &&
|
||||
cacheKey.localeCompare(key, undefined, {
|
||||
sensitivity: "accent",
|
||||
}) === 0
|
||||
)
|
||||
}
|
||||
|
||||
export function setCacheState(state: string): void {
|
||||
core.saveState(State.CacheMatchedKey, state)
|
||||
}
|
||||
|
||||
export function getCacheState(): string | undefined {
|
||||
const cacheKey = core.getState(State.CacheMatchedKey)
|
||||
if (cacheKey) {
|
||||
core.debug(`Cache state/key: ${cacheKey}`)
|
||||
return cacheKey
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
export function logWarning(message: string): void {
|
||||
const warningPrefix = "[warning]"
|
||||
core.info(`${warningPrefix}${message}`)
|
||||
}
|
||||
|
||||
// Cache token authorized for all events that are tied to a ref
|
||||
// See GitHub Context https://help.github.com/actions/automating-your-workflow-with-github-actions/contexts-and-expression-syntax-for-github-actions#github-context
|
||||
export function isValidEvent(): boolean {
|
||||
return RefKey in process.env && Boolean(process.env[RefKey])
|
||||
}
|
Reference in New Issue
Block a user