@herodevs/cli 2.0.0-beta.7 → 2.0.0-beta.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,13 +10,40 @@ The HeroDevs CLI
10
10
  * [@herodevs/cli](#herodevscli)
11
11
  <!-- tocstop -->
12
12
 
13
- ## Installation Instructions
13
+ ### Prerequisites
14
14
 
15
- 1. Install node v20 or higher: [Download Node](https://nodejs.org/en/download)
16
- 1. Install the CLI using one of the following methods:
17
- * Globally: Refer to the [Usage](#usage) instructions on installing the CLI globally
18
- * npx: `npx @herodevs/cli@beta`
19
- 1. Refer to the [Commands](#commands) section for a list of commands
15
+ - Install node v20 or higher: [Download Node](https://nodejs.org/en/download)
16
+ - The HeroDevs CLI expects that you have all required technology installed for the project that you are running the CLI against
17
+ - For example, if you are running the CLI against a Gradle project, the CLI expects you to have Java installed.
18
+
19
+
20
+ ### Installation methods
21
+
22
+ #### Node Package Execute (NPX)
23
+
24
+ With Node installed, you can run the CLI directly from the npm registry without installing it globally or locally on your system
25
+
26
+ ```sh
27
+ npx @herodevs/cli@beta
28
+ ```
29
+
30
+ #### Global NPM Installation
31
+
32
+ ```sh
33
+ npm install -g @herodevs/cli@beta
34
+ ```
35
+
36
+ #### Binary Installation
37
+
38
+ HeroDevs CLI is available as a binary installation, without requiring `npm`. To do that, you may either download and run the script manually, or use the following cURL or Wget command:
39
+
40
+ ```sh
41
+ curl -o- https://raw.githubusercontent.com/herodevs/cli/v2.0.0-beta.9/scripts/install.sh | bash
42
+ ```
43
+
44
+ ```sh
45
+ wget -qO- https://raw.githubusercontent.com/herodevs/cli/v2.0.0-beta.9/scripts/install.sh | bash
46
+ ```
20
47
 
21
48
  ## TERMS
22
49
 
@@ -26,9 +53,16 @@ Use of this CLI is governed by the [HeroDevs End of Life Dataset Terms of Servic
26
53
 
27
54
  The CLI is designed to be non-invasive:
28
55
 
29
- * It does not install dependencies or modify package manager files (package-lock.json, yarn.lock, etc.)
56
+ * It does **not** install dependencies or modify package manager files (package-lock.json, yarn.lock, etc.)
30
57
  * It analyzes the project in its current state
31
- * If you need dependencies installed for accurate scanning, please install them manually before running the scan
58
+
59
+ ## Installing Dependencies Before Use
60
+
61
+ Some projects and ecosystems require projects to have dependencies installed already, to achieve an accurate scan result. It is **highly** recommended that you install all dependencies of your project to your working directory, before running a scan on your project, to ensure scan accuracy.
62
+
63
+ ### Java Users
64
+
65
+ Maven and Gradle projects should run an install and build before scanning
32
66
 
33
67
  ## Usage
34
68
  <!-- usage -->
@@ -37,7 +71,7 @@ $ npm install -g @herodevs/cli@beta
37
71
  $ hd COMMAND
38
72
  running command...
39
73
  $ hd (--version)
40
- @herodevs/cli/2.0.0-beta.7 darwin-arm64 node-v22.18.0
74
+ @herodevs/cli/2.0.0-beta.9 darwin-arm64 node-v22.18.0
41
75
  $ hd --help [COMMAND]
42
76
  USAGE
43
77
  $ hd COMMAND
@@ -49,6 +83,7 @@ USAGE
49
83
  * [`hd help [COMMAND]`](#hd-help-command)
50
84
  * [`hd scan eol`](#hd-scan-eol)
51
85
  * [`hd update [CHANNEL]`](#hd-update-channel)
86
+ * **NOTE:** Only applies to [binary installation method](#binary-installation). NPM users should use [`npm install`](#global-npm-installation) to update to the latest version.
52
87
 
53
88
  ## `hd help [COMMAND]`
54
89
 
@@ -76,13 +111,14 @@ Scan a given SBOM for EOL data
76
111
 
77
112
  ```
78
113
  USAGE
79
- $ hd scan eol [--json] [-f <value> | -d <value>] [-s] [--saveSbom]
114
+ $ hd scan eol [--json] [-f <value> | -d <value>] [-s] [--saveSbom] [--version]
80
115
 
81
116
  FLAGS
82
117
  -d, --dir=<value> [default: <current directory>] The directory to scan in order to create a cyclonedx SBOM
83
118
  -f, --file=<value> The file path of an existing cyclonedx SBOM to scan for EOL
84
119
  -s, --save Save the generated report as herodevs.report.json in the scanned directory
85
120
  --saveSbom Save the generated SBOM as herodevs.sbom.json in the scanned directory
121
+ --version Show CLI version.
86
122
 
87
123
  GLOBAL FLAGS
88
124
  --json Format output as json.
@@ -112,12 +148,14 @@ EXAMPLES
112
148
  $ hd scan eol --json
113
149
  ```
114
150
 
115
- _See code: [src/commands/scan/eol.ts](https://github.com/herodevs/cli/blob/v2.0.0-beta.7/src/commands/scan/eol.ts)_
151
+ _See code: [src/commands/scan/eol.ts](https://github.com/herodevs/cli/blob/v2.0.0-beta.9/src/commands/scan/eol.ts)_
116
152
 
117
153
  ## `hd update [CHANNEL]`
118
154
 
119
155
  update the hd CLI
120
156
 
157
+ * **NOTE:** Only applies to [binary installation method](#binary-installation). NPM users should use [`npm install`](#global-npm-installation) to update to the latest version.
158
+
121
159
  ```
122
160
  USAGE
123
161
  $ hd update [CHANNEL] [--force | | [-a | -v <value> | -i]] [-b ]
@@ -157,7 +195,7 @@ _See code: [@oclif/plugin-update](https://github.com/oclif/plugin-update/blob/v4
157
195
 
158
196
  You can use `@herodevs/cli` in your CI/CD pipelines to automate EOL scanning.
159
197
 
160
- ### Using the Docker Image (recommended)
198
+ ### Using the Docker Image (Recommended)
161
199
 
162
200
  We provide a Docker image that's pre-configured to run EOL scans. Based on [`cdxgen`](https://github.com/CycloneDX/cdxgen),
163
201
  it contains build tools for most project types and will provide best results when generating an SBOM. Use these templates to generate a report and save it to your CI job artifact for analysis and processing after your scan runs.
@@ -207,9 +245,9 @@ eol-scan:
207
245
  - herodevs.report.json
208
246
  ```
209
247
 
210
- ### Using `npx`
248
+ ### Using `npx` in CI
211
249
 
212
- You can use `npx` to run the CLI just like you'd run it locally.
250
+ You can use `npx` to run the CLI in your CI pipeline, just like you would run it locally.
213
251
 
214
252
  > [!NOTE]
215
253
  > The development environment is expected to be ready to run the app. For best results,
package/bin/dev.js CHANGED
@@ -4,6 +4,6 @@ import main from './main.js';
4
4
 
5
5
  try {
6
6
  await main(false);
7
- } catch (error) {
7
+ } catch {
8
8
  process.exit(1);
9
9
  }
package/bin/main.js CHANGED
@@ -21,7 +21,7 @@ async function main(isProduction = false) {
21
21
  development: !isProduction,
22
22
  dir: new URL('./dev.js', import.meta.url),
23
23
  });
24
- } catch (error) {
24
+ } catch {
25
25
  process.exit(1);
26
26
  }
27
27
  }
package/bin/run.js CHANGED
@@ -4,6 +4,6 @@ import main from './main.js';
4
4
 
5
5
  try {
6
6
  await main(true);
7
- } catch (error) {
7
+ } catch {
8
8
  process.exit(1);
9
9
  }
@@ -12,6 +12,7 @@ export default class ScanEol extends Command {
12
12
  dir: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
13
13
  save: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
14
  saveSbom: import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
+ version: import("@oclif/core/interfaces").BooleanFlag<void>;
15
16
  };
16
17
  run(): Promise<EolReport | undefined>;
17
18
  private loadSbom;
@@ -50,6 +50,7 @@ export default class ScanEol extends Command {
50
50
  default: false,
51
51
  description: `Save the generated SBOM as ${filenamePrefix}.sbom.json in the scanned directory`,
52
52
  }),
53
+ version: Flags.version(),
53
54
  };
54
55
  async run() {
55
56
  const { flags } = await this.parse(ScanEol);
@@ -69,6 +70,15 @@ export default class ScanEol extends Command {
69
70
  sbom_generation_time: (sbomEndTime - sbomStartTime) / 1000,
70
71
  }));
71
72
  }
73
+ if (flags.saveSbom && !flags.file) {
74
+ const sbomPath = this.saveSbom(flags.dir, sbom);
75
+ this.log(`SBOM saved to ${sbomPath}`);
76
+ track('CLI SBOM Output Saved', (context) => ({
77
+ command: context.command,
78
+ command_flags: context.command_flags,
79
+ sbom_output_path: sbomPath,
80
+ }));
81
+ }
72
82
  if (!sbom.components?.length) {
73
83
  track('CLI EOL Scan Ended, No Components Found', (context) => ({
74
84
  command: context.command,
@@ -104,15 +114,6 @@ export default class ScanEol extends Command {
104
114
  report_output_path: reportPath,
105
115
  }));
106
116
  }
107
- if (flags.saveSbom && !flags.file) {
108
- const sbomPath = this.saveSbom(flags.dir, sbom);
109
- this.log(`SBOM saved to ${sbomPath}`);
110
- track('CLI SBOM Output Saved', (context) => ({
111
- command: context.command,
112
- command_flags: context.command_flags,
113
- sbom_output_path: sbomPath,
114
- }));
115
- }
116
117
  if (!this.jsonEnabled()) {
117
118
  this.displayResults(scan);
118
119
  }
@@ -0,0 +1,18 @@
1
+ import ora, {} from 'ora';
2
+ import { track } from "../../service/analytics.svc.js";
3
+ const hook = async (opts) => {
4
+ const isHelpOrVersionCmd = opts.argv.includes('--help') || opts.argv.includes('--version');
5
+ let spinner;
6
+ if (!isHelpOrVersionCmd) {
7
+ spinner = ora().start('Cleaning up');
8
+ }
9
+ const event = track('CLI Session Ended', (context) => ({
10
+ cli_version: context.cli_version,
11
+ ended_at: new Date(),
12
+ })).promise;
13
+ if (!isHelpOrVersionCmd) {
14
+ await event;
15
+ spinner?.stop();
16
+ }
17
+ };
18
+ export default hook;
@@ -1,7 +1,7 @@
1
1
  import updateNotifier, {} from 'update-notifier';
2
- import pkg from '../../package.json' with { type: 'json' };
3
- import { debugLogger } from "../service/log.svc.js";
4
- const updateNotifierHook = async (options) => {
2
+ import pkg from '../../../package.json' with { type: 'json' };
3
+ import { debugLogger } from "../../service/log.svc.js";
4
+ const updateNotifierHook = async () => {
5
5
  debugLogger('pkg.version', pkg.version);
6
6
  const distTag = getDistTag(pkg.version);
7
7
  debugLogger('distTag', distTag);
@@ -0,0 +1,3 @@
1
+ import type { Hook } from '@oclif/core';
2
+ declare const hook: Hook.Init;
3
+ export default hook;
@@ -1,7 +1,6 @@
1
1
  import { parseArgs } from 'node:util';
2
- import debug from 'debug';
3
- import { initializeAnalytics, track } from "../service/analytics.svc.js";
4
- const hook = async (opts) => {
2
+ import { initializeAnalytics, track } from "../../service/analytics.svc.js";
3
+ const hook = async () => {
5
4
  const args = parseArgs({ allowPositionals: true, strict: false });
6
5
  initializeAnalytics();
7
6
  track('CLI Command Submitted', (context) => ({
@@ -12,9 +11,5 @@ const hook = async (opts) => {
12
11
  cli_version: context.cli_version,
13
12
  started_at: context.started_at,
14
13
  }));
15
- // If JSON flag is enabled, silence debug logging
16
- if (opts.Command.prototype.jsonEnabled()) {
17
- debug.disable();
18
- }
19
14
  };
20
15
  export default hook;
@@ -0,0 +1,8 @@
1
+ import debug from 'debug';
2
+ const hook = async (opts) => {
3
+ // If JSON flag is enabled, silence debug logging
4
+ if (opts.Command.prototype.jsonEnabled()) {
5
+ debug.disable();
6
+ }
7
+ };
8
+ export default hook;
@@ -58,8 +58,8 @@ export function formatScanResults(report) {
58
58
  ux.colorize('bold', `${report.components.length.toLocaleString()} total packages scanned`),
59
59
  getStatusRowText.EOL(`${EOL.toLocaleString().padEnd(5)} End-of-Life (EOL)`),
60
60
  getStatusRowText.EOL_UPCOMING(`${EOL_UPCOMING.toLocaleString().padEnd(5)} EOL Upcoming`),
61
- getStatusRowText.OK(`${OK.toLocaleString().padEnd(5)} Not End-of-Life`),
62
- getStatusRowText.UNKNOWN(`${UNKNOWN.toLocaleString().padEnd(5)} Unknown Status`),
61
+ getStatusRowText.OK(`${OK.toLocaleString().padEnd(5)} Not End-of-Life (EOL)`),
62
+ getStatusRowText.UNKNOWN(`${UNKNOWN.toLocaleString().padEnd(5)} Unknown EOL Status`),
63
63
  getStatusRowText.UNKNOWN(`${NES_AVAILABLE.toLocaleString().padEnd(5)} HeroDevs NES Remediation${NES_AVAILABLE !== 1 ? 's' : ''} Available`),
64
64
  ];
65
65
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@herodevs/cli",
3
- "version": "2.0.0-beta.7",
3
+ "version": "2.0.0-beta.9",
4
4
  "author": "HeroDevs, Inc",
5
5
  "bin": {
6
6
  "hd": "./bin/run.js"
@@ -26,11 +26,12 @@
26
26
  "prepare": "shx test -d dist || npm run build",
27
27
  "prepack": "oclif manifest",
28
28
  "pretest": "npm run lint && npm run typecheck",
29
- "readme": "npm run ci:fix && npm run build && npm exec oclif readme",
29
+ "readme": "npm run ci:fix && npm run build && oclif readme",
30
30
  "test": "globstar -- node --import tsx --test --experimental-test-module-mocks \"test/**/*.test.ts\"",
31
31
  "test:e2e": "globstar -- node --import tsx --test \"e2e/**/*.test.ts\"",
32
32
  "typecheck": "tsc --noEmit",
33
- "version": "oclif manifest && npm run readme"
33
+ "version": "oclif manifest",
34
+ "postversion": "node scripts/update-install-script-version.js && git add README.md"
34
35
  },
35
36
  "keywords": [
36
37
  "herodevs",
@@ -38,11 +39,11 @@
38
39
  "herodevs cli"
39
40
  ],
40
41
  "dependencies": {
41
- "@amplitude/analytics-node": "^1.5.5",
42
+ "@amplitude/analytics-node": "^1.5.8",
42
43
  "@apollo/client": "^3.13.8",
43
44
  "@cyclonedx/cdxgen": "~11.4.4",
44
45
  "@herodevs/eol-shared": "github:herodevs/eol-shared#v0.1.11",
45
- "@oclif/core": "^4.5.2",
46
+ "@oclif/core": "^4.5.3",
46
47
  "@oclif/plugin-help": "^6.2.32",
47
48
  "@oclif/plugin-update": "^4.7.4",
48
49
  "graphql": "^16.11.0",
@@ -56,11 +57,11 @@
56
57
  "@biomejs/biome": "^2.2.2",
57
58
  "@oclif/test": "^4.1.13",
58
59
  "@types/inquirer": "^9.0.9",
59
- "@types/node": "^24.3.0",
60
+ "@types/node": "^24.3.1",
60
61
  "@types/sinon": "^17.0.4",
61
62
  "@types/update-notifier": "^6.0.8",
62
63
  "globstar": "^1.0.0",
63
- "oclif": "^4.22.14",
64
+ "oclif": "^4.22.18",
64
65
  "shx": "^0.4.0",
65
66
  "sinon": "^21.0.0",
66
67
  "ts-node": "^10.9.2",
@@ -87,9 +88,12 @@
87
88
  "@oclif/plugin-update"
88
89
  ],
89
90
  "hooks": {
90
- "init": "./dist/hooks/npm-update-notifier.js",
91
- "prerun": "./dist/hooks/prerun.js",
92
- "finally": "./dist/hooks/finally.js"
91
+ "init": [
92
+ "./dist/hooks/init/00_npm-update-notifier.js",
93
+ "./dist/hooks/init/01_initialize_amplitude.js"
94
+ ],
95
+ "prerun": "./dist/hooks/prerun/prerun.js",
96
+ "finally": "./dist/hooks/finally/finally.js"
93
97
  },
94
98
  "topicSeparator": " ",
95
99
  "macos": {
@@ -1,14 +0,0 @@
1
- import ora from 'ora';
2
- import { track } from "../service/analytics.svc.js";
3
- const hook = async (opts) => {
4
- const spinner = ora().start('Cleaning up');
5
- const event = track('CLI Session Ended', (context) => ({
6
- cli_version: context.cli_version,
7
- ended_at: new Date(),
8
- })).promise;
9
- if (!opts.argv.includes('--help')) {
10
- await event;
11
- }
12
- spinner.stop();
13
- };
14
- export default hook;
File without changes