Compare commits
24
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
468485fc8e | ||
|
|
46c9f79a1f | ||
|
|
cd3f55e8f9 | ||
|
|
0515f5cb39 | ||
|
|
2d1d679f58 | ||
|
|
a3563a05bc | ||
|
|
8a20ddbf25 | ||
|
|
2a646668d9 | ||
|
|
60be833ffd | ||
|
|
edc501a219 | ||
|
|
000837f2ac | ||
|
|
89f99d150a | ||
|
|
0ed41eff02 | ||
|
|
dbe70eb550 | ||
|
|
78c7c01396 | ||
|
|
89a5c76329 | ||
|
|
4a6d691283 | ||
|
|
b58d457243 | ||
|
|
cc033856be | ||
|
|
8595e805a5 | ||
|
|
fa10a7f0d6 | ||
|
|
6755d8aa71 | ||
|
|
8ec13c1f01 | ||
|
|
723ec8c0d3 |
@@ -1,4 +1,5 @@
|
|||||||
event.json
|
event.json
|
||||||
|
.ruby-version
|
||||||
|
|
||||||
# Dependency directory
|
# Dependency directory
|
||||||
node_modules
|
node_modules
|
||||||
|
|||||||
+134
-48
@@ -203,6 +203,7 @@ const filter_1 = __nccwpck_require__(8752);
|
|||||||
const licenses_1 = __nccwpck_require__(3247);
|
const licenses_1 = __nccwpck_require__(3247);
|
||||||
const summary = __importStar(__nccwpck_require__(8608));
|
const summary = __importStar(__nccwpck_require__(8608));
|
||||||
const git_refs_1 = __nccwpck_require__(1086);
|
const git_refs_1 = __nccwpck_require__(1086);
|
||||||
|
const utils_1 = __nccwpck_require__(918);
|
||||||
function run() {
|
function run() {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
try {
|
try {
|
||||||
@@ -215,39 +216,22 @@ function run() {
|
|||||||
headRef: refs.head
|
headRef: refs.head
|
||||||
});
|
});
|
||||||
const minSeverity = config.fail_on_severity;
|
const minSeverity = config.fail_on_severity;
|
||||||
let failed = false;
|
const scopedChanges = (0, filter_1.filterChangesByScopes)(config.fail_on_scopes, changes);
|
||||||
const licenses = {
|
const filteredChanges = (0, filter_1.filterOutAllowedAdvisories)(config.allow_ghsas, scopedChanges);
|
||||||
allow: config.allow_licenses,
|
|
||||||
deny: config.deny_licenses
|
|
||||||
};
|
|
||||||
const scopes = config.fail_on_scopes;
|
|
||||||
const scopedChanges = (0, filter_1.filterChangesByScopes)(scopes, changes);
|
|
||||||
const allowedGhsas = config.allow_ghsas || [];
|
|
||||||
const filteredChanges = (0, filter_1.filterOutAllowedAdvisories)(allowedGhsas, scopedChanges);
|
|
||||||
const addedChanges = (0, filter_1.filterChangesBySeverity)(minSeverity, filteredChanges).filter(change => change.change_type === 'added' &&
|
const addedChanges = (0, filter_1.filterChangesBySeverity)(minSeverity, filteredChanges).filter(change => change.change_type === 'added' &&
|
||||||
change.vulnerabilities !== undefined &&
|
change.vulnerabilities !== undefined &&
|
||||||
change.vulnerabilities.length > 0);
|
change.vulnerabilities.length > 0);
|
||||||
const [licenseErrors, unknownLicenses] = (0, licenses_1.getDeniedLicenseChanges)(filteredChanges, licenses);
|
const [licenseErrors, unknownLicenses] = (0, licenses_1.getDeniedLicenseChanges)(filteredChanges, {
|
||||||
|
allow: config.allow_licenses,
|
||||||
|
deny: config.deny_licenses
|
||||||
|
});
|
||||||
summary.addSummaryToSummary(addedChanges, licenseErrors, unknownLicenses);
|
summary.addSummaryToSummary(addedChanges, licenseErrors, unknownLicenses);
|
||||||
if (addedChanges.length > 0) {
|
summary.addChangeVulnerabilitiesToSummary(addedChanges, minSeverity);
|
||||||
for (const change of addedChanges) {
|
|
||||||
printChangeVulnerabilities(change);
|
|
||||||
}
|
|
||||||
failed = true;
|
|
||||||
}
|
|
||||||
summary.addChangeVulnerabilitiesToSummary(addedChanges, minSeverity || '');
|
|
||||||
if (licenseErrors.length > 0) {
|
|
||||||
printLicensesError(licenseErrors);
|
|
||||||
core.setFailed('Dependency review detected incompatible licenses.');
|
|
||||||
}
|
|
||||||
printNullLicenses(unknownLicenses);
|
|
||||||
summary.addLicensesToSummary(licenseErrors, unknownLicenses, config);
|
summary.addLicensesToSummary(licenseErrors, unknownLicenses, config);
|
||||||
if (failed) {
|
summary.addScannedDependencies(changes);
|
||||||
core.setFailed('Dependency review detected vulnerable packages.');
|
printVulnerabilitiesBlock(addedChanges, minSeverity);
|
||||||
}
|
printLicensesBlock(licenseErrors, unknownLicenses);
|
||||||
else {
|
printScannedDependencies(changes);
|
||||||
core.info(`Dependency review did not detect any vulnerable packages with severity level "${minSeverity}" or higher.`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
if (error instanceof request_error_1.RequestError && error.status === 404) {
|
if (error instanceof request_error_1.RequestError && error.status === 404) {
|
||||||
@@ -270,20 +254,37 @@ function run() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function printVulnerabilitiesBlock(addedChanges, minSeverity) {
|
||||||
|
let failed = false;
|
||||||
|
core.group('Vulnerabilities', () => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (addedChanges.length > 0) {
|
||||||
|
for (const change of addedChanges) {
|
||||||
|
printChangeVulnerabilities(change);
|
||||||
|
}
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
if (failed) {
|
||||||
|
core.setFailed('Dependency review detected vulnerable packages.');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
core.info(`Dependency review did not detect any vulnerable packages with severity level "${minSeverity}" or higher.`);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
function printChangeVulnerabilities(change) {
|
function printChangeVulnerabilities(change) {
|
||||||
for (const vuln of change.vulnerabilities) {
|
for (const vuln of change.vulnerabilities) {
|
||||||
core.info(`${ansi_styles_1.default.bold.open}${change.manifest} » ${change.name}@${change.version}${ansi_styles_1.default.bold.close} – ${vuln.advisory_summary} ${renderSeverity(vuln.severity)}`);
|
core.info(`${ansi_styles_1.default.bold.open}${change.manifest} » ${change.name}@${change.version}${ansi_styles_1.default.bold.close} – ${vuln.advisory_summary} ${renderSeverity(vuln.severity)}`);
|
||||||
core.info(` ↪ ${vuln.advisory_url}`);
|
core.info(` ↪ ${vuln.advisory_url}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function renderSeverity(severity) {
|
function printLicensesBlock(licenseErrors, unknownLicenses) {
|
||||||
const color = {
|
core.group('Licenses', () => __awaiter(this, void 0, void 0, function* () {
|
||||||
critical: 'red',
|
if (licenseErrors.length > 0) {
|
||||||
high: 'red',
|
printLicensesError(licenseErrors);
|
||||||
moderate: 'yellow',
|
core.setFailed('Dependency review detected incompatible licenses.');
|
||||||
low: 'grey'
|
}
|
||||||
}[severity];
|
printNullLicenses(unknownLicenses);
|
||||||
return `${ansi_styles_1.default.color[color].open}(${severity} severity)${ansi_styles_1.default.color[color].close}`;
|
}));
|
||||||
}
|
}
|
||||||
function printLicensesError(changes) {
|
function printLicensesError(changes) {
|
||||||
if (changes.length === 0) {
|
if (changes.length === 0) {
|
||||||
@@ -303,6 +304,42 @@ function printNullLicenses(changes) {
|
|||||||
core.info(`${ansi_styles_1.default.bold.open}${change.manifest} » ${change.name}@${change.version}${ansi_styles_1.default.bold.close}`);
|
core.info(`${ansi_styles_1.default.bold.open}${change.manifest} » ${change.name}@${change.version}${ansi_styles_1.default.bold.close}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function renderSeverity(severity) {
|
||||||
|
const color = {
|
||||||
|
critical: 'red',
|
||||||
|
high: 'red',
|
||||||
|
moderate: 'yellow',
|
||||||
|
low: 'grey'
|
||||||
|
}[severity];
|
||||||
|
return `${ansi_styles_1.default.color[color].open}(${severity} severity)${ansi_styles_1.default.color[color].close}`;
|
||||||
|
}
|
||||||
|
function renderScannedDependency(change) {
|
||||||
|
const changeType = change.change_type;
|
||||||
|
if (changeType !== 'added' && changeType !== 'removed') {
|
||||||
|
throw new Error(`Unexpected change type: ${changeType}`);
|
||||||
|
}
|
||||||
|
const color = {
|
||||||
|
added: 'green',
|
||||||
|
removed: 'red'
|
||||||
|
}[changeType];
|
||||||
|
const icon = {
|
||||||
|
added: '+',
|
||||||
|
removed: '-'
|
||||||
|
}[changeType];
|
||||||
|
return `${ansi_styles_1.default.color[color].open}${icon} ${change.manifest}@${change.version}${ansi_styles_1.default.color[color].close}`;
|
||||||
|
}
|
||||||
|
function printScannedDependencies(changes) {
|
||||||
|
core.group('Dependency Changes', () => __awaiter(this, void 0, void 0, function* () {
|
||||||
|
const dependencies = (0, utils_1.groupDependenciesByManifest)(changes);
|
||||||
|
for (const manifestName of dependencies.keys()) {
|
||||||
|
const manifestChanges = dependencies.get(manifestName) || [];
|
||||||
|
core.info(`File: ${ansi_styles_1.default.bold.open}${manifestName}${ansi_styles_1.default.bold.close}`);
|
||||||
|
for (const change of manifestChanges) {
|
||||||
|
core.info(`${renderScannedDependency(change)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
run();
|
run();
|
||||||
|
|
||||||
|
|
||||||
@@ -414,8 +451,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
exports.addLicensesToSummary = exports.addChangeVulnerabilitiesToSummary = exports.addSummaryToSummary = void 0;
|
exports.addScannedDependencies = exports.addLicensesToSummary = exports.addChangeVulnerabilitiesToSummary = exports.addSummaryToSummary = void 0;
|
||||||
const core = __importStar(__nccwpck_require__(2186));
|
const core = __importStar(__nccwpck_require__(2186));
|
||||||
|
const utils_1 = __nccwpck_require__(918);
|
||||||
function addSummaryToSummary(addedPackages, licenseErrors, unknownLicenses) {
|
function addSummaryToSummary(addedPackages, licenseErrors, unknownLicenses) {
|
||||||
core.summary
|
core.summary
|
||||||
.addHeading('Dependency Review')
|
.addHeading('Dependency Review')
|
||||||
@@ -424,7 +462,7 @@ function addSummaryToSummary(addedPackages, licenseErrors, unknownLicenses) {
|
|||||||
exports.addSummaryToSummary = addSummaryToSummary;
|
exports.addSummaryToSummary = addSummaryToSummary;
|
||||||
function addChangeVulnerabilitiesToSummary(addedPackages, severity) {
|
function addChangeVulnerabilitiesToSummary(addedPackages, severity) {
|
||||||
const rows = [];
|
const rows = [];
|
||||||
const manifests = getManifests(addedPackages);
|
const manifests = (0, utils_1.getManifestsSet)(addedPackages);
|
||||||
core.summary
|
core.summary
|
||||||
.addHeading('Vulnerabilities')
|
.addHeading('Vulnerabilities')
|
||||||
.addQuote(`Vulnerabilites were filtered by mininum severity <strong>${severity}</strong>.`);
|
.addQuote(`Vulnerabilites were filtered by mininum severity <strong>${severity}</strong>.`);
|
||||||
@@ -441,16 +479,16 @@ function addChangeVulnerabilitiesToSummary(addedPackages, severity) {
|
|||||||
previous_version === change.version;
|
previous_version === change.version;
|
||||||
if (!sameAsPrevious) {
|
if (!sameAsPrevious) {
|
||||||
rows.push([
|
rows.push([
|
||||||
renderUrl(change.source_repository_url, change.name),
|
(0, utils_1.renderUrl)(change.source_repository_url, change.name),
|
||||||
change.version,
|
change.version,
|
||||||
renderUrl(vuln.advisory_url, vuln.advisory_summary),
|
(0, utils_1.renderUrl)(vuln.advisory_url, vuln.advisory_summary),
|
||||||
vuln.severity
|
vuln.severity
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rows.push([
|
rows.push([
|
||||||
{ data: '', colspan: '2' },
|
{ data: '', colspan: '2' },
|
||||||
renderUrl(vuln.advisory_url, vuln.advisory_summary),
|
(0, utils_1.renderUrl)(vuln.advisory_url, vuln.advisory_summary),
|
||||||
vuln.severity
|
vuln.severity
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -484,13 +522,13 @@ function addLicensesToSummary(licenseErrors, unknownLicenses, config) {
|
|||||||
}
|
}
|
||||||
if (licenseErrors.length > 0) {
|
if (licenseErrors.length > 0) {
|
||||||
const rows = [];
|
const rows = [];
|
||||||
const manifests = getManifests(licenseErrors);
|
const manifests = (0, utils_1.getManifestsSet)(licenseErrors);
|
||||||
core.summary.addHeading('Incompatible Licenses', 3).addSeparator();
|
core.summary.addHeading('Incompatible Licenses', 3).addSeparator();
|
||||||
for (const manifest of manifests) {
|
for (const manifest of manifests) {
|
||||||
core.summary.addHeading(`<em>${manifest}</em>`, 4);
|
core.summary.addHeading(`<em>${manifest}</em>`, 4);
|
||||||
for (const change of licenseErrors.filter(pkg => pkg.manifest === manifest)) {
|
for (const change of licenseErrors.filter(pkg => pkg.manifest === manifest)) {
|
||||||
rows.push([
|
rows.push([
|
||||||
renderUrl(change.source_repository_url, change.name),
|
(0, utils_1.renderUrl)(change.source_repository_url, change.name),
|
||||||
change.version,
|
change.version,
|
||||||
change.license || ''
|
change.license || ''
|
||||||
]);
|
]);
|
||||||
@@ -504,14 +542,14 @@ function addLicensesToSummary(licenseErrors, unknownLicenses, config) {
|
|||||||
core.debug(`found ${unknownLicenses.length} unknown licenses`);
|
core.debug(`found ${unknownLicenses.length} unknown licenses`);
|
||||||
if (unknownLicenses.length > 0) {
|
if (unknownLicenses.length > 0) {
|
||||||
const rows = [];
|
const rows = [];
|
||||||
const manifests = getManifests(unknownLicenses);
|
const manifests = (0, utils_1.getManifestsSet)(unknownLicenses);
|
||||||
core.debug(`found ${manifests.entries.length} manifests for unknown licenses`);
|
core.debug(`found ${manifests.entries.length} manifests for unknown licenses`);
|
||||||
core.summary.addHeading('Unknown Licenses', 3).addSeparator();
|
core.summary.addHeading('Unknown Licenses', 3).addSeparator();
|
||||||
for (const manifest of manifests) {
|
for (const manifest of manifests) {
|
||||||
core.summary.addHeading(`<em>${manifest}</em>`, 4);
|
core.summary.addHeading(`<em>${manifest}</em>`, 4);
|
||||||
for (const change of unknownLicenses.filter(pkg => pkg.manifest === manifest)) {
|
for (const change of unknownLicenses.filter(pkg => pkg.manifest === manifest)) {
|
||||||
rows.push([
|
rows.push([
|
||||||
renderUrl(change.source_repository_url, change.name),
|
(0, utils_1.renderUrl)(change.source_repository_url, change.name),
|
||||||
change.version
|
change.version
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -520,9 +558,49 @@ function addLicensesToSummary(licenseErrors, unknownLicenses, config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.addLicensesToSummary = addLicensesToSummary;
|
exports.addLicensesToSummary = addLicensesToSummary;
|
||||||
function getManifests(changes) {
|
function addScannedDependencies(changes) {
|
||||||
|
const dependencies = (0, utils_1.groupDependenciesByManifest)(changes);
|
||||||
|
const manifests = dependencies.keys();
|
||||||
|
const summary = core.summary
|
||||||
|
.addHeading('Scanned Dependencies')
|
||||||
|
.addRaw(`We scanned ${dependencies.size} manifest files:`);
|
||||||
|
for (const manifest of manifests) {
|
||||||
|
const deps = dependencies.get(manifest);
|
||||||
|
if (deps) {
|
||||||
|
const dependencyNames = deps.map(dependency => `<li>${dependency.name}@${dependency.version}</li>`);
|
||||||
|
summary.addRaw(`<h3>${manifest}</h3><ul>${dependencyNames.join('')}</ul>`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.addScannedDependencies = addScannedDependencies;
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 918:
|
||||||
|
/***/ ((__unused_webpack_module, exports) => {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
exports.renderUrl = exports.getManifestsSet = exports.groupDependenciesByManifest = void 0;
|
||||||
|
function groupDependenciesByManifest(changes) {
|
||||||
|
var _a;
|
||||||
|
const dependencies = new Map();
|
||||||
|
for (const change of changes) {
|
||||||
|
const manifestName = change.manifest;
|
||||||
|
if (dependencies.get(manifestName) === undefined) {
|
||||||
|
dependencies.set(manifestName, []);
|
||||||
|
}
|
||||||
|
(_a = dependencies.get(manifestName)) === null || _a === void 0 ? void 0 : _a.push(change);
|
||||||
|
}
|
||||||
|
return dependencies;
|
||||||
|
}
|
||||||
|
exports.groupDependenciesByManifest = groupDependenciesByManifest;
|
||||||
|
function getManifestsSet(changes) {
|
||||||
return new Set(changes.flatMap(c => c.manifest));
|
return new Set(changes.flatMap(c => c.manifest));
|
||||||
}
|
}
|
||||||
|
exports.getManifestsSet = getManifestsSet;
|
||||||
function renderUrl(url, text) {
|
function renderUrl(url, text) {
|
||||||
if (url) {
|
if (url) {
|
||||||
return `<a href="${url}">${text}</a>`;
|
return `<a href="${url}">${text}</a>`;
|
||||||
@@ -531,6 +609,7 @@ function renderUrl(url, text) {
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
exports.renderUrl = renderUrl;
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
@@ -1609,8 +1688,9 @@ exports.context = new Context.Context();
|
|||||||
* @param token the repo PAT or GITHUB_TOKEN
|
* @param token the repo PAT or GITHUB_TOKEN
|
||||||
* @param options other options to set
|
* @param options other options to set
|
||||||
*/
|
*/
|
||||||
function getOctokit(token, options) {
|
function getOctokit(token, options, ...additionalPlugins) {
|
||||||
return new utils_1.GitHub(utils_1.getOctokitOptions(token, options));
|
const GitHubWithPlugins = utils_1.GitHub.plugin(...additionalPlugins);
|
||||||
|
return new GitHubWithPlugins(utils_1.getOctokitOptions(token, options));
|
||||||
}
|
}
|
||||||
exports.getOctokit = getOctokit;
|
exports.getOctokit = getOctokit;
|
||||||
//# sourceMappingURL=github.js.map
|
//# sourceMappingURL=github.js.map
|
||||||
@@ -15048,6 +15128,9 @@ function filterChangesBySeverity(severity, changes) {
|
|||||||
}
|
}
|
||||||
exports.filterChangesBySeverity = filterChangesBySeverity;
|
exports.filterChangesBySeverity = filterChangesBySeverity;
|
||||||
function filterChangesByScopes(scopes, changes) {
|
function filterChangesByScopes(scopes, changes) {
|
||||||
|
if (scopes === undefined) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
const filteredChanges = changes.filter(change => {
|
const filteredChanges = changes.filter(change => {
|
||||||
// if there is no scope on the change (Enterprise Server API for now), we will assume it is a runtime scope
|
// if there is no scope on the change (Enterprise Server API for now), we will assume it is a runtime scope
|
||||||
const scope = change.scope || 'runtime';
|
const scope = change.scope || 'runtime';
|
||||||
@@ -15057,6 +15140,9 @@ function filterChangesByScopes(scopes, changes) {
|
|||||||
}
|
}
|
||||||
exports.filterChangesByScopes = filterChangesByScopes;
|
exports.filterChangesByScopes = filterChangesByScopes;
|
||||||
function filterOutAllowedAdvisories(ghsas, changes) {
|
function filterOutAllowedAdvisories(ghsas, changes) {
|
||||||
|
if (ghsas === undefined) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
const filteredChanges = changes.filter(change => {
|
const filteredChanges = changes.filter(change => {
|
||||||
const noAdvisories = change.vulnerabilities === undefined ||
|
const noAdvisories = change.vulnerabilities === undefined ||
|
||||||
change.vulnerabilities.length === 0;
|
change.vulnerabilities.length === 0;
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Generated
+31
-31
@@ -1,16 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "dependency-review-action",
|
"name": "dependency-review-action",
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "dependency-review-action",
|
"name": "dependency-review-action",
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.9.1",
|
"@actions/core": "^1.9.1",
|
||||||
"@actions/github": "^5.0.3",
|
"@actions/github": "^5.1.0",
|
||||||
"@octokit/plugin-retry": "^3.0.9",
|
"@octokit/plugin-retry": "^3.0.9",
|
||||||
"@octokit/request-error": "^3.0.1",
|
"@octokit/request-error": "^3.0.1",
|
||||||
"ansi-styles": "^6.1.1",
|
"ansi-styles": "^6.1.1",
|
||||||
@@ -20,12 +20,12 @@
|
|||||||
"zod": "^3.19.1"
|
"zod": "^3.19.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^16.11.59",
|
"@types/node": "^16.11.60",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.38.0",
|
"@typescript-eslint/eslint-plugin": "^5.38.0",
|
||||||
"@typescript-eslint/parser": "^5.38.0",
|
"@typescript-eslint/parser": "^5.38.0",
|
||||||
"@vercel/ncc": "^0.34.0",
|
"@vercel/ncc": "^0.34.0",
|
||||||
"esbuild-register": "^3.3.3",
|
"esbuild-register": "^3.3.3",
|
||||||
"eslint": "^8.23.1",
|
"eslint": "^8.24.0",
|
||||||
"eslint-plugin-github": "^4.3.7",
|
"eslint-plugin-github": "^4.3.7",
|
||||||
"eslint-plugin-jest": "^27.0.4",
|
"eslint-plugin-jest": "^27.0.4",
|
||||||
"jest": "^27.5.1",
|
"jest": "^27.5.1",
|
||||||
@@ -46,9 +46,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/github": {
|
"node_modules/@actions/github": {
|
||||||
"version": "5.0.3",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz",
|
||||||
"integrity": "sha512-myjA/pdLQfhUGLtRZC/J4L1RXOG4o6aYdiEq+zr5wVVKljzbFld+xv10k1FX6IkIJtNxbAq44BdwSNpQ015P0A==",
|
"integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/http-client": "^2.0.1",
|
"@actions/http-client": "^2.0.1",
|
||||||
"@octokit/core": "^3.6.0",
|
"@octokit/core": "^3.6.0",
|
||||||
@@ -705,9 +705,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@humanwhocodes/config-array": {
|
"node_modules/@humanwhocodes/config-array": {
|
||||||
"version": "0.10.4",
|
"version": "0.10.5",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.5.tgz",
|
||||||
"integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==",
|
"integrity": "sha512-XVVDtp+dVvRxMoxSiSfasYaG02VEe1qH5cKgMQJWhol6HwzbcqoCMJi8dAGoYAO57jhUyhI6cWuRiTcRaDaYug==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@humanwhocodes/object-schema": "^1.2.1",
|
"@humanwhocodes/object-schema": "^1.2.1",
|
||||||
@@ -1430,9 +1430,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "16.11.59",
|
"version": "16.11.60",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.59.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.60.tgz",
|
||||||
"integrity": "sha512-6u+36Dj3aDzhfBVUf/mfmc92OEdzQ2kx2jcXGdigfl70E/neV21ZHE6UCz4MDzTRcVqGAM27fk+DLXvyDsn3Jw==",
|
"integrity": "sha512-kYIYa1D1L+HDv5M5RXQeEu1o0FKA6yedZIoyugm/MBPROkLpX4L7HRxMrPVyo8bnvjpW/wDlqFNGzXNMb7AdRw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@types/prettier": {
|
"node_modules/@types/prettier": {
|
||||||
@@ -2776,13 +2776,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint": {
|
"node_modules/eslint": {
|
||||||
"version": "8.23.1",
|
"version": "8.24.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.23.1.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.24.0.tgz",
|
||||||
"integrity": "sha512-w7C1IXCc6fNqjpuYd0yPlcTKKmHlHHktRkzmBPZ+7cvNBQuiNjx0xaMTjAJGCafJhQkrFJooREv0CtrVzmHwqg==",
|
"integrity": "sha512-dWFaPhGhTAiPcCgm3f6LI2MBWbogMnTJzFBbhXVRQDJPkr9pGZvVjlVfXd+vyDcWPA2Ic9L2AXPIQM0+vk/cSQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint/eslintrc": "^1.3.2",
|
"@eslint/eslintrc": "^1.3.2",
|
||||||
"@humanwhocodes/config-array": "^0.10.4",
|
"@humanwhocodes/config-array": "^0.10.5",
|
||||||
"@humanwhocodes/gitignore-to-minimatch": "^1.0.2",
|
"@humanwhocodes/gitignore-to-minimatch": "^1.0.2",
|
||||||
"@humanwhocodes/module-importer": "^1.0.1",
|
"@humanwhocodes/module-importer": "^1.0.1",
|
||||||
"ajv": "^6.10.0",
|
"ajv": "^6.10.0",
|
||||||
@@ -7201,9 +7201,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@actions/github": {
|
"@actions/github": {
|
||||||
"version": "5.0.3",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz",
|
||||||
"integrity": "sha512-myjA/pdLQfhUGLtRZC/J4L1RXOG4o6aYdiEq+zr5wVVKljzbFld+xv10k1FX6IkIJtNxbAq44BdwSNpQ015P0A==",
|
"integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@actions/http-client": "^2.0.1",
|
"@actions/http-client": "^2.0.1",
|
||||||
"@octokit/core": "^3.6.0",
|
"@octokit/core": "^3.6.0",
|
||||||
@@ -7705,9 +7705,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@humanwhocodes/config-array": {
|
"@humanwhocodes/config-array": {
|
||||||
"version": "0.10.4",
|
"version": "0.10.5",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.5.tgz",
|
||||||
"integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==",
|
"integrity": "sha512-XVVDtp+dVvRxMoxSiSfasYaG02VEe1qH5cKgMQJWhol6HwzbcqoCMJi8dAGoYAO57jhUyhI6cWuRiTcRaDaYug==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@humanwhocodes/object-schema": "^1.2.1",
|
"@humanwhocodes/object-schema": "^1.2.1",
|
||||||
@@ -8312,9 +8312,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "16.11.59",
|
"version": "16.11.60",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.59.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.60.tgz",
|
||||||
"integrity": "sha512-6u+36Dj3aDzhfBVUf/mfmc92OEdzQ2kx2jcXGdigfl70E/neV21ZHE6UCz4MDzTRcVqGAM27fk+DLXvyDsn3Jw==",
|
"integrity": "sha512-kYIYa1D1L+HDv5M5RXQeEu1o0FKA6yedZIoyugm/MBPROkLpX4L7HRxMrPVyo8bnvjpW/wDlqFNGzXNMb7AdRw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/prettier": {
|
"@types/prettier": {
|
||||||
@@ -9287,13 +9287,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"eslint": {
|
"eslint": {
|
||||||
"version": "8.23.1",
|
"version": "8.24.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.23.1.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.24.0.tgz",
|
||||||
"integrity": "sha512-w7C1IXCc6fNqjpuYd0yPlcTKKmHlHHktRkzmBPZ+7cvNBQuiNjx0xaMTjAJGCafJhQkrFJooREv0CtrVzmHwqg==",
|
"integrity": "sha512-dWFaPhGhTAiPcCgm3f6LI2MBWbogMnTJzFBbhXVRQDJPkr9pGZvVjlVfXd+vyDcWPA2Ic9L2AXPIQM0+vk/cSQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@eslint/eslintrc": "^1.3.2",
|
"@eslint/eslintrc": "^1.3.2",
|
||||||
"@humanwhocodes/config-array": "^0.10.4",
|
"@humanwhocodes/config-array": "^0.10.5",
|
||||||
"@humanwhocodes/gitignore-to-minimatch": "^1.0.2",
|
"@humanwhocodes/gitignore-to-minimatch": "^1.0.2",
|
||||||
"@humanwhocodes/module-importer": "^1.0.1",
|
"@humanwhocodes/module-importer": "^1.0.1",
|
||||||
"ajv": "^6.10.0",
|
"ajv": "^6.10.0",
|
||||||
|
|||||||
+3
-3
@@ -26,7 +26,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.9.1",
|
"@actions/core": "^1.9.1",
|
||||||
"@actions/github": "^5.0.3",
|
"@actions/github": "^5.1.0",
|
||||||
"@octokit/plugin-retry": "^3.0.9",
|
"@octokit/plugin-retry": "^3.0.9",
|
||||||
"@octokit/request-error": "^3.0.1",
|
"@octokit/request-error": "^3.0.1",
|
||||||
"ansi-styles": "^6.1.1",
|
"ansi-styles": "^6.1.1",
|
||||||
@@ -36,12 +36,12 @@
|
|||||||
"zod": "^3.19.1"
|
"zod": "^3.19.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^16.11.59",
|
"@types/node": "^16.11.60",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.38.0",
|
"@typescript-eslint/eslint-plugin": "^5.38.0",
|
||||||
"@typescript-eslint/parser": "^5.38.0",
|
"@typescript-eslint/parser": "^5.38.0",
|
||||||
"@vercel/ncc": "^0.34.0",
|
"@vercel/ncc": "^0.34.0",
|
||||||
"esbuild-register": "^3.3.3",
|
"esbuild-register": "^3.3.3",
|
||||||
"eslint": "^8.23.1",
|
"eslint": "^8.24.0",
|
||||||
"eslint-plugin-github": "^4.3.7",
|
"eslint-plugin-github": "^4.3.7",
|
||||||
"eslint-plugin-jest": "^27.0.4",
|
"eslint-plugin-jest": "^27.0.4",
|
||||||
"jest": "^27.5.1",
|
"jest": "^27.5.1",
|
||||||
|
|||||||
+10
-2
@@ -35,9 +35,13 @@ export function filterChangesBySeverity(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function filterChangesByScopes(
|
export function filterChangesByScopes(
|
||||||
scopes: Scope[],
|
scopes: Scope[] | undefined,
|
||||||
changes: Changes
|
changes: Changes
|
||||||
): Changes {
|
): Changes {
|
||||||
|
if (scopes === undefined) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
const filteredChanges = changes.filter(change => {
|
const filteredChanges = changes.filter(change => {
|
||||||
// if there is no scope on the change (Enterprise Server API for now), we will assume it is a runtime scope
|
// if there is no scope on the change (Enterprise Server API for now), we will assume it is a runtime scope
|
||||||
const scope = change.scope || 'runtime'
|
const scope = change.scope || 'runtime'
|
||||||
@@ -48,9 +52,13 @@ export function filterChangesByScopes(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function filterOutAllowedAdvisories(
|
export function filterOutAllowedAdvisories(
|
||||||
ghsas: string[],
|
ghsas: string[] | undefined,
|
||||||
changes: Changes
|
changes: Changes
|
||||||
): Changes {
|
): Changes {
|
||||||
|
if (ghsas === undefined) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
const filteredChanges = changes.filter(change => {
|
const filteredChanges = changes.filter(change => {
|
||||||
const noAdvisories =
|
const noAdvisories =
|
||||||
change.vulnerabilities === undefined ||
|
change.vulnerabilities === undefined ||
|
||||||
|
|||||||
+102
-54
@@ -3,7 +3,7 @@ import * as dependencyGraph from './dependency-graph'
|
|||||||
import * as github from '@actions/github'
|
import * as github from '@actions/github'
|
||||||
import styles from 'ansi-styles'
|
import styles from 'ansi-styles'
|
||||||
import {RequestError} from '@octokit/request-error'
|
import {RequestError} from '@octokit/request-error'
|
||||||
import {Change, Severity, Scope} from './schemas'
|
import {Change, Severity, Changes} from './schemas'
|
||||||
import {readConfig} from '../src/config'
|
import {readConfig} from '../src/config'
|
||||||
import {
|
import {
|
||||||
filterChangesBySeverity,
|
filterChangesBySeverity,
|
||||||
@@ -14,6 +14,8 @@ import {getDeniedLicenseChanges} from './licenses'
|
|||||||
import * as summary from './summary'
|
import * as summary from './summary'
|
||||||
import {getRefs} from './git-refs'
|
import {getRefs} from './git-refs'
|
||||||
|
|
||||||
|
import {groupDependenciesByManifest} from './utils'
|
||||||
|
|
||||||
async function run(): Promise<void> {
|
async function run(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const config = readConfig()
|
const config = readConfig()
|
||||||
@@ -26,27 +28,15 @@ async function run(): Promise<void> {
|
|||||||
headRef: refs.head
|
headRef: refs.head
|
||||||
})
|
})
|
||||||
|
|
||||||
const minSeverity = config.fail_on_severity
|
const minSeverity = config.fail_on_severity as Severity
|
||||||
let failed = false
|
const scopedChanges = filterChangesByScopes(config.fail_on_scopes, changes)
|
||||||
|
|
||||||
const licenses = {
|
|
||||||
allow: config.allow_licenses,
|
|
||||||
deny: config.deny_licenses
|
|
||||||
}
|
|
||||||
|
|
||||||
const scopes = config.fail_on_scopes
|
|
||||||
|
|
||||||
const scopedChanges = filterChangesByScopes(scopes as Scope[], changes)
|
|
||||||
|
|
||||||
const allowedGhsas: string[] = config.allow_ghsas || []
|
|
||||||
|
|
||||||
const filteredChanges = filterOutAllowedAdvisories(
|
const filteredChanges = filterOutAllowedAdvisories(
|
||||||
allowedGhsas,
|
config.allow_ghsas,
|
||||||
scopedChanges
|
scopedChanges
|
||||||
)
|
)
|
||||||
|
|
||||||
const addedChanges = filterChangesBySeverity(
|
const addedChanges = filterChangesBySeverity(
|
||||||
minSeverity as Severity,
|
minSeverity,
|
||||||
filteredChanges
|
filteredChanges
|
||||||
).filter(
|
).filter(
|
||||||
change =>
|
change =>
|
||||||
@@ -57,36 +47,20 @@ async function run(): Promise<void> {
|
|||||||
|
|
||||||
const [licenseErrors, unknownLicenses] = getDeniedLicenseChanges(
|
const [licenseErrors, unknownLicenses] = getDeniedLicenseChanges(
|
||||||
filteredChanges,
|
filteredChanges,
|
||||||
licenses
|
{
|
||||||
|
allow: config.allow_licenses,
|
||||||
|
deny: config.deny_licenses
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
summary.addSummaryToSummary(addedChanges, licenseErrors, unknownLicenses)
|
summary.addSummaryToSummary(addedChanges, licenseErrors, unknownLicenses)
|
||||||
|
summary.addChangeVulnerabilitiesToSummary(addedChanges, minSeverity)
|
||||||
if (addedChanges.length > 0) {
|
|
||||||
for (const change of addedChanges) {
|
|
||||||
printChangeVulnerabilities(change)
|
|
||||||
}
|
|
||||||
failed = true
|
|
||||||
}
|
|
||||||
|
|
||||||
summary.addChangeVulnerabilitiesToSummary(addedChanges, minSeverity || '')
|
|
||||||
|
|
||||||
if (licenseErrors.length > 0) {
|
|
||||||
printLicensesError(licenseErrors)
|
|
||||||
core.setFailed('Dependency review detected incompatible licenses.')
|
|
||||||
}
|
|
||||||
|
|
||||||
printNullLicenses(unknownLicenses)
|
|
||||||
|
|
||||||
summary.addLicensesToSummary(licenseErrors, unknownLicenses, config)
|
summary.addLicensesToSummary(licenseErrors, unknownLicenses, config)
|
||||||
|
summary.addScannedDependencies(changes)
|
||||||
|
|
||||||
if (failed) {
|
printVulnerabilitiesBlock(addedChanges, minSeverity)
|
||||||
core.setFailed('Dependency review detected vulnerable packages.')
|
printLicensesBlock(licenseErrors, unknownLicenses)
|
||||||
} else {
|
printScannedDependencies(changes)
|
||||||
core.info(
|
|
||||||
`Dependency review did not detect any vulnerable packages with severity level "${minSeverity}" or higher.`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof RequestError && error.status === 404) {
|
if (error instanceof RequestError && error.status === 404) {
|
||||||
core.setFailed(
|
core.setFailed(
|
||||||
@@ -108,6 +82,29 @@ async function run(): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function printVulnerabilitiesBlock(
|
||||||
|
addedChanges: Change[],
|
||||||
|
minSeverity: Severity
|
||||||
|
): void {
|
||||||
|
let failed = false
|
||||||
|
core.group('Vulnerabilities', async () => {
|
||||||
|
if (addedChanges.length > 0) {
|
||||||
|
for (const change of addedChanges) {
|
||||||
|
printChangeVulnerabilities(change)
|
||||||
|
}
|
||||||
|
failed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failed) {
|
||||||
|
core.setFailed('Dependency review detected vulnerable packages.')
|
||||||
|
} else {
|
||||||
|
core.info(
|
||||||
|
`Dependency review did not detect any vulnerable packages with severity level "${minSeverity}" or higher.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function printChangeVulnerabilities(change: Change): void {
|
function printChangeVulnerabilities(change: Change): void {
|
||||||
for (const vuln of change.vulnerabilities) {
|
for (const vuln of change.vulnerabilities) {
|
||||||
core.info(
|
core.info(
|
||||||
@@ -121,18 +118,17 @@ function printChangeVulnerabilities(change: Change): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderSeverity(
|
function printLicensesBlock(
|
||||||
severity: 'critical' | 'high' | 'moderate' | 'low'
|
licenseErrors: Change[],
|
||||||
): string {
|
unknownLicenses: Change[]
|
||||||
const color = (
|
): void {
|
||||||
{
|
core.group('Licenses', async () => {
|
||||||
critical: 'red',
|
if (licenseErrors.length > 0) {
|
||||||
high: 'red',
|
printLicensesError(licenseErrors)
|
||||||
moderate: 'yellow',
|
core.setFailed('Dependency review detected incompatible licenses.')
|
||||||
low: 'grey'
|
}
|
||||||
} as const
|
printNullLicenses(unknownLicenses)
|
||||||
)[severity]
|
})
|
||||||
return `${styles.color[color].open}(${severity} severity)${styles.color[color].close}`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function printLicensesError(changes: Change[]): void {
|
function printLicensesError(changes: Change[]): void {
|
||||||
@@ -161,4 +157,56 @@ function printNullLicenses(changes: Change[]): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderSeverity(
|
||||||
|
severity: 'critical' | 'high' | 'moderate' | 'low'
|
||||||
|
): string {
|
||||||
|
const color = (
|
||||||
|
{
|
||||||
|
critical: 'red',
|
||||||
|
high: 'red',
|
||||||
|
moderate: 'yellow',
|
||||||
|
low: 'grey'
|
||||||
|
} as const
|
||||||
|
)[severity]
|
||||||
|
return `${styles.color[color].open}(${severity} severity)${styles.color[color].close}`
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderScannedDependency(change: Change): string {
|
||||||
|
const changeType: string = change.change_type
|
||||||
|
|
||||||
|
if (changeType !== 'added' && changeType !== 'removed') {
|
||||||
|
throw new Error(`Unexpected change type: ${changeType}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const color = (
|
||||||
|
{
|
||||||
|
added: 'green',
|
||||||
|
removed: 'red'
|
||||||
|
} as const
|
||||||
|
)[changeType]
|
||||||
|
|
||||||
|
const icon = (
|
||||||
|
{
|
||||||
|
added: '+',
|
||||||
|
removed: '-'
|
||||||
|
} as const
|
||||||
|
)[changeType]
|
||||||
|
|
||||||
|
return `${styles.color[color].open}${icon} ${change.manifest}@${change.version}${styles.color[color].close}`
|
||||||
|
}
|
||||||
|
|
||||||
|
function printScannedDependencies(changes: Changes): void {
|
||||||
|
core.group('Dependency Changes', async () => {
|
||||||
|
const dependencies = groupDependenciesByManifest(changes)
|
||||||
|
|
||||||
|
for (const manifestName of dependencies.keys()) {
|
||||||
|
const manifestChanges = dependencies.get(manifestName) || []
|
||||||
|
core.info(`File: ${styles.bold.open}${manifestName}${styles.bold.close}`)
|
||||||
|
for (const change of manifestChanges) {
|
||||||
|
core.info(`${renderScannedDependency(change)}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
run()
|
run()
|
||||||
|
|||||||
+19
-11
@@ -1,6 +1,7 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import {ConfigurationOptions, Change, Changes} from './schemas'
|
import {ConfigurationOptions, Change, Changes} from './schemas'
|
||||||
import {SummaryTableRow} from '@actions/core/lib/summary'
|
import {SummaryTableRow} from '@actions/core/lib/summary'
|
||||||
|
import {groupDependenciesByManifest, getManifestsSet, renderUrl} from './utils'
|
||||||
|
|
||||||
export function addSummaryToSummary(
|
export function addSummaryToSummary(
|
||||||
addedPackages: Changes,
|
addedPackages: Changes,
|
||||||
@@ -20,7 +21,7 @@ export function addChangeVulnerabilitiesToSummary(
|
|||||||
): void {
|
): void {
|
||||||
const rows: SummaryTableRow[] = []
|
const rows: SummaryTableRow[] = []
|
||||||
|
|
||||||
const manifests = getManifests(addedPackages)
|
const manifests = getManifestsSet(addedPackages)
|
||||||
|
|
||||||
core.summary
|
core.summary
|
||||||
.addHeading('Vulnerabilities')
|
.addHeading('Vulnerabilities')
|
||||||
@@ -99,7 +100,7 @@ export function addLicensesToSummary(
|
|||||||
|
|
||||||
if (licenseErrors.length > 0) {
|
if (licenseErrors.length > 0) {
|
||||||
const rows: SummaryTableRow[] = []
|
const rows: SummaryTableRow[] = []
|
||||||
const manifests = getManifests(licenseErrors)
|
const manifests = getManifestsSet(licenseErrors)
|
||||||
|
|
||||||
core.summary.addHeading('Incompatible Licenses', 3).addSeparator()
|
core.summary.addHeading('Incompatible Licenses', 3).addSeparator()
|
||||||
|
|
||||||
@@ -125,7 +126,7 @@ export function addLicensesToSummary(
|
|||||||
|
|
||||||
if (unknownLicenses.length > 0) {
|
if (unknownLicenses.length > 0) {
|
||||||
const rows: SummaryTableRow[] = []
|
const rows: SummaryTableRow[] = []
|
||||||
const manifests = getManifests(unknownLicenses)
|
const manifests = getManifestsSet(unknownLicenses)
|
||||||
|
|
||||||
core.debug(
|
core.debug(
|
||||||
`found ${manifests.entries.length} manifests for unknown licenses`
|
`found ${manifests.entries.length} manifests for unknown licenses`
|
||||||
@@ -150,14 +151,21 @@ export function addLicensesToSummary(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getManifests(changes: Changes): Set<string> {
|
export function addScannedDependencies(changes: Changes): void {
|
||||||
return new Set(changes.flatMap(c => c.manifest))
|
const dependencies = groupDependenciesByManifest(changes)
|
||||||
}
|
const manifests = dependencies.keys()
|
||||||
|
|
||||||
function renderUrl(url: string | null, text: string): string {
|
const summary = core.summary
|
||||||
if (url) {
|
.addHeading('Scanned Dependencies')
|
||||||
return `<a href="${url}">${text}</a>`
|
.addRaw(`We scanned ${dependencies.size} manifest files:`)
|
||||||
} else {
|
|
||||||
return text
|
for (const manifest of manifests) {
|
||||||
|
const deps = dependencies.get(manifest)
|
||||||
|
if (deps) {
|
||||||
|
const dependencyNames = deps.map(
|
||||||
|
dependency => `<li>${dependency.name}@${dependency.version}</li>`
|
||||||
|
)
|
||||||
|
summary.addRaw(`<h3>${manifest}</h3><ul>${dependencyNames.join('')}</ul>`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import {Changes} from './schemas'
|
||||||
|
|
||||||
|
export function groupDependenciesByManifest(
|
||||||
|
changes: Changes
|
||||||
|
): Map<string, Changes> {
|
||||||
|
const dependencies: Map<string, Changes> = new Map()
|
||||||
|
for (const change of changes) {
|
||||||
|
const manifestName = change.manifest
|
||||||
|
|
||||||
|
if (dependencies.get(manifestName) === undefined) {
|
||||||
|
dependencies.set(manifestName, [])
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies.get(manifestName)?.push(change)
|
||||||
|
}
|
||||||
|
|
||||||
|
return dependencies
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getManifestsSet(changes: Changes): Set<string> {
|
||||||
|
return new Set(changes.flatMap(c => c.manifest))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderUrl(url: string | null, text: string): string {
|
||||||
|
if (url) {
|
||||||
|
return `<a href="${url}">${text}</a>`
|
||||||
|
} else {
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user