@leverege/build-tools 2.31.3 → 2.32.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.
@@ -1,7 +1,11 @@
1
- # This is the reserved static IP - see GCP -> VPC network -> IP addresses
1
+ # The service section controls the load balancer IP address for applying
2
+ # reserved static IPs and for creating a secondary LB for UDP traffic.
3
+ # See the *** UDP PORTS *** section below for more info.
4
+ #
2
5
  #service:
3
6
  # spec:
4
- # loadBalancerIP: xx.xx.xx.xx
7
+ # loadBalancerIP: "xx.xx.xx.xx"
8
+ # single: true # true by default, set to false for UDP support
5
9
 
6
10
  deployment:
7
11
  replicas: 3
@@ -14,3 +18,37 @@ logs:
14
18
  enabled: true
15
19
  format: json
16
20
  bufferingSize: 10
21
+
22
+ # Custom entry points may be added here - the first two are port definitions
23
+ # for both unsecured and secured MQTT ports used by connect. Note that the
24
+ # mqtts port has TLS termination performed by traefik and both ports are then
25
+ # forwarded to one open port (1883) on the target service. The vernemq service
26
+ # chart provides the IngressRouteTCP chart to make this happen.
27
+ #
28
+ #ports:
29
+ # mqtt:
30
+ # expose: true
31
+ # port: 1883
32
+ # protocol: TCP
33
+ # mqtts:
34
+ # expose: true
35
+ # port: 8883
36
+ # protocol: TCP
37
+ #
38
+ # *** UDP PORTS ***
39
+ # Traefik is also capable of providing UDP routes. However, since a GKE service
40
+ # may not currently support mixed protocols on one load balancer we must split
41
+ # the protocols across two different load balancers. k8s v1.24 supports the
42
+ # MixedProtocolLBService feature but this is not yet GA in GKE. Setting the
43
+ # service.single to false will enable the dual LB approach.
44
+ #
45
+ #service: <-- this is just an example of how to set this
46
+ # single: false <-- because this should appear at the top
47
+ #
48
+ # See the siren marine udp service chart ingressroute for an example of how to
49
+ # setup a traefik IngressRouteUDP route.
50
+ #ports:
51
+ # siren-udp:
52
+ # port: 1993
53
+ # expose: true
54
+ # protocol: UDP
@@ -81,3 +81,9 @@ resources:
81
81
  requests:
82
82
  cpu: "7000m"
83
83
  memory: "12Gi"
