Compare commits

..
6 changed files with 55 additions and 70 deletions
+3 -43
View File
@@ -109,42 +109,6 @@ test('prints headline as h1', () => {
expect(text).toContain('<h1>Dependency Review</h1>') expect(text).toContain('<h1>Dependency Review</h1>')
}) })
test('returns minimal summary in case the core.summary is too large for a PR comment', () => {
let changes: Changes = [
createTestChange({name: 'lodash', version: '1.2.3'}),
createTestChange({name: 'colors', version: '2.3.4'}),
createTestChange({name: '@foo/bar', version: '*'})
]
let minSummary: string = summary.addSummaryToSummary(
changes,
emptyInvalidLicenseChanges,
emptyChanges,
scorecard,
defaultConfig
)
// side effect DR report into core.summary as happens in main.ts
summary.addScannedDependencies(changes)
const text = core.summary.stringify()
expect(text).toContain('<h1>Dependency Review</h1>')
expect(minSummary).toContain('# Dependency Review')
expect(text).toContain('❌ 3 vulnerable package(s)')
expect(text).not.toContain('* ❌ 3 vulnerable package(s)')
expect(text).toContain('lodash')
expect(text).toContain('colors')
expect(text).toContain('@foo/bar')
expect(minSummary).toContain('* ❌ 3 vulnerable package(s)')
expect(minSummary).not.toContain('lodash')
expect(minSummary).not.toContain('colors')
expect(minSummary).not.toContain('@foo/bar')
expect(text.length).toBeGreaterThan(minSummary.length)
})
test('returns minimal summary formatted for posting as a PR comment', () => { test('returns minimal summary formatted for posting as a PR comment', () => {
const OLD_ENV = process.env const OLD_ENV = process.env
@@ -232,14 +196,10 @@ test('groups dependencies with empty manifest paths together', () => {
emptyScorecard, emptyScorecard,
defaultConfig defaultConfig
) )
summary.addScannedDependencies(changesWithEmptyManifests) summary.addScannedFiles(changesWithEmptyManifests)
const text = core.summary.stringify() const text = core.summary.stringify()
expect(text).toContain('Unnamed Manifest')
expect(text).toContain('<summary>Unnamed Manifest</summary>') expect(text).toContain('python/dist-info/METADATA')
expect(text).toContain('castore')
expect(text).toContain('connection')
expect(text).toContain('<summary>python/dist-info/METADATA</summary>')
expect(text).toContain('pygments')
}) })
test('does not include status section if nothing was found', () => { test('does not include status section if nothing was found', () => {
Generated Vendored
+23 -12
View File
@@ -705,7 +705,7 @@ function run() {
createScorecardWarnings(scorecard, config); createScorecardWarnings(scorecard, config);
} }
core.setOutput('dependency-changes', JSON.stringify(changes)); core.setOutput('dependency-changes', JSON.stringify(changes));
summary.addScannedDependencies(changes); summary.addScannedFiles(changes);
printScannedDependencies(changes); printScannedDependencies(changes);
// include full summary in output; Actions will truncate if oversized // include full summary in output; Actions will truncate if oversized
let rendered = core.summary.stringify(); let rendered = core.summary.stringify();
@@ -1442,7 +1442,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result; return result;
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.addDeniedToSummary = exports.addSnapshotWarnings = exports.addScorecardToSummary = exports.addScannedDependencies = exports.addLicensesToSummary = exports.addChangeVulnerabilitiesToSummary = exports.addSummaryToSummary = void 0; exports.addDeniedToSummary = exports.addSnapshotWarnings = exports.addScorecardToSummary = exports.addScannedFiles = 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); const utils_1 = __nccwpck_require__(918);
const icons = { const icons = {
@@ -1450,6 +1450,7 @@ const icons = {
cross: '❌', cross: '❌',
warning: '⚠️' warning: '⚠️'
}; };
const MAX_SCANNED_FILES_BYTES = 1048576;
// generates the DR report summmary and caches it to the Action's core.summary. // generates the DR report summmary and caches it to the Action's core.summary.
// returns the DR summary string, ready to be posted as a PR comment if the // returns the DR summary string, ready to be posted as a PR comment if the
// final DR report is too large // final DR report is too large
@@ -1631,19 +1632,29 @@ function formatLicense(license) {
} }
return license; return license;
} }
function addScannedDependencies(changes) { function addScannedFiles(changes) {
const dependencies = (0, utils_1.groupDependenciesByManifest)(changes); const manifests = Array.from((0, utils_1.groupDependenciesByManifest)(changes).keys()).sort();
const manifests = dependencies.keys(); let sf_size = 0;
const summary = core.summary.addHeading('Scanned Manifest Files', 2); let trunc_at = -1;
for (const manifest of manifests) { for (const [index, entry] of manifests.entries()) {
const deps = dependencies.get(manifest); if (sf_size + entry.length >= MAX_SCANNED_FILES_BYTES) {
if (deps) { trunc_at = index;
const dependencyNames = deps.map(dependency => `<li>${dependency.name}@${dependency.version}</li>`); break;
summary.addDetails(manifest, `<ul>${dependencyNames.join('')}</ul>`); }
sf_size += entry.length;
}
if (trunc_at >= 0) {
// truncate the manifests list if it will overflow the summary output
manifests.slice(0, trunc_at);
// if there's room between cutoff size and list size, add a warning
const size_diff = MAX_SCANNED_FILES_BYTES - sf_size;
if (size_diff < 12) {
manifests.push('(truncated)');
} }
} }
core.summary.addHeading('Scanned Files', 2).addList(manifests);
} }
exports.addScannedDependencies = addScannedDependencies; exports.addScannedFiles = addScannedFiles;
function snapshotWarningRecommendation(config, warnings) { function snapshotWarningRecommendation(config, warnings) {
const no_pr_snaps = warnings.includes('No snapshots were found for the head SHA'); const no_pr_snaps = warnings.includes('No snapshots were found for the head SHA');
const retries_disabled = !config.retry_on_snapshot_warnings; const retries_disabled = !config.retry_on_snapshot_warnings;
Generated Vendored
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -143,7 +143,7 @@ async function createSummary(
...licenseIssues.unlicensed ...licenseIssues.unlicensed
] ]
summary.addScannedDependencies(allChanges) summary.addScannedFiles(allChanges)
const text = core.summary.stringify() const text = core.summary.stringify()
await fs.promises.writeFile(path.resolve(tmpDir, fileName), text, { await fs.promises.writeFile(path.resolve(tmpDir, fileName), text, {
+1 -1
View File
@@ -166,7 +166,7 @@ async function run(): Promise<void> {
} }
core.setOutput('dependency-changes', JSON.stringify(changes)) core.setOutput('dependency-changes', JSON.stringify(changes))
summary.addScannedDependencies(changes) summary.addScannedFiles(changes)
printScannedDependencies(changes) printScannedDependencies(changes)
// include full summary in output; Actions will truncate if oversized // include full summary in output; Actions will truncate if oversized
+26 -12
View File
@@ -1,7 +1,7 @@
import * as core from '@actions/core' import * as core from '@actions/core'
import {ConfigurationOptions, Changes, Change, Scorecard} from './schemas'
import {SummaryTableRow} from '@actions/core/lib/summary' import {SummaryTableRow} from '@actions/core/lib/summary'
import {InvalidLicenseChanges, InvalidLicenseChangeTypes} from './licenses' import {InvalidLicenseChanges, InvalidLicenseChangeTypes} from './licenses'
import {Change, Changes, ConfigurationOptions, Scorecard} from './schemas'
import {groupDependenciesByManifest, getManifestsSet, renderUrl} from './utils' import {groupDependenciesByManifest, getManifestsSet, renderUrl} from './utils'
const icons = { const icons = {
@@ -10,6 +10,8 @@ const icons = {
warning: '⚠️' warning: '⚠️'
} }
const MAX_SCANNED_FILES_BYTES = 1048576
// generates the DR report summmary and caches it to the Action's core.summary. // generates the DR report summmary and caches it to the Action's core.summary.
// returns the DR summary string, ready to be posted as a PR comment if the // returns the DR summary string, ready to be posted as a PR comment if the
// final DR report is too large // final DR report is too large
@@ -263,21 +265,33 @@ function formatLicense(license: string | null): string {
return license return license
} }
export function addScannedDependencies(changes: Changes): void { export function addScannedFiles(changes: Changes): void {
const dependencies = groupDependenciesByManifest(changes) const manifests = Array.from(
const manifests = dependencies.keys() groupDependenciesByManifest(changes).keys()
).sort()
const summary = core.summary.addHeading('Scanned Manifest Files', 2) let sf_size = 0
let trunc_at = -1
for (const manifest of manifests) { for (const [index, entry] of manifests.entries()) {
const deps = dependencies.get(manifest) if (sf_size + entry.length >= MAX_SCANNED_FILES_BYTES) {
if (deps) { trunc_at = index
const dependencyNames = deps.map( break
dependency => `<li>${dependency.name}@${dependency.version}</li>` }
) sf_size += entry.length
summary.addDetails(manifest, `<ul>${dependencyNames.join('')}</ul>`) }
if (trunc_at >= 0) {
// truncate the manifests list if it will overflow the summary output
manifests.slice(0, trunc_at)
// if there's room between cutoff size and list size, add a warning
const size_diff = MAX_SCANNED_FILES_BYTES - sf_size
if (size_diff < 12) {
manifests.push('(truncated)')
} }
} }
core.summary.addHeading('Scanned Files', 2).addList(manifests)
} }
function snapshotWarningRecommendation( function snapshotWarningRecommendation(