Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: more logs & configurable log level #1131

Merged
merged 10 commits into from
Dec 8, 2023
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
6 changes: 6 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ module.exports = {
],
parserOptions: {
project: './tsconfig.json'
},
rules: {
/* @see https://typescript-eslint.io/rules/unbound-method/ */
'@typescript-eslint/unbound-method': ['error', {
ignoreStatic: true
}]
}
},
{
Expand Down
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/ValidationError-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ Steps to reproduce the behavior:
<!-- upload the complete output to this issue, or a pastebin of you choice and put the link here. -->
4. Expected result:
<!-- run the original call again
with parameters `--no-validate --output-reproducible --output-file=-`,
then upload the output this issue, or to a pastebin of you choice and put the link here. -->
with parameters `-vvv --no-validate --output-reproducible --output-file=-`,
then upload all output to this issue, or to a pastebin of you choice and put the link here. -->

## Environment

Expand Down
12 changes: 11 additions & 1 deletion HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,18 @@ All notable changes to this project will be documented in this file.
## unreleased

* Changed
* Hardened JSON imports (via [#1132])
* Log output is less verbose, can be re-enabled via CLI switch `--verbose` ([#158] via [#1131])
Warnings and errors are still displayed as before.
This is considered a non-breaking change, since only informational logs and debug information is affected.
* Hardened JSON imports (via [#1132])
* Added
* CLI switch `-v, --verbose` to increase output verbosity ([#158] via [#1131])
May be used multiple times, like `-vvv`.
* More logs on info-level (via [#1131])
* More logs on debug-level (via [#1131])

[#158]: https://github.com/CycloneDX/cyclonedx-node-npm/issues/158
[#1131]: https://github.com/CycloneDX/cyclonedx-node-npm/pull/1131
[#1132]: https://github.com/CycloneDX/cyclonedx-node-npm/pull/1132

## 1.14.3 - 2023-12-01
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ Options:
--no-validate Disable validation of resulting BOM.
--mc-type <type> Type of the main component.
(choices: "application", "firmware", "library", default: "application")
-v, --verbose Increase the verbosity of messages.
Use multiple times to increase the verbosity even more.
-V, --version output the version number
-h, --help display help for command
```
Expand Down
11 changes: 7 additions & 4 deletions src/builders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@ export class BomBuilder {
}
}

// TODO use instead ? : https://www.npmjs.com/package/debug ?
this.console.info('INFO | gather dependency tree ...')
this.console.debug('DEBUG | npm-ls: run npm with %j in %j', args, projectDir)
let npmLsReturns: Buffer
Expand Down Expand Up @@ -208,7 +207,6 @@ export class BomBuilder {
}

buildFromNpmLs (data: any, npmVersion?: string): Models.Bom {
// TODO use instead ? : https://www.npmjs.com/package/debug ?
this.console.info('INFO | build BOM ...')

// region all components & dependencies
Expand Down Expand Up @@ -310,11 +308,13 @@ export class BomBuilder {
for (const [depName, depData] of Object.entries(data.dependencies ?? {}) as any) {
if (depData === null || typeof depData !== 'object') {
// cannot build
this.console.debug('DEBUG | skip malformed component %j in %j', depName, depData)
continue // for-loop
}
if (typeof depData.path !== 'string') {
// might be an optional dependency that was not installed
// skip, as it was not installed anyway
this.console.debug('DEBUG | skip missing component %j in %j', depName, depData.path)
continue // for-loop
}

Expand All @@ -323,14 +323,17 @@ export class BomBuilder {
const _dep = this.makeComponent(depData)
if (_dep === false) {
// shall be skipped
this.console.debug('DEBUG | skip impossible component %j in %j', depName, depData.path)
continue // for-loop
}
dep = _dep ??
new DummyComponent(Enums.ComponentType.Library, `InterferedDependency.${depName as string}`)
if (dep instanceof DummyComponent) {
this.console.warn('WARN | InterferedDependency $j', dep.name)
this.console.warn('WARN | InterferedDependency %j in %j', depName, depData.path)
} else {
this.console.debug('DEBUG | built component %j in %j: %j', depName, depData.path, dep)
}

this.console.info('INFO | add component for %j in %j', depName, depData.path)
allComponents.set(depData.path, dep)
}
directDepRefs.add(dep.bomRef)
Expand Down
27 changes: 20 additions & 7 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { dirname, resolve } from 'path'

import { loadJsonFile } from './_helpers'
import { BomBuilder, TreeBuilder } from './builders'
import { makeConsoleLogger } from './logger'

enum OutputFormat {
JSON = 'JSON',
Expand All @@ -50,6 +51,7 @@ interface CommandOptions {
outputFile: string
validate: boolean
mcType: Enums.ComponentType
verbose: number
}

function makeCommand (process: NodeJS.Process): Command {
Expand Down Expand Up @@ -164,6 +166,15 @@ function makeCommand (process: NodeJS.Process): Command {
).default(
Enums.ComponentType.Application
)
).addOption(
new Option(
'-v, --verbose',
'Increase the verbosity of messages. Use multiple times to increase the verbosity even more.'
).argParser<number>(
function (_: any, previous: number): number {
return previous + 1
}
).default(0)
).addArgument(
new Argument(
'[<package-manifest>]',
Expand All @@ -189,13 +200,11 @@ const ExitCode: Readonly<Record<string, number>> = Object.freeze({
export async function run (process: NodeJS.Process): Promise<number> {
process.title = 'cyclonedx-node-npm'

// all output shall be bound to stdError - stdOut is for result output only
const myConsole = new console.Console(process.stderr, process.stderr)

const program = makeCommand(process)
program.parse(process.argv)

const options: CommandOptions = program.opts()
const myConsole = makeConsoleLogger(options.verbose)
myConsole.debug('DEBUG | options: %j', options)

const packageFile = resolve(process.cwd(), program.args[0] ?? 'package.json')
Expand Down Expand Up @@ -272,7 +281,9 @@ export async function run (process: NodeJS.Process): Promise<number> {
myConsole.log('LOG | try validate BOM result ...')
try {
const validationErrors = await validator.validate(serialized)
if (validationErrors !== null) {
if (validationErrors === null) {
myConsole.info('INFO | BOM result appears valid')
} else {
myConsole.debug('DEBUG | BOM result invalid. details: ', validationErrors)
myConsole.error('ERROR | Failed to generate valid BOM.')
myConsole.warn(
Expand All @@ -290,14 +301,16 @@ export async function run (process: NodeJS.Process): Promise<number> {
}
}

// TODO use instead ? : https://www.npmjs.com/package/debug ?
myConsole.log('LOG | writing BOM to', options.outputFile)
writeSync(
const written = writeSync(
options.outputFile === OutputStdOut
? process.stdout.fd
: openSync(resolve(process.cwd(), options.outputFile), 'w'),
serialized
)
myConsole.info('INFO | wrote %d bytes to %s', written, options.outputFile)

return ExitCode.SUCCESS
return written > 0
? ExitCode.SUCCESS
: ExitCode.FAILURE
}
39 changes: 39 additions & 0 deletions src/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*!
This file is part of CycloneDX generator for NPM projects.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

SPDX-License-Identifier: Apache-2.0
Copyright (c) OWASP Foundation. All Rights Reserved.
*/

function noop (): void {
// do nothing
}

export function makeConsoleLogger (level: number): Console {
// all output shall be bound to stdError - stdOut is for result output only
const myConsole = new console.Console(process.stderr, process.stderr)

if (level < 3) {
myConsole.debug = noop
if (level < 2) {
myConsole.info = noop
if (level < 1) {
myConsole.log = noop
}
}
}

return myConsole
}
2 changes: 2 additions & 0 deletions tests/integration/synthetics/cli.run.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ describe('cli.run()', () => {
argv: [
process.argv[0],
'dummy_process',
'-vvv',
'--output-reproducible',
'--validate',
// no intention to test all the spec-versions nor all the output-formats - this would be not our scope.
Expand Down Expand Up @@ -311,6 +312,7 @@ describe('cli.run()', () => {
argv: [
process.argv[0],
'dummy_process',
'-vvv',
'--ignore-npm-errors',
'--output-reproducible',
'--validate',
Expand Down