diff --git a/action.yml b/action.yml index 08d5cf57..0d3d711f 100644 --- a/action.yml +++ b/action.yml @@ -17,6 +17,14 @@ inputs: this should be the tip of the pull request, obtainable by running `git rev-parse ${GITHUB_SHA}^2`" required: true + mode: + description: + required: "Either 'regex' (in which case the linter_output_path file is read + line-by-line and the regex input is used) or 'json' (in which case the + linter_output_path file is expected to be a JSON file containing a single + array of objects, each of which must have the same keys as the capture + groups listed in the description of the regex input)." + default: regex regex: description: "Regex that will match against each line of the file. The following named groups should be captured: diff --git a/lib/main.js b/lib/main.js index fe468539..402aa660 100644 --- a/lib/main.js +++ b/lib/main.js @@ -28,8 +28,24 @@ function getAnnotationLevel() { return val; } } +function makeAnnotation(raw) { + // Chop `./` off the front so that Github will recognize the file path + const normalized_path = raw.filename.replace('./', ''); + const annotation_level = (getAnnotationLevel() == 'warning') ? + 'warning' : + 'failure'; + return { + path: normalized_path, + start_line: raw.lineNumber, + end_line: raw.lineNumber, + start_column: raw.columnNumber, + end_column: raw.columnNumber, + annotation_level: annotation_level, + message: `[${raw.errorCode}] ${raw.errorDesc}`, + }; +} // Regex match each line in the output and turn them into annotations -function parseOutput(output, regex) { +function parseOutputLines(output, regex) { let errors = output.split('\n'); let annotations = []; for (let i = 0; i < errors.length; i++) { @@ -40,27 +56,22 @@ function parseOutput(output, regex) { if (!groups) { throw "No named capture groups in regex match."; } - // Chop `./` off the front so that Github will recognize the file path - const normalized_path = groups.filename.replace('./', ''); - const line = parseInt(groups.lineNumber); - const column = parseInt(groups.columnNumber); - const annotation_level = (getAnnotationLevel() == 'warning') ? - 'warning' : - 'failure'; - const annotation = { - path: normalized_path, - start_line: line, - end_line: line, - start_column: column, - end_column: column, - annotation_level: annotation_level, - message: `[${groups.errorCode}] ${groups.errorDesc}`, - }; + const annotation = makeAnnotation({ + filename: groups.filename, + lineNumber: parseInt(groups.lineNumber), + columnNumber: parseInt(groups.columnNumber), + errorCode: groups.errorCode, + errorDesc: groups.errorDesc, + }); annotations.push(annotation); } } return annotations; } +function parseOutputJSON(output) { + let raw = JSON.parse(output); + return raw.map(makeAnnotation); +} function createCheck(check_name, title, annotations) { return __awaiter(this, void 0, void 0, function* () { const octokit = new github.GitHub(String(GITHUB_TOKEN)); @@ -84,8 +95,18 @@ function run() { const linterOutputPath = core.getInput('linter_output_path'); console.log(`Reading linter output from: ${GITHUB_WORKSPACE}/${linterOutputPath}`); const output = yield fs.promises.readFile(`${GITHUB_WORKSPACE}/${linterOutputPath}`); - const regex = core.getInput('regex'); - const annotations = parseOutput(output.toString(), RegExp(regex)); + const mode = core.getInput('mode'); + let annotations; + if (mode === 'regex') { + const regex = core.getInput('regex'); + annotations = parseOutputLines(output.toString(), RegExp(regex)); + } + else if (mode === 'json') { + annotations = parseOutputJSON(output.toString()); + } + else { + throw `Mode '${mode}' not recognized.`; + } if (annotations.length > 0) { console.log("==============================================================="); console.log("| FAILURES DETECTED |"); diff --git a/src/main.ts b/src/main.ts index 3023550b..3bb239ea 100644 --- a/src/main.ts +++ b/src/main.ts @@ -16,8 +16,33 @@ function getAnnotationLevel(): string { } } +interface RawAnnotation { + filename: string; + lineNumber: number; + columnNumber: number; + errorCode: string; + errorDesc: string; +} + +function makeAnnotation(raw: RawAnnotation): Annotation { + // Chop `./` off the front so that Github will recognize the file path + const normalized_path = raw.filename.replace('./', ''); + const annotation_level = (getAnnotationLevel() == 'warning') ? + 'warning' : + 'failure'; + return { + path: normalized_path, + start_line: raw.lineNumber, + end_line: raw.lineNumber, + start_column: raw.columnNumber, + end_column: raw.columnNumber, + annotation_level: annotation_level, + message: `[${raw.errorCode}] ${raw.errorDesc}`, + } +} + // Regex match each line in the output and turn them into annotations -function parseOutput(output: string, regex: RegExp): Annotation[] { +function parseOutputLines(output: string, regex: RegExp): Annotation[] { let errors = output.split('\n'); let annotations: Annotation[] = []; for (let i = 0; i < errors.length; i++) { @@ -28,22 +53,13 @@ function parseOutput(output: string, regex: RegExp): Annotation[] { if (!groups) { throw "No named capture groups in regex match."; } - // Chop `./` off the front so that Github will recognize the file path - const normalized_path = groups.filename.replace('./', ''); - const line = parseInt(groups.lineNumber); - const column = parseInt(groups.columnNumber); - const annotation_level = (getAnnotationLevel() == 'warning') ? - 'warning' : - 'failure'; - const annotation = { - path: normalized_path, - start_line: line, - end_line: line, - start_column: column, - end_column: column, - annotation_level: annotation_level, - message: `[${groups.errorCode}] ${groups.errorDesc}`, - }; + const annotation = makeAnnotation({ + filename: groups.filename, + lineNumber: parseInt(groups.lineNumber), + columnNumber: parseInt(groups.columnNumber), + errorCode: groups.errorCode, + errorDesc: groups.errorDesc, + }); annotations.push(annotation); } @@ -51,6 +67,11 @@ function parseOutput(output: string, regex: RegExp): Annotation[] { return annotations; } +function parseOutputJSON(output: string): Annotation[] { + let raw: RawAnnotation[] = JSON.parse(output); + return raw.map(makeAnnotation); +} + async function createCheck(check_name: string, title: string, annotations: Annotation[]) { const octokit = new github.GitHub(String(GITHUB_TOKEN)); const req = { @@ -82,8 +103,16 @@ async function run() { const linterOutputPath = core.getInput('linter_output_path'); console.log(`Reading linter output from: ${GITHUB_WORKSPACE}/${linterOutputPath}`) const output = await fs.promises.readFile(`${GITHUB_WORKSPACE}/${linterOutputPath}`); - const regex = core.getInput('regex'); - const annotations = parseOutput(output.toString(), RegExp(regex)); + const mode = core.getInput('mode'); + let annotations: Annotation[]; + if (mode === 'regex') { + const regex = core.getInput('regex'); + annotations = parseOutputLines(output.toString(), RegExp(regex)) + } else if (mode === 'json') { + annotations = parseOutputJSON(output.toString()); + } else { + throw `Mode '${mode}' not recognized.`; + } if (annotations.length > 0) { console.log("===============================================================") console.log("| FAILURES DETECTED |")