Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ USAGE
FLAGS
-c, --csv Output in CSV format
-m, --months=<value> [default: 12] The number of months of git history to review
-s, --save Save the committers report as eol.committers.<output>
-s, --save Save the committers report as herodevs.committers.<output>

GLOBAL FLAGS
--json Format output as json.
Expand Down Expand Up @@ -117,7 +117,7 @@ FLAGS
-c, --csv Save output in CSV format (only applies when using --save)
-d, --dir=<value> The directory to scan in order to create a cyclonedx sbom
-f, --file=<value> The file path of an existing cyclonedx sbom to scan for EOL
-s, --save Save the list of purls as eol.purls.<output>
-s, --save Save the list of purls as herodevs.purls.<output>

GLOBAL FLAGS
--json Format output as json.
Expand Down Expand Up @@ -152,7 +152,7 @@ FLAGS
-d, --dir=<value> The directory to scan in order to create a cyclonedx sbom
-f, --file=<value> The file path of an existing cyclonedx sbom to scan for EOL
-p, --purls=<value> The file path of a list of purls to scan for EOL
-s, --save Save the generated report as eol.report.json in the scanned directory
-s, --save Save the generated report as herodevs.report.json in the scanned directory

GLOBAL FLAGS
--json Format output as json.
Expand Down Expand Up @@ -184,7 +184,7 @@ FLAGS
-b, --background Run the scan in the background
-d, --dir=<value> The directory to scan in order to create a cyclonedx sbom
-f, --file=<value> The file path of an existing cyclonedx sbom to scan for EOL
-s, --save Save the generated SBOM as eol.sbom.json in the scanned directory
-s, --save Save the generated SBOM as herodevs.sbom.json in the scanned directory

GLOBAL FLAGS
--json Format output as json.
Expand Down
File renamed without changes.
8 changes: 4 additions & 4 deletions e2e/scan/eol.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { describe, it } from 'node:test';
import { fileURLToPath } from 'node:url';
import { promisify } from 'node:util';
import { runCommand } from '@oclif/test';
import { config } from '../../src/config/constants';
import { config, filenamePrefix } from '../../src/config/constants';

const execAsync = promisify(exec);

