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

tests: more cov #1185

Draft
wants to merge 16 commits into
base: main
Choose a base branch
from
Draft
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
17 changes: 13 additions & 4 deletions .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ jobs:

test-jest:
needs: [ 'build' ]
name: jest (node${{ matrix.node-version }} ${{ matrix.os }})
name: jest (node${{ matrix.node-version }} ${{ matrix.os }} ${{ matrix.omit-optional && 'omit-optional'}})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
Expand All @@ -90,6 +90,10 @@ jobs:
- ubuntu-latest
- windows-latest
- macos-13 # macos-latest has issues with node14
include:
- node-version: 22
os: ubuntu-latest
omit-optional: true
timeout-minutes: 15
steps:
- name: Checkout
Expand All @@ -107,6 +111,11 @@ jobs:
set -ex
dep_constraints=''
dev_requirements='jest jest-junit imurmurhash fast-glob'
omit=''
if [[ -n '${{ matrix.omit-optional }}' ]]
then
omit='--omit=optional'
fi
# as long as npm cannot auto-resolve engine-constraints, we need to help here
case '${{ matrix.node-version }}' in
'14')
Expand All @@ -120,13 +129,13 @@ jobs:
## !! dont install all the dev-packages, especially since some are not runnable on node 14.0.0
if [[ -n "$dep_constraints" ]]
then
npm add --ignore-scripts --omit=dev --only=prod --production --loglevel=silly --save $dep_constraints
npm add --ignore-scripts $omit --omit=dev --only=prod --production --loglevel=silly --save $dep_constraints
fi
npm i --ignore-scripts --omit=dev --only=prod --production --loglevel=silly
npm i --ignore-scripts $omit --omit=dev --only=prod --production --loglevel=silly
## rebuild deps for which scripts were ignored, or partially installed - since "ignore-scripts" was used
npm rebuild --loglevel=silly libxmljs2 || npm uninstall --no-save libxmljs2
## install the needed dev-deps
npm i --ignore-scripts --loglevel=silly --no-save $dev_requirements
npm i --ignore-scripts --loglevel=silly $omit --no-save $dev_requirements
- name: fetch build artifact
# see https://github.com/actions/download-artifact
uses: actions/download-artifact@v4
Expand Down
3 changes: 2 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ module.exports = {
// An array of glob patterns indicating a set of files for which coverage information should be collected
collectCoverageFrom: [
'src/**',
'dist/**' // running tests on build results, so need to have this vector
'dist/**', // running tests on build results, so need to have this vector
'bin/**'
],

// The directory where Jest should output its coverage files
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"jest": "29.7.0",
"jest-junit": "16.0.0",
"npm-run-all": "^4.1.5",
"rimraf": "^5.0.7",
"typescript": "5.4.5"
},
"type": "commonjs",
Expand All @@ -89,12 +90,13 @@
"prepublish": "npm run build",
"prepublishOnly": "run-s -lc build test",
"lint": "tsc --noEmit",
"prebuild": "node -r fs -e 'fs.rmSync(`dist`,{recursive:true,force:true})'",
"prebuild": "rimraf dist",
"build": "tsc -b ./tsconfig.json",
"cs-fix": "eslint --fix .",
"setup-tests": "echo 'noting yet'",
"test": "run-p --aggregate-output -lc test:*",
"test:jest": "jest",
"test:lint": "tsc --noEmit",
"test:standard": "eslint .",
"dogfooding:npx": "npx .",
"dogfooding:npm-exec": "npm exec .",
Expand Down
110 changes: 62 additions & 48 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,72 +55,79 @@ interface CommandOptions {
}

