import { lint } from 'php-codesniffer'; import { execFileSync } from 'child_process'; import { blame } from 'git-blame-json'; import * as path from 'path'; import * as core from '@actions/core'; import * as github from '@actions/github'; import * as Webhooks from '@octokit/webhooks'; export async function runOnBlame(files: string[]): Promise<void> { try { const options: Record<string, string> = {}; const standard = core.getInput('standard'); if (standard) options.standard = standard; const lintResults = await lint( files, core.getInput('phpcs_path', { required: true }) ); const dontFailOnWarning = core.getInput('fail_on_warnings') == 'false' || core.getInput('fail_on_warnings') === 'off'; if (!lintResults.totals.errors) { if (dontFailOnWarning) return; if (!lintResults.totals.warnings) return; } // blame files and output relevant errors const payload = github.context .payload as Webhooks.WebhookPayloadPullRequest; // get email of author of first commit in PR const authorEmail = execFileSync( 'git', ['--no-pager', 'log', '--format=%ae', `${github.context.sha}^!`], { encoding: 'utf8', windowsHide: true, timeout: 5000 } ).trim(); console.log('PR author email: %s', authorEmail); for (const [file, results] of Object.entries(lintResults.files)) { const blameMap = await blame(file); let headerPrinted = false; for (const message of results.messages) { if (blameMap.get(message.line)?.authorMail === authorEmail) { // that's our line // we simulate checkstyle output to be picked up by problem matched if (!headerPrinted) { console.log(`<file name="${path.relative(process.cwd(), file)}">`); headerPrinted = true; } // output the problem console.log( '<error line="%d" column="%d" severity="%s" message="%s" source="%s"/>', message.line, message.column, message.type.toLowerCase(), message.message, message.source ); // fail if (message.type === 'WARNING' && !dontFailOnWarning) core.setFailed(message.message); else if (message.type === 'ERROR') core.setFailed(message.message); } } } } catch (err) { core.debug(err); core.setFailed(err); } }