@leverege/build-tools 2.56.1 → 2.57.0

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.
@@ -0,0 +1,11 @@
1
+ {
2
+ "protected-branches": [
3
+ "development",
4
+ "main"
5
+ ],
6
+ "npm-scripts": [
7
+ "lint",
8
+ "test"
9
+ ],
10
+ "ignore-packages": []
11
+ }
@@ -0,0 +1 @@
1
+ hook-and-release
package/.har/pre-push ADDED
@@ -0,0 +1 @@
1
+ hook-and-release
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leverege/build-tools",
3
- "version": "2.56.1",
3
+ "version": "2.57.0",
4
4
  "description": "A collection of build / support tools for Leverege developers",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -10,7 +10,8 @@
10
10
  "scripts": {
11
11
  "clean": "rm -rf lib",
12
12
  "lint": "find ./src -name \\*.\\*js | xargs npx eslint --report-unused-disable-directives",
13
- "test": "echo \"Error: no test specified\" && exit 1"
13
+ "prepare": "hook-and-release",
14
+ "test": "echo \"no tests specified\" && exit 0"
14
15
  },
15
16
  "bin": {
16
17
  "build-tools": "src/build-tools.mjs",
@@ -34,6 +35,7 @@
34
35
  "helmup": "src/helmup.sh",
35
36
  "helminit": "src/helmup.sh",
36
37
  "helmwhat": "src/helmup.sh",
38
+ "hook-and-release": "src/hook-and-release.mjs",
37
39
  "k8cryo": "src/k8cryo.sh",
38
40
  "k8scale": "src/k8scale.sh",
39
41
  "k8thaw": "src/k8cryo.sh",
@@ -56,7 +58,7 @@
56
58
  "author": "Leverege Devs",
57
59
  "license": "SEE LICENSE IN LICENSE.md",
58
60
  "dependencies": {
59
- "@google-cloud/artifact-registry": "^3.4.0",
61
+ "@google-cloud/artifact-registry": "^3.5.0",
60
62
  "ansi-colors": "^4.1.3",
61
63
  "chalk": "^5.3.0",
62
64
  "command-line-args": "^6.0.1",
@@ -66,7 +68,7 @@
66
68
  "execa": "^9.5.1",
67
69
  "glob": "^11.0.0",
68
70
  "handlebars": "^4.7.8",
69
- "inquirer": "^12.0.1",
71
+ "inquirer": "^12.1.0",
70
72
  "js-yaml": "^4.1.0",
71
73
  "ms": "^2.1.3",
72
74
  "npm-registry-fetch": "^18.0.2",
@@ -76,7 +78,7 @@
76
78
  "readline-sync": "^1.4.10",
77
79
  "semver": "^7.6.3",
78
80
  "simple-git": "^3.27.0",
79
- "zx": "^8.2.0"
81
+ "zx": "^8.2.2"
80
82
  },
81
83
  "devDependencies": {
82
84
  "@leverege/eslint-config-leverege": "^5.0.1",
package/src/Utils.mjs CHANGED
@@ -9,6 +9,7 @@ import YAML from 'js-yaml'
9
9
 
10
10
  let debugEnabled = process.env.BUILD_TOOLS_DEBUG === '1'
11
11
 
12
+ export const enableDebug = () => { debugEnabled = true }
12
13
  export const disableDebug = () => { debugEnabled = false }
13
14
 
14
15
  /* eslint-disable no-console */
@@ -115,26 +116,29 @@ export const getGcpSecret = async ( gcpProject, secretName, opts ) => {
115
116
  }
116
117
  }
117
118
 
118
- export const getGitRootDirectory = async () => {
119
+ const runGitCommand = async ( cmd, debugLabel ) => {
119
120
  try {
120
- const gitRoot = await shellCmd( 'git rev-parse --show-toplevel' )
121
- debug( { gitRoot }, '<==getGitRootDirectory' )
122
- return gitRoot
121
+ const result = await shellCmd( cmd )
122
+ debug( { result }, `<==${debugLabel}` )
123
+ return result
123
124
  } catch ( error ) {
124
- debug( { error }, '<==getGitRootDirectory' )
125
- throw error
125
+ debug( { error }, chalk.red( `***ERROR git failed [${cmd}]` ) )
126
+ return undefined
126
127
  }
127
128
  }
128
129
 
129
- export const getGitUpstream = async () => {
130
- let branch
130
+ export const getGitBranch = async () => runGitCommand( 'git rev-parse --abbrev-ref HEAD', 'getGitCurrentBranch' )
131
+ export const getGitDiff = async opts => runGitCommand( `git diff ${opts}`, 'getGitDiff' )
132
+ export const getGitHooksPath = async () => runGitCommand( 'git config --get core.hooksPath', 'getGitHooksPath' )
133
+ export const setGitHooksPath = async hookPath => runGitCommand( `git config core.hooksPath ${hookPath}`, 'setGitHooksPath' )
134
+ export const getGitRootDirectory = async () => runGitCommand( 'git rev-parse --show-toplevel', 'getGitRootDirectory' )
135
+ export const getGitBranchAndUpstream = async () => {
136
+ const branch = await getGitBranch() ?? 'detached'
137
+ let upstream = 'no-upstream'
131
138
  try {
132
- branch = await shellCmd( 'git rev-parse --abbrev-ref HEAD' )
133
- const upstream = await shellCmd( `git rev-parse --abbrev-ref ${branch}@{u}` )
134
- return { branch, upstream }
135
- } catch ( err ) {
136
- return { branch, upstream : undefined }
137
- }
139
+ upstream = await runGitCommand( `git rev-parse --abbrev-ref ${branch}@{u}`, 'getGitUpstream' ) ?? 'no-upstream'
140
+ } catch ( error ) {}
141
+ return { branch, upstream }
138
142
  }
139
143
 
140
144
  export const gitRepoIsDirty = async () => {
@@ -382,13 +386,15 @@ export const parseHelmChart = async ( helmroot = './helm' ) => {
382
386
  } )
383
387
  }
384
388
 
385
- export const analyzeRepository = async ( giveGuidance ) => {
389
+ export const getRepositoryDescr = async () => {
390
+ const currentDir = process.cwd()
391
+ const workingDir = process.env.PWD
386
392
  const gitRoot = await getGitRootDirectory()
393
+ const gitHooksPath = await getGitHooksPath()
394
+ const { branch : gitBranch, upstream : gitUpstream } = await getGitBranchAndUpstream()
387
395
  const subPkgs = await glob( `${gitRoot}/packages/**/package.json`, { ignore : '/**/node_modules/**' } )
388
396
  const helmChart = await parseHelmChart()
389
397
  const isMonoRepo = subPkgs?.length > 0
390
-
391
- // Verify the presence of a root package.json file for all monorepos
392
398
  let rootPackageJson
393
399
  try {
394
400
  rootPackageJson = await parseJsonFile( `${gitRoot}/package.json` )
@@ -396,6 +402,32 @@ export const analyzeRepository = async ( giveGuidance ) => {
396
402
  rootPackageJson = { isInvalid : true, error : 'invalid or non-existent root package.json file' }
397
403
  }
398
404
  const isNpmWorkspace = rootPackageJson?.workspaces?.length > 0
405
+
406
+ return {
407
+ currentDir,
408
+ workingDir,
409
+ gitBranch,
410
+ gitHooksPath,
411
+ gitRoot,
412
+ gitUpstream,
413
+ helmChart,
414
+ isMonoRepo,
415
+ isNpmWorkspace,
416
+ rootPackageJson,
417
+ subPkgs,
418
+ }
419
+ }
420
+
421
+ export const analyzeRepository = async ( giveGuidance ) => {
422
+ const {
423
+ gitRoot,
424
+ subPkgs,
425
+ helmChart,
426
+ isMonoRepo,
427
+ rootPackageJson,
428
+ isNpmWorkspace,
429
+ } = await getRepositoryDescr()
430
+
399
431
  if ( isMonoRepo && rootPackageJson.isInvalid ) {
400
432
  log( chalk.red.bold( `
401
433
  ***REQUIRED: A package.json file is required at the monorepo root` ) )
@@ -11,7 +11,7 @@ import {
11
11
  debug, log,
12
12
  errorExit,
13
13
  analyzeRepository,
14
- getGitUpstream,
14
+ getGitBranchAndUpstream,
15
15
  gitRepoIsDirty,
16
16
  proceed,
17
17
  shellCmd } from './Utils.mjs'
@@ -234,7 +234,7 @@ if ( imageVersion !== packageVersion ) {
234
234
  }
235
235
  }
236
236
 
237
- const repoInfo = await getGitUpstream()
237
+ const repoInfo = await getGitBranchAndUpstream()
238
238
 
239
239
  if ( willGitTag && !repoInfo.upstream ) {
240
240
  log( `
@@ -0,0 +1,23 @@
1
+ import commandLineArgs from 'command-line-args'
2
+ import commandLineUsage from 'command-line-usage'
3
+
4
+ import { log } from '../Utils.mjs'
5
+
6
+ const parseCLIArgs = ( optionList, sections ) => {
7
+ const cliArgs = commandLineArgs( optionList, { camelCase : true, partial : true } )
8
+
9
+ /* eslint-disable no-underscore-dangle */
10
+ if ( cliArgs._unknown ) {
11
+ throw new Error( `Unknown command line options: ${cliArgs._unknown.join( ', ' )}` )
12
+ }
13
+ /* eslint-enable no-underscore-dangle */
14
+
15
+ if ( cliArgs.help ) {
16
+ log( commandLineUsage( sections ) )
17
+ process.exit( 0 )
18
+ }
19
+
20
+ return cliArgs
21
+ }
22
+
23
+ export default parseCLIArgs
@@ -0,0 +1,249 @@
1
+ import fs from 'node:fs'
2
+
3
+ import chalk from 'chalk'
4
+
5
+ import {
6
+ debug,
7
+ enableDebug,
8
+ errorExit,
9
+ getRepositoryDescr,
10
+ log,
11
+ parseJsonFile,
12
+ setGitHooksPath,
13
+ shellCmd,
14
+ warning,
15
+ } from '../Utils.mjs'
16
+
17
+ import parseCLIArgs from './CLIParser.mjs'
18
+
19
+ const cliOptionList = [
20
+ {
21
+ name : 'init',
22
+ type : Boolean,
23
+ default : false,
24
+ description : '{green bootstraps the repo .har directory and adds appropriate git hook}',
25
+ },
26
+ {
27
+ name : 'debug',
28
+ type : Boolean,
29
+ default : false,
30
+ description : '{yellow enables verbose debugging}',
31
+ },
32
+ {
33
+ name : 'help',
34
+ type : Boolean,
35
+ default : false,
36
+ description : '{green display this help screen}',
37
+ },
38
+ ]
39
+
40
+ const cliSections = [
41
+ {
42
+ header : 'Leverege Hook and Release (HAR) Script',
43
+ content : `{green HAR is a replacement for the Husky git hook manager - it is designed to
44
+ handle git hooks in standard git repositories as well as git monorepos. It
45
+ connects into a repository's git hook system after a repo is cloned. The hook
46
+ connection is made during the {yellow.bold npm install} phase, which will execute the
47
+ {yellow.bold npm prepare} script as defined in the package.json scripts section:
48
+
49
+ {yellow.bold "scripts": {
50
+ ...
51
+ "prepare": "hook-and-release",
52
+ ...
53
+ }
54
+
55
+ The hook-and-release script can be invoked directly from the command line,
56
+ typically for first-time initialization, or from the git hook scripts located
57
+ in the .har subdirectory in the root of a repository. Running with the {yellow.bold --init}
58
+ command line switch will create the .har subdirectory at the repo root with a
59
+ config.json file and two standard hook scripts, pre-commit and pre-push:
60
+
61
+ {yellow.bold .har
62
+ ├── config.json
63
+ ├── pre-commit
64
+ └── pre-push}
65
+ }`
66
+ },
67
+ {
68
+ header : 'Options',
69
+ optionList : cliOptionList,
70
+ },
71
+ {
72
+ header : 'Configuration File and Hook Scripts',
73
+ content : [
74
+ `{bold .har/config.json} {green controls branch, script and package config
75
+ {white.bold protected-branches} list of branch names to protect
76
+ {white.bold npm-scripts} list of npm scripts to run on protected branches
77
+ {white.bold ignore-packages} list of monorepo packages to ignore
78
+
79
+ {white.bold Example config.json}
80
+ \\{
81
+ "protected-branches": [
82
+ "development",
83
+ "main",
84
+ ],
85
+ "npm-scripts": [
86
+ "lint",
87
+ "test"
88
+ ],
89
+ "ignore-packages": [
90
+ "legacy-*"
91
+ ]
92
+ \\}
93
+
94
+ {white.bold Example pre-commit script file contents}
95
+
96
+ hook-and-release --debug
97
+
98
+ which tell HAR to run with debugging enabled. This will print out copious
99
+ amounts of information and prevents the git command from succeeding, so
100
+ it's more like a debug with dry-run. Removing the {yellow.bold --debug} will
101
+ allow everything to run normally.
102
+ }`
103
+ ]
104
+ },
105
+ ]
106
+
107
+ /* eslint-disable security/detect-non-literal-fs-filename */
108
+ export default class Config {
109
+ constructor( options = {} ) {
110
+ try {
111
+ this.cliArgs = parseCLIArgs( cliOptionList, cliSections )
112
+
113
+ if ( this.cliArgs.debug ) {
114
+ enableDebug()
115
+ }
116
+ } catch ( error ) {
117
+ log( chalk.red( `\n***ERROR: ${error.message}` ) )
118
+ process.exit( 1 )
119
+ }
120
+ }
121
+
122
+ async bootstrapHookAndRelease() {
123
+ const repoDescr = await getRepositoryDescr()
124
+ this.gitRoot = repoDescr.gitRoot
125
+ this.gitBranch = repoDescr.gitBranch
126
+ this.gitHooksPath = repoDescr.gitHooksPath
127
+ this.isMonoRepo = repoDescr.isMonoRepo
128
+
129
+ const harHook = '.har'
130
+ this.harDir = `${this.gitRoot}/${harHook}`
131
+
132
+ if ( this.gitHooksPath !== harHook ) {
133
+ await setGitHooksPath( harHook )
134
+ }
135
+
136
+ if ( this.cliArgs.init ) {
137
+ await this.initializeConfiguration( this.harDir )
138
+ }
139
+
140
+ // Start with the basics, is there a root har directory?
141
+ if ( !fs.existsSync( this.harDir ) ) {
142
+ const missingHarDir = `
143
+ The required .har configuration directory is missing from this repository. Try running:
144
+
145
+ hook-and-release --init
146
+
147
+ which will populate the ${this.harDir} directory.`
148
+ errorExit( missingHarDir )
149
+ }
150
+
151
+ const harConfigFile = `${this.harDir}/config.json`
152
+ if ( !fs.existsSync( harConfigFile ) ) {
153
+ const missingHarConfig = `
154
+ The required .har/config.json file is missing from this repository which implies
155
+ the init phase failed. Try removing the .har directory and rerunning:
156
+
157
+ hook-and-release --init`
158
+ errorExit( missingHarConfig )
159
+ }
160
+
161
+ let jsonConfig
162
+ try {
163
+ jsonConfig = await parseJsonFile( harConfigFile )
164
+ } catch ( error ) {
165
+ errorExit( `
166
+ There appears to be a syntax error in the har config file:
167
+
168
+ ${harConfigFile}
169
+
170
+ ${error}
171
+
172
+ correct the JSON syntax and try again` )
173
+
174
+ return undefined
175
+ }
176
+
177
+ this.jsonConfig = jsonConfig
178
+ this.protectedBranches = jsonConfig['protected-branches'] || [ 'main', 'development' ]
179
+ this.ignoredPackages = jsonConfig['ignore-packages'] || ''
180
+ this.npmScripts = jsonConfig['npm-scripts'] || [ 'lint', 'test' ]
181
+ return this
182
+ }
183
+
184
+ isBranchProtected() {
185
+ const branchName = this.gitBranch
186
+ const protectedBranch = this.protectedBranches.some( ( pattern ) => {
187
+ // convert wildcard pattern to a regular expression
188
+ const regex = new RegExp( `^${pattern.replace( /\*/g, '.*' )}$` ) // eslint-disable-line security/detect-non-literal-regexp
189
+ return regex.test( branchName )
190
+ } )
191
+ debug( { branchName, protectedBranch }, '<==harConfig isBranchProtected' )
192
+ return protectedBranch
193
+ }
194
+
195
+ // this could be made more generic but the initial config is dirt simple
196
+ async initializeConfiguration( harDir ) {
197
+ if ( fs.existsSync( harDir ) ) {
198
+ const harConfigExists = `The hook-and-release configuration directory already exists - skipping --init
199
+
200
+ `
201
+ warning( harConfigExists )
202
+ return
203
+ }
204
+ fs.mkdirSync( harDir, { recursive : true } )
205
+
206
+ const CONFIG_CONTENT = {
207
+ 'protected-branches' : [ 'development', 'main' ],
208
+ 'npm-scripts' : [ 'lint', 'test' ],
209
+ 'ignore-packages' : []
210
+ }
211
+ fs.writeFileSync( `${harDir}/config.json`, JSON.stringify( CONFIG_CONTENT, null, 2 ), 'utf8' )
212
+
213
+ const makeHarHookScript = async ( harScript ) => {
214
+ const SCRIPT_CONTENT = 'hook-and-release'
215
+
216
+ fs.writeFileSync( harScript, SCRIPT_CONTENT, 'utf8' )
217
+ fs.chmodSync( harScript, 0o750 )
218
+ }
219
+
220
+ makeHarHookScript( `${harDir}/pre-commit` )
221
+ makeHarHookScript( `${harDir}/pre-push` )
222
+ }
223
+
224
+ async runNpmScripts( runDirectories = [] ) {
225
+ for ( const runDirectory of runDirectories ) { // eslint-disable-line no-restricted-syntax
226
+ const scripts = this.npmScripts
227
+
228
+ // for each script run sequentially
229
+ for ( const script of scripts ) { // eslint-disable-line no-restricted-syntax
230
+ const cmd = `npm run ${script}`
231
+ log( `hook-and-release in ${chalk.green( runDirectory )} => ${chalk.green( cmd )}` )
232
+ if ( !this.cliArgs.debug ) {
233
+ try {
234
+ await shellCmd( cmd, { cwd : runDirectory, stdio : 'inherit' } ) // eslint-disable-line no-await-in-loop
235
+ } catch ( err ) {
236
+ errorExit( err )
237
+ }
238
+ }
239
+ }
240
+ }
241
+ }
242
+
243
+ // Static async factory method to initialize the Config object and run async setup
244
+ static async create( options = {} ) {
245
+ const config = new Config( options )
246
+ await config.bootstrapHookAndRelease()
247
+ return config
248
+ }
249
+ }
@@ -0,0 +1,3 @@
1
+ import Config from './Config.mjs'
2
+
3
+ export default Config
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+
3
+ import path from 'node:path'
4
+
5
+ import { debug, getGitDiff, } from './Utils.mjs'
6
+
7
+ import Config from './hook-and-release/index.mjs'
8
+
9
+ const harConfig = await Config.create()
10
+ debug( { harConfig }, '<==hook-and-release config object' )
11
+
12
+ // Config.create() is the only thing that needs to run during npm install
13
+ if ( process.env.npm_lifecycle_event === 'prepare' ) { process.exit( 0 ) }
14
+
15
+ // if this branch isn't under protection then we're done
16
+ if ( !harConfig.isBranchProtected() ) { process.exit( 0 ) }
17
+
18
+ // TODO: maybe move getRunDirectories into the har Config class too?
19
+ const getRunDirectories = async () => {
20
+ // non-mono means we just run once from the root of the repo
21
+ if ( !harConfig.isMonoRepo ) {
22
+ return [ process.cwd() ]
23
+ }
24
+
25
+ // otherwise get staged mods from git and parse out the package names
26
+ const gitDiff = await getGitDiff( '--name-only --cached' )
27
+ const stagedFiles = gitDiff.split( '\n' )
28
+ const packageDirs = new Set()
29
+
30
+ // loop through staged files and extract package directories
31
+ stagedFiles.forEach( ( file ) => {
32
+ const parts = file.split( path.sep ) // Split path to identify package
33
+ if ( parts.length > 1 && parts[0] === 'packages' ) {
34
+ const packageDir = parts[1]
35
+
36
+ // check if the package should be ignored before adding it to the Set
37
+ const shouldIgnore = harConfig.ignoredPackages.some( ( ignoredPattern ) => {
38
+ // convert an entry like legacy-* into a regex legacy-.*
39
+ const regex = new RegExp( ignoredPattern.replace( '*', '.*' ) ) // eslint-disable-line security/detect-non-literal-regexp
40
+ return regex.test( packageDir )
41
+ } )
42
+
43
+ if ( shouldIgnore ) {
44
+ debug( { packageDir }, '<==ignoring based on config' )
45
+ } else {
46
+ packageDirs.add( packageDir )
47
+ }
48
+ }
49
+ } )
50
+
51
+ const packageDirsArray = Array.from( packageDirs )
52
+ const packageDirsWithPath = packageDirsArray.map( ( packageDir ) => {
53
+ return path.join( process.cwd(), 'packages', packageDir )
54
+ } )
55
+
56
+ debug( { stagedFiles, packageDirsArray, packageDirsWithPath }, '<==unleash: getPackageDirectory' )
57
+ return packageDirsWithPath
58
+ }
59
+
60
+ const runDirectories = await getRunDirectories()
61
+ await harConfig.runNpmScripts( runDirectories )
62
+
63
+ // exit status of 1 in debug mode to prevent git from running
64
+ process.exit( harConfig.cliArgs.debug ? 1 : 0 )
package/src/overwhelm.mjs CHANGED
@@ -269,7 +269,7 @@ const validValuesLocalConfig = ( vlf ) => {
269
269
  if ( !fs.existsSync( vlf ) ) { return undefined }
270
270
 
271
271
  const valuesLocal = YAML.load( fs.readFileSync( vlf, { encoding : 'utf-8' } ) )
272
- const configBlock = valuesLocal.config
272
+ const configBlock = valuesLocal?.config
273
273
 
274
274
  // only care about validating config at this time
275
275
  if ( configBlock ) {
@@ -1,20 +0,0 @@
1
- registry:
2
- - root: us-docker.pkg.dev
3
- - repositories:
4
- - name: stack
5
- charts:
6
- - api-server
7
- - authz-server
8
- - emailer
9
- - message-processor
10
- - name: leverege
11
- charts:
12
- - pubsub-pulse
13
- - pusher
14
- - overdose
15
- - name: cox-health
16
- charts:
17
- - actions-server
18
- - analytics-server
19
- - centrak-healthz
20
- - centrak-ingestor
@@ -1,96 +0,0 @@
1
- #!/usr/bin/env node
2
- /*
3
- * chart-to-registry will...
4
- */
5
- import fs from 'node:fs'
6
-
7
- import chalk from 'chalk'
8
- import commandLineArgs from 'command-line-args'
9
- import commandLineUsage from 'command-line-usage'
10
- import { lt as semverLt } from 'semver'
11
- import YAML from 'js-yaml'
12
-
13
- import {
14
- condir,
15
- debug,
16
- errorExit,
17
- log,
18
- warning,
19
- getGitRootDirectory,
20
- parsePackageJson,
21
- parseHelmChart,
22
- shellCmd } from './Utils.mjs'
23
-
24
- const commandLineOptions = [ // Use commandLineOptions to tie into the Usage statements
25
-
26
- {
27
- name : 'location',
28
- type : String,
29
- description : '{green the location of the artifact registry the chart will be pushed to (default us-docker.pkg.dev)}',
30
- },
31
- {
32
- name : 'project',
33
- type : String,
34
- description : '{green the name of the google project containing the npmrc and slack config secrets (default leverege-registry)}',
35
- },
36
- {
37
- name : 'repository',
38
- type : String,
39
- description : '{green the target repository to receive the pushed chart}',
40
- },
41
- {
42
- name : 'dry-run',
43
- type : Boolean,
44
- description : '{yellow perform everything except the actual chart push}',
45
- },
46
- {
47
- name : 'help',
48
- type : Boolean,
49
- description : '{green display this help screen}',
50
- },
51
-
52
- ]
53
-
54
- const sections = [
55
- {
56
- header : 'Leverege Helm Chart Compass (for helmup)',
57
- content : `{green This tool helps helmup navigate the helm charts stored in the
58
- artifact-registries.}`
59
- },
60
- { header : 'Options',
61
- optionList : commandLineOptions,
62
- },
63
- ]
64
-
65
- const args = commandLineArgs( commandLineOptions, { camelCase : true, partial : true } )
66
- const usage = commandLineUsage( sections )
67
-
68
- if ( args.help ) {
69
- log( usage )
70
- process.exit( 0 )
71
- }
72
-
73
- /* eslint-disable no-underscore-dangle */
74
- if ( args._unknown ) {
75
- log( usage )
76
- log( `\nUnrecognized argument [${chalk.bold.red( args._unknown )}]\n` )
77
- process.exit( 1 )
78
- }
79
- /* eslint-enable no-underscore-dangle */
80
-
81
- const minNodejsVersion = '18.0.0'
82
- if ( semverLt( process.version, minNodejsVersion ) ) {
83
- errorExit( `\n***ERROR: must be running at least node ${minNodejsVersion}\n` )
84
- }
85
-
86
- // First of all, fail if we are not in a git repository
87
- let gitRoot
88
- try {
89
- gitRoot = await getGitRootDirectory()
90
- } catch ( error ) {
91
- errorExit( chalk.red.bold( error ), { errorCode : 5 } )
92
- }
93
-
94
- const chartCompass = YAML.load( fs.readFileSync( './registry-compass.yaml', 'utf8' ) )
95
-
96
- condir( { chartCompass }, '<==Navigation' )