Expand Down Expand Up @@ -62,8 +62,8 @@ describe('scan:eol e2e', () => {
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const fixturesDir = path.resolve(__dirname, '../fixtures');
const simplePurls = path.resolve(__dirname, '../fixtures/npm/simple.purls.json');
const simpleSbom = path.join(fixturesDir, 'npm/eol.sbom.json');
const reportPath = path.resolve(fixturesDir, 'eol.report.json');
const simpleSbom = path.join(fixturesDir, `npm/${filenamePrefix}.sbom.json`);
const reportPath = path.resolve(fixturesDir, `${filenamePrefix}.report.json`);
const upToDatePurls = path.resolve(__dirname, '../fixtures/npm/up-to-date.purls.json');
const emptyPurlsPath = path.resolve(__dirname, '../fixtures/npm/empty.purls.json');

Expand Down Expand Up @@ -213,7 +213,7 @@ describe('with directory flag', () => {
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const simpleDir = path.resolve(__dirname, '../fixtures/npm/simple');
const upToDateDir = path.resolve(__dirname, '../fixtures/npm/up-to-date');
const reportPath = path.join(simpleDir, 'eol.report.json');
const reportPath = path.join(simpleDir, `${filenamePrefix}.report.json`);

async function run(cmd: string) {
// Ensure test directory exists and is clean
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"ci": "biome ci",
"ci:fix": "biome check --write",
"clean": "shx rm -rf dist && npm run clean:files && shx rm -rf node_modules",
"clean:files": "shx rm -f eol.**.csv eol.**.json eol.**.text",
"clean:files": "shx rm -f herodevs.**.csv herodevs.**.json herodevs.**.txt",
"dev": "npm run build && ./bin/dev.js",
"dev:debug": "npm run build && DEBUG=oclif:* ./bin/dev.js",
"format": "biome format --write",
Expand Down
9 changes: 5 additions & 4 deletions src/commands/report/committers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Command, Flags } from '@oclif/core';

import fs from 'node:fs';
import path from 'node:path';
import { filenamePrefix } from '../../config/constants.ts';
import {
type CommitEntry,
type ReportData,
Expand Down Expand Up @@ -37,7 +38,7 @@ export default class Committers extends Command {
}),
save: Flags.boolean({
char: 's',
description: 'Save the committers report as eol.committers.<output>',
description: `Save the committers report as ${filenamePrefix}.committers.<output>`,
default: false,
}),
};
Expand All @@ -61,7 +62,7 @@ export default class Committers extends Command {
// JSON mode
if (save) {
try {
fs.writeFileSync(path.resolve('eol.committers.json'), JSON.stringify(reportData, null, 2));
fs.writeFileSync(path.resolve(`${filenamePrefix}.committers.json`), JSON.stringify(reportData, null, 2));
this.log('Report written to json');
} catch (error) {
this.error(`Failed to save JSON report: ${getErrorMessage(error)}`);
Expand All @@ -77,7 +78,7 @@ export default class Committers extends Command {
const csvOutput = formatAsCsv(reportData);
if (save) {
try {
fs.writeFileSync(path.resolve('eol.committers.csv'), csvOutput);
fs.writeFileSync(path.resolve(`${filenamePrefix}.committers.csv`), csvOutput);
this.log('Report written to csv');
} catch (error) {
this.error(`Failed to save CSV report: ${getErrorMessage(error)}`);
Expand All @@ -90,7 +91,7 @@ export default class Committers extends Command {

if (save) {
try {
fs.writeFileSync(path.resolve('eol.committers.txt'), textOutput);
fs.writeFileSync(path.resolve(`${filenamePrefix}.committers.txt`), textOutput);
this.log('Report written to txt');
} catch (error) {
this.error(`Failed to save txt report: ${getErrorMessage(error)}`);
Expand Down
5 changes: 3 additions & 2 deletions src/commands/report/purls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import fs from 'node:fs';
import path from 'node:path';
import { Command, Flags, ux } from '@oclif/core';

import { filenamePrefix } from '../../config/constants.ts';
import { getErrorMessage, isErrnoException } from '../../service/error.svc.ts';
import { extractPurls, getPurlOutput } from '../../service/purls.svc.ts';
import ScanSbom from '../scan/sbom.ts';
Expand All @@ -28,7 +29,7 @@ export default class ReportPurls extends Command {
save: Flags.boolean({
char: 's',
default: false,
description: 'Save the list of purls as eol.purls.<output>',
description: `Save the list of purls as ${filenamePrefix}.purls.<output>`,
}),
csv: Flags.boolean({
char: 'c',
Expand Down Expand Up @@ -57,7 +58,7 @@ export default class ReportPurls extends Command {
if (save) {
try {
const outputFile = csv && !this.jsonEnabled() ? 'csv' : 'json';
const outputPath = path.join(_dirFlag || process.cwd(), `eol.purls.${outputFile}`);
const outputPath = path.join(_dirFlag || process.cwd(), `${filenamePrefix}.purls.${outputFile}`);
const purlOutput = getPurlOutput(purls, outputFile);
fs.writeFileSync(outputPath, purlOutput);

Expand Down
14 changes: 7 additions & 7 deletions src/commands/scan/eol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import terminalLink from 'terminal-link';
import { batchSubmitPurls } from '../../api/nes/nes.client.ts';
import type { ScanResult } from '../../api/types/hd-cli.types.js';
import type { ComponentStatus, InsightsEolScanComponent } from '../../api/types/nes.types.ts';
import { config } from '../../config/constants.ts';
import { config, filenamePrefix } from '../../config/constants.ts';
import type { Sbom } from '../../service/eol/cdx.svc.ts';
import { getErrorMessage, isErrnoException } from '../../service/error.svc.ts';
import { extractPurls, parsePurlsFile } from '../../service/purls.svc.ts';
Expand Down Expand Up @@ -37,7 +37,7 @@ export default class ScanEol extends Command {
save: Flags.boolean({
char: 's',
default: false,
description: 'Save the generated report as eol.report.json in the scanned directory',
description: `Save the generated report as ${filenamePrefix}.report.json in the scanned directory`,
}),
};

Expand All @@ -61,7 +61,7 @@ export default class ScanEol extends Command {
}

this.log('* Use --json to output the report payload');
this.log('* Use --save to save the report to eol.report.json');
this.log(`* Use --save to save the report to ${filenamePrefix}.report.json`);
this.log('* Use --help for more commands or options');
}

Expand Down Expand Up @@ -116,19 +116,19 @@ export default class ScanEol extends Command {

private async saveReport(components: InsightsEolScanComponent[], createdOn?: string): Promise<void> {
const { flags } = await this.parse(ScanEol);
const reportPath = path.join(flags.dir || process.cwd(), 'eol.report.json');
const reportPath = path.join(flags.dir || process.cwd(), `${filenamePrefix}.report.json`);

try {
fs.writeFileSync(reportPath, JSON.stringify({ components, createdOn }, null, 2));
this.log('Report saved to eol.report.json');
this.log(`Report saved to ${filenamePrefix}.report.json`);
} catch (error) {
if (!isErrnoException(error)) {
this.error(`Failed to save report: ${getErrorMessage(error)}`);
}
if (error.code === 'EACCES') {
this.error('Permission denied. Unable to save report to eol.report.json');
this.error(`Permission denied. Unable to save report to ${filenamePrefix}.report.json`);
} else if (error.code === 'ENOSPC') {
this.error('No space left on device. Unable to save report to eol.report.json');
this.error(`No space left on device. Unable to save report to ${filenamePrefix}.report.json`);
} else {
this.error(`Failed to save report: ${getErrorMessage(error)}`);
}
Expand Down
19 changes: 13 additions & 6 deletions src/commands/scan/sbom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { spawn } from 'node:child_process';
import fs from 'node:fs';
import { join, resolve } from 'node:path';
import { Command, Flags, ux } from '@oclif/core';
import { filenamePrefix } from '../../config/constants.ts';
import type { Sbom } from '../../service/eol/cdx.svc.ts';
import { createSbom, validateIsCycloneDxSbom } from '../../service/eol/eol.svc.ts';
import { getErrorMessage } from '../../service/error.svc.ts';
Expand All @@ -25,7 +26,7 @@ export default class ScanSbom extends Command {
save: Flags.boolean({
char: 's',
default: false,
description: 'Save the generated SBOM as eol.sbom.json in the scanned directory',
description: `Save the generated SBOM as ${filenamePrefix}.sbom.json in the scanned directory`,
}),
background: Flags.boolean({
char: 'b',
Expand All @@ -45,14 +46,13 @@ export default class ScanSbom extends Command {
}

static getSbomArgs(flags: Record<string, string>): string[] {
const { dir, file, save, json, background } = flags ?? {};
const { dir, file, background } = flags ?? {};

const sbomArgs = [];
const sbomArgs = ['--json'];

if (file) sbomArgs.push('--file', file);
if (dir) sbomArgs.push('--dir', dir);
// if (save) sbomArgs.push('--save'); // only save if sbom command is used directly with -s flag
if (json) sbomArgs.push('--json');
if (background) sbomArgs.push('--background');

return sbomArgs;
Expand All @@ -75,17 +75,24 @@ export default class ScanSbom extends Command {
const path = dir || process.cwd();
if (file) {
sbom = this._getSbomFromFile(file);
ux.action.stop();
} else if (background) {
this._getSbomInBackground(path);
this.log(`The scan is running in the background. The file will be saved at ${path}/eol.sbom.json`);
this.log(`The scan is running in the background. The file will be saved at ${path}/${filenamePrefix}.sbom.json`);
ux.action.stop();
return;
} else {
sbom = await this._getSbomFromScan(path);
ux.action.stop();
if (save) {
this._saveSbom(path, sbom);
}
}

if (!save) {
this.log(JSON.stringify(sbom, null, 2));
}

return sbom;
}

Expand Down Expand Up @@ -158,7 +165,7 @@ export default class ScanSbom extends Command {

private _saveSbom(dir: string, sbom: Sbom) {
try {
const outputPath = join(dir, 'eol.sbom.json');
const outputPath = join(dir, `${filenamePrefix}.sbom.json`);
fs.writeFileSync(outputPath, JSON.stringify(sbom, null, 2));
if (!this.jsonEnabled()) {
this.log(`SBOM saved to ${outputPath}`);
Expand Down
2 changes: 2 additions & 0 deletions src/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ export const config = {
graphqlPath: process.env.GRAPHQL_PATH || GRAPHQL_PATH,
showVulnCount: true,
};

export const filenamePrefix = 'herodevs';
3 changes: 2 additions & 1 deletion src/service/eol/sbom.worker.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { writeFileSync } from 'node:fs';
import { join } from 'node:path';
import { createBom } from '@cyclonedx/cdxgen';
import { filenamePrefix } from '../../config/constants.ts';
import { SBOM_DEFAULT__OPTIONS } from './cdx.svc.ts';

process.on('uncaughtException', (err) => {
Expand All @@ -18,7 +19,7 @@ try {
const options = JSON.parse(process.argv[2]);
const { path, opts } = options;
const { bomJson } = await createBom(path, { ...SBOM_DEFAULT__OPTIONS, ...opts });
const outputPath = join(path, 'eol.sbom.json');
const outputPath = join(path, `${filenamePrefix}.sbom.json`);
writeFileSync(outputPath, JSON.stringify(bomJson, null, 2));
process.exit(0);
} catch (error: unknown) {
Expand Down
2 changes: 1 addition & 1 deletion src/service/purls.svc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export function extractPurls(sbom: Sbom): string[] {

/**
* Parse a purls file in either JSON or text format, including the format of
* eol.purls.json - { purls: [ 'pkg:npm/express@4.18.2', 'pkg:npm/react@18.3.1' ] }
* herodevs.purls.json - { purls: [ 'pkg:npm/express@4.18.2', 'pkg:npm/react@18.3.1' ] }
* or a text file with one purl per line.
*/
export function parsePurlsFile(purlsFileString: string): string[] {
Expand Down
2 changes: 1 addition & 1 deletion test/service/purls.svc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('formatCsvValue', () => {

describe('parsePurlsFile', () => {
describe('JSON format', () => {
it('should parse eol.purls.json format', () => {
it('should parse herodevs.purls.json format', () => {
const input = JSON.stringify({
purls: ['pkg:npm/@apollo/client@3.13.5', 'pkg:npm/react@18.2.0'],
});
Expand Down
4 changes: 3 additions & 1 deletion test/service/sbom.background.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,7 @@ test('ScanSbom - Run scan in the background', async () => {

ok(parseStub.calledOnce);

ok(logSpy.calledWith('The scan is running in the background. The file will be saved at ./some-dir/eol.sbom.json'));
ok(
logSpy.calledWith('The scan is running in the background. The file will be saved at ./some-dir/herodevs.sbom.json'),
);
});