From 14d92785e4d286f400f7f67b03863abefdfb5d25 Mon Sep 17 00:00:00 2001 From: Naoki Oketani Date: Mon, 9 Dec 2019 12:43:13 +0900 Subject: [PATCH] Set Issue labels by inputs & add unit test (#12) * Set Issue labels by inputs * Add unit test --- .eslintrc.json | 4 +-- README.md | 3 +- __tests__/audit.test.ts | 15 +++++++++ action.yml | 5 ++- dist/index.js | 69 +++++++++++++++++++++++++++++++++++------ src/audit.ts | 30 ++++++++++++++++++ src/main.ts | 21 ++++++------- 7 files changed, 122 insertions(+), 25 deletions(-) create mode 100644 __tests__/audit.test.ts create mode 100644 src/audit.ts diff --git a/.eslintrc.json b/.eslintrc.json index 09d81aa..86a551c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -12,7 +12,7 @@ "import/no-namespace": "off", "no-unused-vars": "off", "@typescript-eslint/no-unused-vars": "error", - "@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}], + "@typescript-eslint/explicit-member-accessibility": "off", "@typescript-eslint/no-require-imports": "error", "@typescript-eslint/array-type": "error", "@typescript-eslint/await-thenable": "error", @@ -55,4 +55,4 @@ "es6": true, "jest/globals": true } - } \ No newline at end of file + } diff --git a/README.md b/README.md index 94b7a76..eb12da4 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,8 @@ GitHub Action to run `npm audit` |Parameter|Required|Default Value|Description| |:--:|:--:|:--:|:--| -|issue_assignees|false|N/A|Issue assignees (separeted by commma)| +|issue_assignees|false|N/A|Issue assignees (separated by commma)| +|issue_labels|false|N/A|Issue labels (separated by commma)| |issue_title|false|npm audit found vulnerabilities|Issue title| |token|true|N/A|GitHub Access Token.
${{ secrets.GITHUB_TOKEN }} is recommended.| diff --git a/__tests__/audit.test.ts b/__tests__/audit.test.ts new file mode 100644 index 0000000..a700516 --- /dev/null +++ b/__tests__/audit.test.ts @@ -0,0 +1,15 @@ +import {Audit} from '../src/audit' + +const audit = new Audit() + +describe('npm audit', () => { + test('finds vulnerabilities', () => { + audit.status = 1 + expect(audit.foundVulnerability()).toBeTruthy() + }) + + test('does not find vulnerabilities', () => { + audit.status = 0 + expect(audit.foundVulnerability()).toBeFalsy() + }) +}) diff --git a/action.yml b/action.yml index c61c1e9..3c2fd68 100644 --- a/action.yml +++ b/action.yml @@ -6,7 +6,10 @@ inputs: description: 'GitHub access token used to create an issue' required: true issue_assignees: - description: 'Issue assignees (separeted by commma)' + description: 'Issue assignees (separated by commma)' + required: false + issue_labels: + description: 'Issue assignees (separated by commma)' required: false issue_title: description: 'Issue title' diff --git a/dist/index.js b/dist/index.js index 35cc0a0..ee552d7 100644 --- a/dist/index.js +++ b/dist/index.js @@ -3012,6 +3012,55 @@ const windowsRelease = release => { module.exports = windowsRelease; +/***/ }), + +/***/ 50: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const child_process_1 = __webpack_require__(129); +class Audit { + constructor() { + this.stdout = ''; + this.status = null; + } + run() { + return __awaiter(this, void 0, void 0, function* () { + const result = child_process_1.spawnSync('npm', ['audit'], { + encoding: 'utf-8' + }); + if (result.error) { + throw result.error; + } + if (result.status === null) { + throw new Error('the subprocess terminated due to a signal.'); + } + if (result.stderr && result.stderr.length > 0) { + throw new Error(result.stderr); + } + this.status = result.status; + this.stdout = result.stdout; + }); + } + foundVulnerability() { + // `npm audit` return 1 when it found vulnerabilities + return this.status === 1; + } +} +exports.Audit = Audit; + + /***/ }), /***/ 87: @@ -4620,18 +4669,14 @@ Object.defineProperty(exports, "__esModule", { value: true }); const core = __importStar(__webpack_require__(470)); const github = __importStar(__webpack_require__(469)); const strip_ansi_1 = __importDefault(__webpack_require__(90)); -const child_process_1 = __webpack_require__(129); +const audit_1 = __webpack_require__(50); function run() { return __awaiter(this, void 0, void 0, function* () { try { - const result = child_process_1.spawnSync('npm', ['audit'], { - encoding: 'utf-8' - }); - if (result.stderr && result.stderr.length > 0) { - throw new Error(result.stderr); - } - core.info(result.stdout); - if (result.status === 0) { + const audit = new audit_1.Audit(); + audit.run(); + core.info(audit.stdout); + if (!audit.foundVulnerability()) { // vulnerabilities are not found return; } @@ -4639,13 +4684,17 @@ function run() { const token = core.getInput('token', { required: true }); const client = new github.GitHub(token); // remove control characters and create a code block - const issueBody = `\`\`\`\n${strip_ansi_1.default(result.stdout)}\n\`\`\``; + const issueBody = `\`\`\`\n${strip_ansi_1.default(audit.stdout)}\n\`\`\``; const issueOptions = { title: core.getInput('issue_title'), body: issueBody, assignees: core .getInput('issue_assignees') .replace(/\s+/g, '') + .split(','), + labels: core + .getInput('issue_labels') + .replace(/\s+/g, '') .split(',') }; const { data: issue } = yield client.issues.create(Object.assign(Object.assign({}, github.context.repo), issueOptions)); diff --git a/src/audit.ts b/src/audit.ts new file mode 100644 index 0000000..13abf25 --- /dev/null +++ b/src/audit.ts @@ -0,0 +1,30 @@ +import {spawnSync, SpawnSyncReturns} from 'child_process' + +export class Audit { + stdout: string = '' + status: number | null = null + + public async run(): Promise { + const result: SpawnSyncReturns = spawnSync('npm', ['audit'], { + encoding: 'utf-8' + }) + + if (result.error) { + throw result.error + } + if (result.status === null) { + throw new Error('the subprocess terminated due to a signal.') + } + if (result.stderr && result.stderr.length > 0) { + throw new Error(result.stderr) + } + + this.status = result.status + this.stdout = result.stdout + } + + public foundVulnerability(): boolean { + // `npm audit` return 1 when it found vulnerabilities + return this.status === 1 + } +} diff --git a/src/main.ts b/src/main.ts index 68ee648..40d7554 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,21 +2,16 @@ import * as core from '@actions/core' import * as github from '@actions/github' import stripAnsi from 'strip-ansi' import Octokit, {IssuesCreateResponse} from '@octokit/rest' -import {spawnSync, SpawnSyncReturns} from 'child_process' +import {Audit} from './audit' async function run(): Promise { try { - const result: SpawnSyncReturns = spawnSync('npm', ['audit'], { - encoding: 'utf-8' - }) + const audit = new Audit() + audit.run() - if (result.stderr && result.stderr.length > 0) { - throw new Error(result.stderr) - } + core.info(audit.stdout) - core.info(result.stdout) - - if (result.status === 0) { + if (!audit.foundVulnerability()) { // vulnerabilities are not found return } @@ -26,13 +21,17 @@ async function run(): Promise { const client: Octokit = new github.GitHub(token) // remove control characters and create a code block - const issueBody = `\`\`\`\n${stripAnsi(result.stdout)}\n\`\`\`` + const issueBody = `\`\`\`\n${stripAnsi(audit.stdout)}\n\`\`\`` const issueOptions = { title: core.getInput('issue_title'), body: issueBody, assignees: core .getInput('issue_assignees') .replace(/\s+/g, '') + .split(','), + labels: core + .getInput('issue_labels') + .replace(/\s+/g, '') .split(',') } const {