Skip to content
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
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
e67ab7b
log error
OmgImAlexis Oct 4, 2019
9390731
Attempt to fix results
OmgImAlexis Oct 4, 2019
7e7541e
Try another fix?
OmgImAlexis Oct 4, 2019
d49445d
Remove need for eslintConfig field in package.json
OmgImAlexis Oct 4, 2019
0ed385f
Throw error if xo field missing in package.json
OmgImAlexis Oct 4, 2019
c433907
Remove need for xo field in package.json
OmgImAlexis Oct 4, 2019
632ce77
Switch to actions v2
OmgImAlexis Oct 4, 2019
2acb50b
Use github actions v2
OmgImAlexis Oct 4, 2019
ccd7696
Switch to package-lock
OmgImAlexis Oct 4, 2019
8321ecc
Lint
OmgImAlexis Oct 4, 2019
f189969
Update current check with annotations
OmgImAlexis Oct 4, 2019
4f7192f
Use env for github token
OmgImAlexis Oct 4, 2019
4e83166
Update check not create
OmgImAlexis Oct 4, 2019
2962bf7
Try and fix xo and add dogfeed action
OmgImAlexis Oct 4, 2019
349c236
Fix lint and add missing dep
OmgImAlexis Oct 4, 2019
7af47b9
Fix xo path.
OmgImAlexis Oct 4, 2019
cdf7e8b
Remove extra try/catch
OmgImAlexis Oct 4, 2019
6618e2a
Split xo and updateCheck into own functions
OmgImAlexis Oct 4, 2019
aa62f53
test lint
OmgImAlexis Oct 4, 2019
2dece1c
ignore xo return code when parsing
OmgImAlexis Oct 4, 2019
99ab77d
Cleanup errors and silence output
OmgImAlexis Oct 4, 2019
c5f0894
log Checklist and fix plural on error/warning
OmgImAlexis Oct 4, 2019
fce7131
Fix plural.
OmgImAlexis Oct 4, 2019
c2148d8
Stringify to show all data
OmgImAlexis Oct 4, 2019
0ae2a09
Fix typo
OmgImAlexis Oct 4, 2019
fa8b634
Ensure we annotate the correct check
OmgImAlexis Oct 4, 2019
2d44e1e
Add logs
OmgImAlexis Oct 4, 2019
cdf4a8b
Log context
OmgImAlexis Oct 4, 2019
495fab9
Print all of checkRuns
OmgImAlexis Oct 4, 2019
a2f86e4
Fix errors and add action input for check name.
OmgImAlexis Oct 7, 2019
8e459b2
Add check for non-matching check name.
OmgImAlexis Oct 7, 2019
3475aaf
Fix non-matching check name
OmgImAlexis Oct 7, 2019
c82e028
Fix check name
OmgImAlexis Oct 7, 2019
7bf0fa1
Fix lint error.
OmgImAlexis Oct 7, 2019
3e052dc
Lint
OmgImAlexis Oct 7, 2019
6d51462
Only return result at end of parsing.
OmgImAlexis Oct 7, 2019
19c6561
Only push the first 50 annotations.
OmgImAlexis Oct 7, 2019
9db6146
Fix xo until PR merges.
OmgImAlexis Oct 12, 2019
65f48c1
Fix typos.
OmgImAlexis Oct 12, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 0 additions & 17 deletions .github/main.workflow

This file was deleted.

42 changes: 42 additions & 0 deletions .github/workflows/push.yml
@@ -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
Comment on lines +6 to +22
Copy link
Owner

@stoe stoe Oct 26, 2019

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

  lint:
    name: Lint code on Node v${{ matrix.node }}
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node: ['10', '12', '13']

    steps:
      - uses: actions/checkout@master
      - uses: actions/setup-node@master
        with:
          node-version: ${{ matrix.node }}
      - run: npm ci
      - run: npm run lint

So it can be "tested" agains other Node versions?

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.


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
292 changes: 184 additions & 108 deletions entrypoint.js
@@ -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
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what this is used for?
@OmgImAlexis, can you explain, please?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a patch for this PR.

xojs/xo#405

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool.
Can you add a comment that it is a workaround for the linked PR and could be removed if it gets merged, please.


// 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();