Files
rust-audit-check/src/main.ts
T

127 lines
3.8 KiB
TypeScript

import * as os from 'os';
import * as process from 'process';
import * as core from '@actions/core';
import * as github from '@actions/github';
import { Cargo } from '@clechasseur/rs-actions-core';
import * as input from './input';
import * as interfaces from './interfaces';
import * as reporter from './reporter';
async function getData(
ignore: string[] | undefined,
workingDirectory: string,
): Promise<interfaces.Report> {
const cargo = await Cargo.get();
await cargo.findOrInstall('cargo-audit');
let stdout = '';
try {
core.startGroup('Calling cargo-audit (JSON output)');
const commandArray = ['audit'];
for (const item of ignore ?? []) {
commandArray.push('--ignore', item);
}
commandArray.push('--json');
commandArray.push('--file', `${workingDirectory}/Cargo.lock`);
await cargo.call(commandArray, {
ignoreReturnCode: true,
listeners: {
stdout: (buffer) => {
stdout += buffer.toString();
},
},
});
} finally {
// Cool story: `cargo-audit` JSON output is missing the trailing `\n`,
// so the `::endgroup::` annotation from the line below is being
// eaten by it.
// Manually writing the `\n` to denote the `cargo-audit` end
process.stdout.write(os.EOL);
core.endGroup();
}
return JSON.parse(stdout);
}
function removeTrailingSlash(str) {
if (str[str.length - 1] === '/') {
return str.substr(0, str.length - 1);
}
return str;
}
export async function run(actionInput: input.Input): Promise<void> {
const labels = actionInput.new_issue_labels;
const ignore = actionInput.ignore;
const workingDirectory = removeTrailingSlash(actionInput.workingDirectory);
const report = await getData(ignore, workingDirectory);
let shouldReport = false;
if (!report.vulnerabilities.found) {
core.info('No vulnerabilities were found');
} else {
core.warning(`${report.vulnerabilities.count} vulnerabilities found!`);
shouldReport = true;
}
// In `cargo-audit < 0.12` report contained an array of `Warning`.
// In `cargo-audit >= 0.12` it is a JSON object,
// where key is a warning type, and value is an array of `Warning` of that type.
let warnings: Array<interfaces.Warning> = [];
if (Array.isArray(report.warnings)) {
warnings = report.warnings;
} else {
for (const items of Object.values(report.warnings)) {
warnings = warnings.concat(items);
}
}
if (warnings.length === 0) {
core.info('No warnings were found');
} else {
core.warning(`${warnings.length} warnings found!`);
shouldReport = true;
}
if (!shouldReport) {
return;
}
// const octokit = github.getOctokit(actionInput.token, {userAgent: USER_AGENT});
const advisories = report.vulnerabilities.list;
if (
github.context.eventName == 'schedule' ||
github.context.eventName == 'workflow_dispatch'
) {
core.debug(
'Action was triggered on a schedule event, creating an Issues report',
);
await reporter.reportIssues(
actionInput.token,
advisories,
warnings,
labels,
);
} else {
core.debug(
`Action was triggered on a ${github.context.eventName} event, creating a Check report`,
);
await reporter.reportCheck(actionInput.token, advisories, warnings);
}
}
async function main(): Promise<void> {
try {
const actionInput = input.get();
await run(actionInput);
} catch (error) {
core.setFailed((error as Error).message);
}
return;
}
main();