function makeCommand (process: NodeJS.Process): Command {
return new Command(
).description(
'Create CycloneDX Software Bill of Materials (SBOM) from Node.js NPM projects.'
).usage(
const cmd = new Command()
cmd.description('Create CycloneDX Software Bill of Materials (SBOM) from Node.js NPM projects.')
cmd.usage(
// Need to add the `[--]` manually, to indicate how to stop a variadic option.
'[options] [--] [<package-manifest>]'
).addOption(
new Option(
)
cmd.addOption(
(new Option(
'--ignore-npm-errors',
'Whether to ignore errors of NPM.\n' +
'This might be used, if "npm install" was run with "--force" or "--legacy-peer-deps".'
).default(false)
).addOption(
new Option(
)).default(false)
)
cmd.addOption(
(new Option(
'--package-lock-only',
'Whether to only use the lock file, ignoring "node_modules".\n' +
'This means the output will be based only on the few details in and the tree described by the "npm-shrinkwrap.json" or "package-lock.json", rather than the contents of "node_modules" directory.'
).default(false)
).addOption(
new Option(
)).default(false)
)
cmd.addOption(
(new Option(
'--omit <type...>',
'Dependency types to omit from the installation tree. ' +
'(can be set multiple times)'
).choices(
)).choices(
Object.values(Omittable).sort()
).default(
process.env.NODE_ENV === 'production'
? [Omittable.Dev]
: [],
`"${Omittable.Dev}" if the NODE_ENV environment variable is set to "production", otherwise empty`
)
).addOption(
new Option(
)
cmd.addOption(
(new Option(
'--flatten-components',
'Whether to flatten the components.\n' +
'This means the actual nesting of node packages is not represented in the SBOM result.'
).default(false)
).addOption(
new Option(
)).default(false)
)
cmd.addOption(
(new Option(
'--short-PURLs',
'Omit all qualifiers from PackageURLs.\n' +
'This causes information loss in trade-off shorter PURLs, which might improve ingesting these strings.'
).default(false)
).addOption(
new Option(
)).default(false)
)
cmd.addOption(
(new Option(
'--spec-version <version>',
'Which version of CycloneDX spec to use.'
).choices(
)).choices(
Object.keys(Spec.SpecVersionDict).sort()
).default(
Spec.Version.v1dot4
)
).addOption(
new Option(
)
cmd.addOption(
(new Option(
'--output-reproducible',
'Whether to go the extra mile and make the output reproducible.\n' +
'This requires more resources, and might result in loss of time- and random-based-values.'
).env(
)).env(
'BOM_REPRODUCIBLE'
)
).addOption(
)
cmd.addOption(
(function () {
const o = new Option(
const o = (new Option(
'--output-format <format>',
'Which output format to use.'
).choices(
)).choices(
[OutputFormat.JSON, OutputFormat.XML]
).default(
// the context is node/JavaScript - which should prefer JSON
Expand All @@ -132,31 +139,35 @@ function makeCommand (process: NodeJS.Process): Command {
o.parseArg = (v, p) => oldParseArg(v.toUpperCase(), p)
return o
})()
).addOption(
new Option(
)
cmd.addOption(
(new Option(
'--output-file <file>',
'Path to the output file.\n' +
`Set to "${OutputStdOut}" to write to STDOUT.`
).default(
)).default(
OutputStdOut,
'write to STDOUT'
)
).addOption(
new Option(
)
cmd.addOption(
(new Option(
'--validate',
'Validate resulting BOM before outputting. ' +
'Validation is skipped, if requirements not met. See the README.'
).default(undefined)
).addOption(
)).default(undefined)
)
cmd.addOption(
new Option(
'--no-validate',
'Disable validation of resulting BOM.'
)
).addOption(
new Option(
)
cmd.addOption(
(new Option(
'--mc-type <type>',
'Type of the main component.'
).choices(
)).choices(
// Object.values(Enums.ComponentType) -- use all possible
[ // for the NPM context only the following make sense:
Enums.ComponentType.Application,
Expand All @@ -166,29 +177,32 @@ function makeCommand (process: NodeJS.Process): Command {
).default(
Enums.ComponentType.Application
)
).addOption(
new Option(
)
cmd.addOption(
(new Option(
'-v, --verbose',
'Increase the verbosity of messages. Use multiple times to increase the verbosity even more.'
).argParser<number>(
)).argParser<number>(
function (_: any, previous: number): number {
return previous + 1
}
).default(0)
).addArgument(
new Argument(
)
cmd.addArgument(
(new Argument(
'[<package-manifest>]',
"Path to project's manifest file."
).default(
)).default(
'package.json',
'"package.json" file in current working directory'
)
).version(
)
cmd.version(
// that is supposed to be the last option in the list on the help page.
loadJsonFile(resolve(module.path, '..', 'package.json')).version as string
).allowExcessArguments(
false
)
cmd.allowExcessArguments(false)
return cmd
}

const ExitCode: Readonly<Record<string, number>> = Object.freeze({
Expand All @@ -204,7 +218,7 @@ export async function run (process: NodeJS.Process): Promise<number> {
program.parse(process.argv)

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

const packageFile = resolve(process.cwd(), program.args[0] ?? 'package.json')
Expand Down
2 changes: 1 addition & 1 deletion src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function noop (): void {
// do nothing
}

export function makeConsoleLogger (level: number): Console {
export function makeConsoleLogger (process: NodeJS.Process, 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)

Expand Down
Loading
Loading