This repository has been archived by the owner on Jan 4, 2023. It is now read-only.
Updated the new actions toolkit and fixed multiple check issue #17
Closed
Closed
Changes from all commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
e67ab7b
log error
OmgImAlexis 9390731
Attempt to fix results
OmgImAlexis 7e7541e
Try another fix?
OmgImAlexis d49445d
Remove need for eslintConfig field in package.json
OmgImAlexis 0ed385f
Throw error if xo field missing in package.json
OmgImAlexis c433907
Remove need for xo field in package.json
OmgImAlexis 632ce77
Switch to actions v2
OmgImAlexis 2acb50b
Use github actions v2
OmgImAlexis ccd7696
Switch to package-lock
OmgImAlexis 8321ecc
Lint
OmgImAlexis f189969
Update current check with annotations
OmgImAlexis 4f7192f
Use env for github token
OmgImAlexis 4e83166
Update check not create
OmgImAlexis 2962bf7
Try and fix xo and add dogfeed action
OmgImAlexis 349c236
Fix lint and add missing dep
OmgImAlexis 7af47b9
Fix xo path.
OmgImAlexis cdf7e8b
Remove extra try/catch
OmgImAlexis 6618e2a
Split xo and updateCheck into own functions
OmgImAlexis aa62f53
test lint
OmgImAlexis 2dece1c
ignore xo return code when parsing
OmgImAlexis 99ab77d
Cleanup errors and silence output
OmgImAlexis c5f0894
log Checklist and fix plural on error/warning
OmgImAlexis fce7131
Fix plural.
OmgImAlexis c2148d8
Stringify to show all data
OmgImAlexis 0ae2a09
Fix typo
OmgImAlexis fa8b634
Ensure we annotate the correct check
OmgImAlexis 2d44e1e
Add logs
OmgImAlexis cdf4a8b
Log context
OmgImAlexis 495fab9
Print all of checkRuns
OmgImAlexis a2f86e4
Fix errors and add action input for check name.
OmgImAlexis 8e459b2
Add check for non-matching check name.
OmgImAlexis 3475aaf
Fix non-matching check name
OmgImAlexis c82e028
Fix check name
OmgImAlexis 7bf0fa1
Fix lint error.
OmgImAlexis 3e052dc
Lint
OmgImAlexis 6d51462
Only return result at end of parsing.
OmgImAlexis 19c6561
Only push the first 50 annotations.
OmgImAlexis 9db6146
Fix xo until PR merges.
OmgImAlexis 65f48c1
Fix typos.
OmgImAlexis File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
name: Test my code | ||
|
||
on: push | ||
|
||
jobs: | ||
lint: | ||
name: Lint code | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@master | ||
- name: Install deps | ||
uses: docker://node:10-alpine | ||
with: | ||
entrypoint: npm | ||
args: ci | ||
|
||
- name: Lint | ||
uses: docker://node:10-alpine | ||
with: | ||
entrypoint: npm | ||
args: run lint | ||
|
||
test: | ||
name: Test action against own code | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@master | ||
- name: Install deps | ||
uses: docker://node:10-alpine | ||
with: | ||
entrypoint: npm | ||
args: ci | ||
|
||
# uses: stoe/xo-action@master | ||
- name: Lint | ||
uses: omgimalexis/xo-action@master | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
with: | ||
check_name: Test action against own code |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,132 +1,208 @@ | ||
/* eslint-disable camelcase */ | ||
|
||
const {Toolkit} = require('actions-toolkit'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const core = require('@actions/core'); | ||
const exec = require('@actions/exec'); | ||
const github = require('@actions/github'); | ||
|
||
const workspace = process.env.GITHUB_WORKSPACE; | ||
const xoPath = path.join(workspace, 'node_modules', '.bin', 'xo'); | ||
|
||
const fixXoForChildProcess = async () => { | ||
const cliMainPath = path.join(path.dirname(fs.realpathSync(xoPath)), 'cli-main.js') | ||
fs.writeFileSync(cliMainPath, fs.readFileSync(cliMainPath).toString().replace('process.exit(report.errorCount === 0 ? 0 : 1);', 'process.exitCode = (report.errorCount === 0 ? 0 : 1);')); | ||
}; | ||
Comment on lines
+12
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure what this is used for? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a patch for this PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool. |
||
|
||
// Returns results from xo command | ||
const runXo = async options => { | ||
let resultString = ''; | ||
|
||
const parseResults = data => { | ||
resultString += data.toString(); | ||
}; | ||
|
||
await exec.exec(xoPath, options, { | ||
cwd: workspace, | ||
ignoreReturnCode: true, | ||
silent: true, | ||
listeners: { | ||
stdout: parseResults, | ||
stderr: parseResults | ||
} | ||
}); | ||
|
||
Toolkit.run(async tools => { | ||
const pkg = tools.getPackageJSON(); | ||
const {sha: head_sha, action: title} = tools.context; | ||
const annotations = []; | ||
const summary = []; | ||
return JSON.parse(resultString); | ||
}; | ||
|
||
let warningCount = 0; | ||
let errorCount = 0; | ||
let conclusion = 'success'; | ||
let results; | ||
const updateCheck = async ({summary, conclusion, annotations}) => { | ||
const client = new github.GitHub(process.env.GITHUB_TOKEN); | ||
const {sha: head_sha, action: title, ref} = github.context; | ||
const {owner, repo} = github.context.repo; | ||
|
||
try { | ||
const {eslintConfig, xo} = pkg; | ||
const optionsXo = ['--reporter=json']; | ||
const checkRuns = await client.checks | ||
.listForRef({owner, repo, ref}) | ||
.then(({data}) => data.check_runs); | ||
|
||
if (eslintConfig.plugins.includes('prettier') || xo.prettier) { | ||
optionsXo.push('--prettier'); | ||
} | ||
// User must provide the check run's name | ||
// so we can match it up with the correct run | ||
const checkName = core.getInput('check_name') || 'lint'; | ||
let checkNameRun = checkRuns.find(check => check.name === checkName); | ||
|
||
// Bail if we have more than one check and there's no named run found | ||
if (checkRuns.length >= 2 && !checkNameRun) { | ||
core.debug(`Couldn't find a check run matching "${checkName}".`); | ||
|
||
const result = await tools.runInWorkspace('xo', optionsXo, { | ||
reject: false | ||
// Create new check run as we couldn't find a matching one. | ||
await client.checks.create({ | ||
...github.context.repo, | ||
name: checkName, | ||
head_sha, | ||
started_at: new Date().toISOString() | ||
}); | ||
|
||
[...results] = JSON.parse(result.stdout); | ||
} catch (error) { | ||
// XO will respond with a rejected Promise if errors/warnings are found | ||
[...results] = JSON.parse(error.stdout); | ||
} | ||
const checkRuns = await client.checks | ||
.listForRef({owner, repo, ref}) | ||
.then(({data}) => data.check_runs); | ||
|
||
for (const result of results) { | ||
const {filePath, messages} = result; | ||
checkNameRun = checkRuns.find(check => check.name === checkName); | ||
} | ||
|
||
warningCount += Number(result.warningCount); | ||
errorCount += Number(result.errorCount); | ||
const checkRunId = checkRuns.length >= 2 ? checkNameRun.id : checkRuns[0].id; | ||
|
||
await client.checks.update({ | ||
...github.context.repo, | ||
check_run_id: checkRunId, | ||
completed_at: new Date().toISOString(), | ||
conclusion, | ||
output: { | ||
title, | ||
summary: | ||
conclusion === 'success' | ||
? 'XO found no lint in your code.' | ||
: 'XO found lint in your code.', | ||
text: | ||
conclusion === 'success' | ||
? ':tada: XO found no lint in your code.' | ||
: summary.join('\n'), | ||
annotations: annotations.slice(0, 49) | ||
} | ||
}); | ||
}; | ||
|
||
for (const msg of messages) { | ||
const {severity, ruleId: raw_details} = msg; | ||
let {line, endLine, message} = msg; | ||
let annotation_level; | ||
const run = async () => { | ||
try { | ||
const annotations = []; | ||
const summary = []; | ||
|
||
let warningCount = 0; | ||
let errorCount = 0; | ||
let conclusion = 'success'; | ||
|
||
const pkgPath = path.join(workspace, 'package.json'); | ||
const {eslintConfig = {}, xo = {}} = require(pkgPath); | ||
|
||
// Only run with prettier flag if needed | ||
const needsPrettier = | ||
(eslintConfig && | ||
eslintConfig.plugins && | ||
eslintConfig.plugins.includes('prettier')) || | ||
xo.prettier; | ||
|
||
// Fix xo command before running command | ||
await fixXoForChildProcess(); | ||
|
||
// Run xo command | ||
const results = await runXo([ | ||
'--reporter=json', | ||
needsPrettier ? '--prettier' : '' | ||
]).catch(error => { | ||
core.setFailed(error.message); | ||
return []; | ||
}); | ||
|
||
// Sanity checks | ||
message = message.replace(/["']/g, '`'); | ||
if (encodeURI(message).split(/%..|./).length - 1 >= 64) { | ||
message = message.substring(0, 60) + '...'; | ||
for (const result of results) { | ||
const {filePath, messages} = result; | ||
|
||
warningCount += Number(result.warningCount); | ||
errorCount += Number(result.errorCount); | ||
|
||
for (const msg of messages) { | ||
const {severity, ruleId: raw_details} = msg; | ||
let {line, endLine} = msg; | ||
let annotation_level; | ||
|
||
// Sanity checks | ||
let message = msg.message.replace(/["']/g, '`'); | ||
if (encodeURI(message).split(/%..|./).length - 1 >= 64) { | ||
message = message.substring(0, 60) + '...'; | ||
} | ||
|
||
switch (severity) { | ||
case 1: | ||
annotation_level = 'warning'; | ||
break; | ||
case 2: | ||
annotation_level = 'failure'; | ||
break; | ||
default: | ||
annotation_level = 'notice'; | ||
} | ||
|
||
line = line || 1; | ||
if (endLine < line || !endLine) { | ||
endLine = line; | ||
} | ||
// EO - Sanity checks | ||
|
||
annotations.push({ | ||
path: filePath.replace(`${workspace}/`, ''), | ||
start_line: line, | ||
end_line: endLine, | ||
annotation_level, | ||
message, | ||
raw_details | ||
}); | ||
} | ||
} | ||
|
||
switch (severity) { | ||
case 1: | ||
annotation_level = 'warning'; | ||
break; | ||
case 2: | ||
annotation_level = 'failure'; | ||
break; | ||
default: | ||
annotation_level = 'notice'; | ||
} | ||
if (warningCount > 0) { | ||
summary.push( | ||
`:warning: Found ${warningCount} warning${ | ||
warningCount === 1 ? '' : 's' | ||
}.` | ||
); | ||
conclusion = 'neutral'; | ||
} | ||
|
||
line = line || 1; | ||
if (endLine < line || !endLine) { | ||
endLine = line; | ||
} | ||
// EO - Sanity checks | ||
|
||
annotations.push({ | ||
path: filePath.replace(`${tools.workspace}/`, ''), | ||
start_line: line, | ||
end_line: endLine, | ||
annotation_level, | ||
message, | ||
raw_details | ||
}); | ||
if (errorCount > 0) { | ||
summary.push( | ||
`:x: Found ${errorCount} error${errorCount === 1 ? '' : 's'}.` | ||
); | ||
conclusion = 'failure'; | ||
} | ||
} | ||
|
||
if (warningCount > 0) { | ||
summary.push(`:warning: Found ${warningCount} warnings.`); | ||
conclusion = 'neutral'; | ||
} | ||
await updateCheck({summary, conclusion, annotations}).catch(error => { | ||
core.setFailed(error.message); | ||
}); | ||
|
||
if (errorCount > 0) { | ||
summary.push(`:x: Found ${errorCount} errors.`); | ||
conclusion = 'failure'; | ||
} | ||
if (errorCount > 0) { | ||
core.setFailed(':x: Lint errors found!'); | ||
return; | ||
} | ||
|
||
try { | ||
const optionsCreate = { | ||
...tools.context.repo, | ||
name: 'xo', | ||
head_sha, | ||
completed_at: new Date().toISOString(), | ||
conclusion, | ||
output: { | ||
title, | ||
summary: | ||
conclusion === 'success' | ||
? 'XO found no lint in your code.' | ||
: 'XO found lint in your code.', | ||
text: | ||
conclusion === 'success' | ||
? ':tada: XO found no lint in your code.' | ||
: summary.join('\n'), | ||
annotations | ||
} | ||
}; | ||
if (warningCount > 0) { | ||
// Currently doesn't work | ||
// See https://github.com/actions/toolkit/tree/master/packages/core#exit-codes | ||
// core.setNeutral(':x: Lint warnings found.'); | ||
core.warning(':x: Lint warnings found.'); | ||
return; | ||
} | ||
|
||
await tools.github.checks.create(optionsCreate); | ||
// Tools.exit.success(':white_check_mark: No lint found!'); | ||
} catch (error) { | ||
// <Debug> | ||
tools.log.debug(error); | ||
console.trace(error); | ||
console.debug(error.request.request.validate); | ||
// </Debug> | ||
|
||
tools.exit.failure(error); | ||
} | ||
|
||
if (errorCount > 0) { | ||
tools.exit.failure(':x: Lint errors found!'); | ||
return; | ||
} | ||
|
||
if (warningCount > 0) { | ||
tools.exit.neutral(':warning: Lint warnings found!'); | ||
return; | ||
core.setFailed(error.message); | ||
} | ||
}; | ||
|
||
tools.exit.success(':white_check_mark: No lint found!'); | ||
}); | ||
run(); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@OmgImAlexis, what do you think changing this to
So it can be "tested" agains other Node versions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it really make sense to run the linter action against a matrix? If there were test cases to check the linter execution against a matrix it would be fine. But this is actually just ensuring the linter code does not have lint issues, so node versions should not matter, if they do, this would mean code issues and thus require proper test cases.