84
+
85
+ tolerations:
86
+ - key: "high-compute"
87
+ operator: "Equal"
88
+ value: "true"
89
+ effect: "NoSchedule"
package/src/helmup CHANGED
@@ -13,11 +13,13 @@ PLATFORM=(
13
13
  api-server
14
14
  db-curator
15
15
  emailer
16
+ fota-server
16
17
  imagine
17
18
  message-processor
18
19
  messenger
19
20
  reason
20
21
  resource-server
22
+ rule-engine
21
23
  scheduler
22
24
  transponder-bq
23
25
  transponder-rt
@@ -25,7 +27,7 @@ PLATFORM=(
25
27
  )
26
28
 
27
29
  SYSTEM=(
28
- elastic
30
+ elasticsearch
29
31
  redis
30
32
  postgres
31
33
  timescale-db
@@ -0,0 +1,629 @@
1
+ #!/usr/bin/env node
2
+ /* eslint-disable security/detect-unsafe-regex */
3
+ /* eslint-disable no-console */
4
+ /* eslint-disable max-len */
5
+
6
+ import cliArgs from 'command-line-args'
7
+ import cliHelp from 'command-line-usage'
8
+ import { $, fs } from 'zx'
9
+ import pkg from 'enquirer'
10
+ import colors from 'ansi-colors'
11
+ import path from 'path'
12
+ import { readPackage } from 'read-pkg'
13
+
14
+ const { prompt } = pkg
15
+
16
+ const NPMJS_TAGS = {
17
+ ALPHA : 'alpha',
18
+ BETA : 'beta',
19
+ LATEST : 'latest',
20
+ }
21
+
22
+ const DEFAULT_PACKAGES_PATH = './packages/*'
23
+
24
+ /**
25
+ * Functions
26
+ */
27
+
28
+ const validateVersionArg = ( { args } ) => {
29
+ if ( !args.version ) {
30
+ return
31
+ }
32
+
33
+ const isValid = /^\d+\.\d+\.\d+(-[a-zA-Z]+\.\d+)?$/.test( args.version )
34
+ if ( !isValid ) {
35
+ console.log( `
36
+ ${colors.bold.red( 'ERROR:' )} Invalid version arg: ${colors.bold.yellow( args.version )}.
37
+ Use SemVer specs (e.g: ${colors.bold.yellow( '2.25.5-beta.1' )}).
38
+ ` )
39
+ process.exit( 1 )
40
+ }
41
+ }
42
+
43
+ const validateNpmjsTag = ( { args, config } ) => {
44
+ const npmjsTags = Object.values( NPMJS_TAGS )
45
+ if ( args['npmjs-tag'] && !npmjsTags.includes( args['npmjs-tag'] ) ) {
46
+ console.log( `
47
+ ${colors.bold.red( 'ERROR:' )} Invalid npmjs tag: ${colors.bold.yellow( args['npmjs-tag'] )}.
48
+ Possible values: ${colors.bold.yellow( npmjsTags.join( ', ' ) )}.
49
+ ` )
50
+ process.exit( 1 )
51
+ }
52
+
53
+ if (
54
+ ( config?.isBetaRelease === true || args?.version?.includes( '-beta.' ) ) &&
55
+ args['npmjs-tag'] === NPMJS_TAGS.LATEST
56
+ ) {
57
+ console.log( `
58
+ ${colors.bold.red( 'ERROR:' )} It's not possible to publish a beta release to npmjs with tag ${colors.bold.yellow( 'latest' )}.
59
+ ` )
60
+ process.exit( 1 )
61
+ }
62
+ }
63
+
64
+ const validateArgs = ( args ) => {
65
+ validateVersionArg( { args } )
66
+ validateNpmjsTag( { args } )
67
+ }
68
+
69
+ const getCurrentBranch = async () => {
70
+ const { stdout } =
71
+ await $`git branch --show-current`
72
+ .nothrow()
73
+ .quiet()
74
+
75
+ return stdout.split( '\n' )[0]
76
+ }
77
+
78
+ const getLatestBranches = async ( { n = 10, branchFilter } ) => {
79
+ const grepFilter = branchFilter || ''
80
+
81
+ const { stdout } =
82
+ await $`git branch -r --sort=-committerdate --format "%(refname:lstrip=3)" | grep "${grepFilter}"`
83
+ .nothrow()
84
+ .quiet()
85
+
86
+ const branches = stdout.split( '\n' ).slice( 0, -1 ).filter( branch => branch !== 'HEAD' )
87
+ return branches.slice( 0, n )
88
+ }
89
+
90
+ const promptForBranch = async ( latestBranches, currentBranch ) => {
91
+ if ( latestBranches.length === 0 ) {
92
+ console.log( `
93
+ ${colors.bold.red( 'ERROR:' )} Could not find git branches.
94
+ ` )
95
+ process.exit( 1 )
96
+ }
97
+
98
+ const { branch } = await prompt( {
99
+ type : 'select',
100
+ name : 'branch',
101
+ message : 'Which branch would you like to release?',
102
+ choices : latestBranches.map( option => ( { value : option } ) ),
103
+ initial : currentBranch
104
+ } )
105
+ return branch
106
+ }
107
+
108
+ const getBranch = async ( branchFilter ) => {
109
+ const currentBranch = await getCurrentBranch()
110
+ const latestBranches = await getLatestBranches( branchFilter )
111
+ return promptForBranch( latestBranches, currentBranch )
112
+ }
113
+
114
+ const getGitRootDirectory = async () => {
115
+ const { stdout } = await $`git rev-parse --show-toplevel`.quiet()
116
+ return stdout.split( '\n' )[0]
117
+ }
118
+
119
+ const getSubDirectories = async ( repositoryRoot, directory ) => {
120
+ const absolutePathDirectory = path.join( repositoryRoot, directory )
121
+ const relativeDirectory = path.relative( repositoryRoot, absolutePathDirectory )
122
+ try {
123
+ const entries = await fs.promises.readdir( absolutePathDirectory, { withFileTypes : true } )
124
+ const subDirectories = entries.filter( entry => entry.isDirectory() )
125
+ return subDirectories.map( entry => path.join( relativeDirectory, entry.name ) )
126
+ } catch ( err ) {
127
+ return []
128
+ }
129
+ }
130
+
131
+ const fileExists = async ( filePath ) => {
132
+ try {
133
+ await fs.promises.access( filePath )
134
+ return true
135
+ } catch ( err ) {
136
+ return false
137
+ }
138
+ }
139
+
140
+ const findPackagesInDirectories = async ( repositoryRoot, directories ) => {
141
+ return directories.reduce( async ( accPromise, directory ) => {
142
+ const acc = await accPromise
143
+ const hasWildcard = directory.endsWith( '*' )
144
+ const basePath = hasWildcard ? directory.slice( 0, -1 ) : directory
145
+ const directoriesToSearch = hasWildcard ?
146
+ await getSubDirectories( repositoryRoot, basePath ) :
147
+ [ basePath ]
148
+
149
+ for ( let i = 0; i < directoriesToSearch.length; i++ ) {
150
+ const currentDirectory = directoriesToSearch[i]
151
+ const pkgPath = path.join( directoriesToSearch[i], 'package.json' )
152
+ const pkgExists = await fileExists( path.join( repositoryRoot, pkgPath ) ) // eslint-disable-line no-await-in-loop
153
+ if ( pkgExists ) {
154
+ acc.push( currentDirectory )
155
+ }
156
+ }
157
+ return acc
158
+
159
+ }, Promise.resolve( [] ) )
160
+ }
161
+
162
+ const getMonorepoPackagePaths = async ( repositoryRoot, packagesPath ) => {
163
+ let pkg
164
+ try {
165
+ pkg = await readPackage( { cwd : repositoryRoot } )
166
+ } catch ( err ) {}
167
+
168
+ return findPackagesInDirectories( repositoryRoot, pkg?.workspaces || [ packagesPath ] )
169
+ }
170
+
171
+ const selectPackageToUpdate = async ( repositoryRoot, packagePaths ) => {
172
+ const currentPath = process.cwd()
173
+ const currentPackageRelativePath = path.relative( repositoryRoot, currentPath )
174
+
175
+ const { packageName } = await prompt( {
176
+ type : 'select',
177
+ name : 'packageName',
178
+ message : 'What package are you releasing?',
179
+ choices : packagePaths,
180
+ initial : currentPackageRelativePath
181
+ } )
182
+
183
+ return path.join( repositoryRoot, packageName )
184
+ }
185
+
186
+ const getPackagePath = async ( { repositoryRoot, packagesPath = DEFAULT_PACKAGES_PATH } ) => {
187
+ const packagePaths = await getMonorepoPackagePaths( repositoryRoot, packagesPath )
188
+ if ( packagePaths.length > 0 ) {
189
+ return selectPackageToUpdate( repositoryRoot, packagePaths )
190
+ }
191
+
192
+ return repositoryRoot
193
+ }
194
+
195
+ const checkoutToBranch = async ( branch ) => {
196
+ try {
197
+ await $`git checkout ${branch}`
198
+ } catch ( err ) {
199
+ console.log( err.stderr || err )
200
+ process.exit( 1 )
201
+ }
202
+ }
203
+
204
+ const getPackageJsonVersion = async ( packagePath ) => {
205
+ if ( !packagePath ) {
206
+ console.log( `
207
+ ${colors.bold.red( 'ERROR:' )} Could not find a package.json file.
208
+ The tag-release script must run from a npm project.
209
+ ` )
210
+ return process.exit( 1 )
211
+ }
212
+
213
+ const packageJson = await readPackage( { cwd : packagePath } )
214
+ return packageJson.version
215
+ }
216
+
217
+ const getNextVersions = ( currentVersion ) => {
218
+ const [ major, minor, patch, beta ] = currentVersion.split( /\.|-beta\./ ).map( Number )
219
+
220
+ const nextMajor = `${major + 1}.0.0`
221
+ const nextMinor = `${major}.${minor + 1}.0`
222
+ const nextPatch = `${major}.${minor}.${patch + 1}`
223
+ const nextBeta = beta ? `${major}.${minor}.${patch}-beta.${beta + 1}` : `${major}.${minor}.${patch + 1}-beta.1`
224
+
225
+ return {
226
+ nextMajor,
227
+ nextMinor,
228
+ nextPatch,
229
+ nextBeta,
230
+ }
231
+ }
232
+
233
+ const promptForVersion = async ( currentVersion ) => {
234
+ const { nextMajor, nextMinor, nextPatch, nextBeta } = getNextVersions( currentVersion )
235
+ const choices = [
236
+ { hint : '(major release)', value : nextMajor },
237
+ { hint : '(minor release)', value : nextMinor },
238
+ { hint : '(patch release)', value : nextPatch },
239
+ { hint : '(beta release)', value : nextBeta },
240
+ { value : 'custom' },
241
+ ]
242
+ const { version } = await prompt( {
243
+ type : 'select',
244
+ name : 'version',
245
+ message : `What version are you releasing (current version is ${currentVersion})?`,
246
+ choices,
247
+ } )
248
+
249
+ if ( version === 'custom' ) {
250
+ const { customVersion } = await prompt( {
251
+ type : 'input',
252
+ name : 'customVersion',
253
+ message : `What custom version are you releasing (current version is ${currentVersion})?`,
254
+ initial : currentVersion
255
+ } )
256
+ return customVersion
257
+ }
258
+
259
+ return version
260
+ }
261
+
262
+ const getVersion = async ( { branch, packagePath } ) => {
263
+ await checkoutToBranch( branch )
264
+ const currentVersion = await getPackageJsonVersion( packagePath )
265
+ return promptForVersion( currentVersion )
266
+ }
267
+
268
+ const getPackageName = async ( { packagePath } ) => {
269
+ const noTrailingSlashPath = packagePath.slice( -1 ) === '/' ?
270
+ packagePath.substr( 0, packagePath.length - 1 ) :
271
+ packagePath
272
+ return noTrailingSlashPath.split( '/' ).slice( -1 )[0]
273
+ }
274
+
275
+ const getBuildMessage = ( { isPackageInRepositoryRoot, packageName, version } ) => {
276
+ if ( isPackageInRepositoryRoot ) {
277
+ return `BUILD v${version}`
278
+ }
279
+ return `BUILD ${packageName}/v${version}`
280
+ }
281
+
282
+ const getGitTagSuffix = async () => {
283
+ const { tagSuffix } = await prompt( {
284
+ type : 'input',
285
+ name : 'tagSuffix',
286
+ message : 'What suffix you like to add to the tag name for git? (e.g: "-RC.1" for v1.2.3-RC.1)',
287
+ } )
288
+ return tagSuffix
289
+ }
290
+
291
+ const confirmPushCommit = async ( buildMessage ) => {
292
+ const { confirm } = await prompt( [ {
293
+ type : 'confirm',
294
+ name : 'confirm',
295
+ message : `${colors.bold.red( '[Warning]' )} Commit and push ${colors.bold.yellow( buildMessage )} to git remote?`
296
+ } ] )
297
+ return confirm
298
+ }
299
+
300
+ const isPackageInRepositoryRoot = async ( { repositoryRoot, packagePath } ) => {
301
+ return repositoryRoot === packagePath
302
+ }
303
+
304
+ const promptForNpmjsTag = async ( { isBetaRelease } ) => {
305
+ const choices = Object.values( NPMJS_TAGS ).map( option => ( {
306
+ value : option,
307
+ ...( ( isBetaRelease && option === NPMJS_TAGS.LATEST ) && { disabled : '(not available for beta releases)' } )
308
+ } ) )
309
+ const { npmjsTag } = await prompt( {
310
+ type : 'select',
311
+ name : 'npmjsTag',
312
+ message : 'Which npmjs tag would you like to use when publishing?',
313
+ choices,
314
+ initial : isBetaRelease ? NPMJS_TAGS.BETA : NPMJS_TAGS.LATEST,
315
+ } )
316
+ return npmjsTag
317
+ }
318
+
319
+ const confirmTagRelease = async ( { isBetaRelease, publishable } ) => {
320
+ const message = [
321
+ 'Releasing will commit',
322
+ isBetaRelease ? ' and push' : ', push, and tag',
323
+ ' the version in git',
324
+ publishable ? ' and npm' : '',
325
+ '. Proceed?'
326
+ ].join( '' )
327
+
328
+ const { confirmResponse } = await prompt( {
329
+ type : 'select',
330
+ name : 'confirmResponse',
331
+ message,
332
+ choices : [ 'yes', 'no', 'advanced' ],
333
+ initial : 'yes',
334
+ } )
335
+
336
+ if ( confirmResponse === 'no' ) {
337
+ console.log( 'Aborting...' )
338
+ process.exit()
339
+ }
340
+
341
+ return confirmResponse
342
+ }
343
+
344
+ const isWorkspacePackage = async () => {
345
+ const gitRootDirectory = await getGitRootDirectory()
346
+ try {
347
+ const packageJson = await readPackage( { cwd : gitRootDirectory } )
348
+ return packageJson?.workspaces?.length > 0
349
+ } catch ( err ) {
350
+ return false
351
+ }
352
+ }
353
+
354
+ const updateNpmPackageJsonAndLock = async ( config ) => {
355
+ const { version, packagePath, isPackageInRepositoryRoot } = config
356
+
357
+ const isWorkspace = await isWorkspacePackage()
358
+
359
+ try {
360
+ if ( !isPackageInRepositoryRoot ) {
361
+ await $`npm version --no-git-tag-version ${version} --prefix ${packagePath}`
362
+ if ( isWorkspace ) {
363
+ await $`npm install`
364
+ } else {
365
+ await $`npm install --prefix ${packagePath}`
366
+ }
367
+ } else {
368
+ await $`npm version --no-git-tag-version ${version}`
369
+ }
370
+ } catch ( err ) {
371
+ console.log( err.stderr || err )
372
+ process.exit( 1 )
373
+ }
374
+ }
375
+
376
+ const createNewBuildCommit = async ( { buildMessage } ) => {
377
+ try {
378
+ await $`git add .`
379
+ await $`git commit -m ${buildMessage}`
380
+ } catch ( err ) {
381
+ console.log( err.stderr || err )
382
+ process.exit( 1 )
383
+ }
384
+ }
385
+
386
+ const pushToGitRemote = async () => {
387
+ try {
388
+ await $`git push`
389
+ } catch ( err ) {
390
+ console.log( err.stderr || err )
391
+ process.exit( 1 )
392
+ }
393
+ }
394
+
395
+ const commitAndPushNewBuild = async ( config ) => {
396
+ const { buildMessage, noConfirm } = config
397
+
398
+ const confirmAnswer = noConfirm || await confirmPushCommit( buildMessage )
399
+ if ( !confirmAnswer ) {
400
+ console.log( 'Aborting...' )
401
+ process.exit()
402
+ }
403
+
404
+ await updateNpmPackageJsonAndLock( config )
405
+ await createNewBuildCommit( config )
406
+ await pushToGitRemote()
407
+ }
408
+
409
+ const confirmPushTag = async ( tagName ) => {
410
+ const { confirm } = await prompt( [ {
411
+ type : 'confirm',
412
+ name : 'confirm',
413
+ message : `${colors.bold.red( '[Warning]' )} Push new tag ${colors.bold.yellow( tagName )} to git remote?`
414
+ } ] )
415
+ return confirm
416
+ }
417
+
418
+ const createGitTag = async ( tagName ) => {
419
+ try {
420
+ await $`git tag ${tagName}`
421
+ } catch ( err ) {
422
+ console.log( err.stderr || err )
423
+ process.exit( 1 )
424
+ }
425
+ }
426
+
427
+ const pushGitTag = async ( tagName ) => {
428
+ try {
429
+ await $`git push origin ${tagName}`
430
+ } catch ( err ) {
431
+ console.log( err.stderr || err )
432
+ process.exit( 1 )
433
+ }
434
+ }
435
+
436
+ const createAndPushGitTag = async ( { tagName, noConfirm } ) => {
437
+ const confirmAnswer = noConfirm || await confirmPushTag( tagName )
438
+ if ( confirmAnswer ) {
439
+ await createGitTag( tagName )
440
+ await pushGitTag( tagName )
441
+ }
442
+ }
443
+
444
+ const confirmPublishToNpmjs = async ( version, npmjsTag ) => {
445
+ const { confirm } = await prompt( [ {
446
+ type : 'confirm',
447
+ name : 'confirm',
448
+ message : `${colors.bold.red( '[Warning]' )} Publish new version ${colors.bold.yellow( version )} to npmjs with tag ${colors.bold.yellow( npmjsTag )}?`
449
+ } ] )
450
+ return confirm
451
+ }
452
+
453
+ const publishToNpmjs = async ( { version, npmjsTag, noConfirm } ) => {
454
+ const confirmAnswer = noConfirm || await confirmPublishToNpmjs( version, npmjsTag )
455
+ if ( !confirmAnswer ) {
456
+ console.log( 'Aborting...' )
457
+ process.exit()
458
+ }
459
+
460
+ try {
461
+ await $`npm publish --tag ${npmjsTag}`
462
+ } catch ( err ) {
463
+ console.log( err.stderr || err )
464
+ process.exit( 1 )
465
+ }
466
+ }
467
+
468
+ const displayReleaseInfo = ( config ) => {
469
+ const {
470
+ branch,
471
+ version,
472
+ repositoryRoot,
473
+ packageName,
474
+ packagePath,
475
+ buildMessage,
476
+ tagName,
477
+ publishable,
478
+ npmjsTag,
479
+ isBetaRelease
480
+ } = config
481
+
482
+ console.log( `
483
+
484
+ ${colors.bold.green( '============ Tag Release Summary ============' )}
485
+ ${colors.blue( 'Branch:' )} ${branch}
486
+ ${colors.blue( 'Version:' )} ${version}
487
+ ${colors.blue( 'Root directory:' )} ${repositoryRoot}
488
+ ${colors.blue( 'Package name:' )} ${packageName}
489
+ ${colors.blue( 'package.json path:' )} ${path.join( packagePath, 'package.json' )}${buildMessage ? `
490
+ ${colors.blue( 'Commit message:' )} ${buildMessage}` : ''}${isBetaRelease ? '' : `
491
+ ${colors.blue( 'Git tag:' )} ${tagName}`}${publishable ? `
492
+ ${colors.blue( 'Npmjs tag:' )} ${npmjsTag}` : ''}
493
+ ${colors.bold.green( '=============================================' )}
494
+ ` )
495
+ }
496
+
497
+ /**
498
+ * Script
499
+ */
500
+
501
+ const optionList = [
502
+ {
503
+ name : 'branch',
504
+ type : String,
505
+ alias : 'b',
506
+ description : 'branch where the tag will be created',
507
+ },
508
+ {
509
+ name : 'npmjs-tag',
510
+ type : String,
511
+ alias : 'n',
512
+ description : 'npmjs package tag to be used when publishing (for npmjs lib repositories)',
513
+ typeLabel : 'alpha|beta|latest'
514
+ },
515
+ {
516
+ name : 'version',
517
+ type : String,
518
+ alias : 'v',
519
+ description : 'version to be tagged',
520
+ },
521
+ {
522
+ name : 'publishable',
523
+ type : Boolean,
524
+ alias : 'p',
525
+ description : 'flag to indicate the repository is publishable to npmjs',
526
+ },
527
+ {
528
+ name : 'package-path',
529
+ type : String,
530
+ alias : 'a',
531
+ description : 'relative path to the package from the projec\'s root in case it\'s a monorepo',
532
+ },
533
+ {
534
+ name : 'tag-suffix',
535
+ type : String,
536
+ alias : 't',
537
+ description : 'tag suffix to be appended to the version when pushing to git',
538
+ },
539
+ {
540
+ name : 'branch-filter',
541
+ type : String,
542
+ alias : 'f',
543
+ description : 'branch filter used to filter available branches in interactive mode',
544
+ },
545
+ {
546
+ name : 'no-commit',
547
+ type : Boolean,
548
+ description : 'do not create a new commit on git (in case the goal is just tagging it)',
549
+ },
550
+ {
551
+ name : 'no-confirm',
552
+ type : Boolean,
553
+ description : 'push to git and publish to npmjs without asking for confirmation',
554
+ },
555
+ {
556
+ name : 'help',
557
+ type : Boolean,
558
+ alias : 'h',
559
+ description : 'show this help',
560
+ },
561
+ ]
562
+
563
+ const sections = [
564
+ {
565
+ header : 'Tag release script',
566
+ content : 'This script is intended to give users a simple way to create git tags, push them and publish to Npmjs (if the --publishable flag is passed)',
567
+ },
568
+ { header : 'Options',
569
+ optionList,
570
+ },
571
+ ]
572
+
573
+ const args = cliArgs( optionList, { partial : true } )
574
+ const help = cliHelp( sections )
575
+
576
+ if ( args.help ) {
577
+ console.log( help )
578
+ process.exit()
579
+ }
580
+
581
+ validateArgs( args )
582
+
583
+ const config = {}
584
+
585
+ config.noConfirm = !!args['no-confirm']
586
+
587
+ config.noCommit = !!args['no-commit']
588
+
589
+ config.repositoryRoot = await getGitRootDirectory()
590
+
591
+ config.branch = args.branch || await getBranch( { branchFilter : args['branch-filter'] } )
592
+
593
+ const argsPackagePath = args['package-path'] && path.join( config.repositoryRoot, args['package-path'] )
594
+ config.packagePath = argsPackagePath || await getPackagePath( config )
595
+
596
+ config.isPackageInRepositoryRoot = await isPackageInRepositoryRoot( config )
597
+
598
+ config.version = args.version || await getVersion( config )
599
+
600
+ config.packageName = await getPackageName( config )
601
+
602
+ config.buildMessage = config.noCommit ? '' : getBuildMessage( config )
603
+
604
+ config.isBetaRelease = config.version.includes( '-beta.' )
605
+
606
+ if ( !config.isBetaRelease ) {
607
+ const tagSuffix = args['tag-suffix'] ?? await getGitTagSuffix()
608
+ const tagPrefix = config.isPackageInRepositoryRoot ? '' : `${config.packageName}/`
609
+ config.tagName = `${tagPrefix}v${config.version}${tagSuffix}`
610
+ }
611
+
612
+ config.publishable = !!args.publishable
613
+ if ( config.publishable ) {
614
+ validateNpmjsTag( { config, args } )
615
+ config.npmjsTag = args['npmjs-tag'] || await promptForNpmjsTag( config )
616
+ }
617
+
618
+ displayReleaseInfo( config )
619
+
620
+ const confirmResponse = await confirmTagRelease( config )
621
+ if ( confirmResponse === 'yes' ) {
622
+ config.noConfirm = true
623
+ }
624
+
625
+ if ( !config.noCommit ) { await commitAndPushNewBuild( config ) }
626
+ if ( !config.isBetaRelease ) { await createAndPushGitTag( config ) }
627
+ if ( config.publishable ) { await publishToNpmjs( config ) }
628
+
629
+ process.exit()