@leverege/build-tools 2.105.3 → 2.106.1

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.
@@ -68,6 +68,16 @@
68
68
  "runtimeExecutable": "node",
69
69
  "console": "integratedTerminal"
70
70
  },
71
+ {
72
+ "name": "hook-and-release pubsub-pulse",
73
+ "type": "node",
74
+ "request": "launch",
75
+ "program": "${workspaceFolder}/src/hook-and-release.mjs",
76
+ "args": [""],
77
+ "cwd": "/Users/john/Work/leverege/cicd/@srv/pubsub-pulse",
78
+ "runtimeExecutable": "node",
79
+ "console": "integratedTerminal"
80
+ },
71
81
  {
72
82
  "name": "ingestor in monorepo",
73
83
  "type": "node",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leverege/build-tools",
3
- "version": "2.105.3",
3
+ "version": "2.106.1",
4
4
  "description": "A collection of build / support tools for Leverege developers",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -74,6 +74,10 @@
74
74
  "node": "^22.22 || >=24.15",
75
75
  "npm": ">=11.10"
76
76
  },
77
+ "docker": {
78
+ "node": "24.14.0-alpine3.23",
79
+ "npm": "11.12.0"
80
+ },
77
81
  "license": "SEE LICENSE IN LICENSE.md",
78
82
  "dependencies": {
79
83
  "@kubernetes/client-node": "^1.4.0",
@@ -90,11 +94,11 @@
90
94
  "googleapis": "^173.0.0",
91
95
  "handlebars": "^4.7.9",
92
96
  "ignore": "^7.0.5",
93
- "inquirer": "14.0.0",
94
- "js-yaml": "^4.1.1",
97
+ "inquirer": "14.0.2",
98
+ "js-yaml": "^4.2.0",
95
99
  "jsdoc": "^4.0.5",
96
100
  "ms": "^2.1.3",
97
- "npm-registry-fetch": "^20.0.0",
101
+ "npm-registry-fetch": "^20.0.1",
98
102
  "ora": "^9.4.0",
99
103
  "p-limit": "^7.3.0",
100
104
  "package-up": "^5.0.0",
package/src/Docker.mjs CHANGED
@@ -7,6 +7,7 @@ import chalk from 'chalk'
7
7
  import handlebars from 'handlebars'
8
8
 
9
9
  import {
10
+ BUILD_TOOLS_DOCKER,
10
11
  errorExit,
11
12
  getCleanTag,
12
13
  getDateTimestamp,
@@ -19,14 +20,10 @@ import {
19
20
 
20
21
  const DIRNAME = path.dirname( url.fileURLToPath( import.meta.url ) )
21
22
 
22
- // TODO: This is a temporary band-aid while we assess the impact of the yarn
23
- // and/or CI pipeline transition. This will at least allow us to lock down the
24
- // specific versions of node/npm and facilitate testing via the env vars.
25
- //
26
23
  // See the latest docker images here => https://hub.docker.com/_/node
27
- //
28
- const dockerfileNodeVersion = process.env.DOCKER_BUILD_NODE_VERSION || '24.14.0-alpine3.23'
29
- const dockerfileNpmVersion = process.env.DOCKER_BUILD_NPM_VERSION || '11.12.0'
24
+ // Versions are defined in package.json "docker" stanza; env vars allow per-build overrides.
25
+ const dockerfileNodeVersion = process.env.DOCKER_BUILD_NODE_VERSION || BUILD_TOOLS_DOCKER.node
26
+ const dockerfileNpmVersion = process.env.DOCKER_BUILD_NPM_VERSION || BUILD_TOOLS_DOCKER.npm
30
27
 
31
28
  // The contents of these variables were initially located in files that live in
32
29
  // the build-tools repository, but it just became simpler to pull the contents
package/src/Utils.mjs CHANGED
@@ -17,6 +17,14 @@ import YAML from 'js-yaml'
17
17
  // this assumes this file lives in the src dir of the build-tools repo
18
18
  export const BUILD_TOOLS_ROOT = process.env.BUILD_TOOLS_ROOT || path.dirname( url.fileURLToPath( import.meta.url ) )
19
19
 
20
+ // load the package.json to get the docker image and minimum node version - we use this
21
+ // in multiple places so good to centralize here
22
+ // eslint-disable-next-line security/detect-non-literal-fs-filename
23
+ const btPkg = JSON.parse( fs.readFileSync( path.join( BUILD_TOOLS_ROOT, '../package.json' ), 'utf8' ) )
24
+ export const BUILD_TOOLS_DOCKER = btPkg.docker
25
+ export const BUILD_TOOLS_MIN_NODE = semver.minVersion( btPkg.engines?.node ?? '22.0.0' )?.version ?? '22.0.0'
26
+ export const BUILD_TOOLS_MIN_NPM = semver.minVersion( btPkg.engines?.npm ?? '11.10.0' )?.version ?? '11.10.0'
27
+
20
28
  let debugEnabled = process.env.BUILD_TOOLS_DEBUG === '1'
21
29
 
22
30
  export const enableDebug = () => { debugEnabled = true }
@@ -625,7 +633,10 @@ export const getRepositoryDescr = async () => {
625
633
  const gitRoot = await getGitRootDirectory()
626
634
  const gitHooksPath = await getGitHooksPath()
627
635
  const { branch : gitBranch, upstream : gitUpstream } = await getGitBranchAndUpstream()
628
- const subPkgs = await glob( `${gitRoot}/{apps,packages}/*/**/package.json`, { ignore : '/**/node_modules/**' } )
636
+ const subPkgs = await glob(
637
+ `${gitRoot}/{apps,packages}/**/{package.json,pyproject.toml}`,
638
+ { ignore : [ '/**/node_modules/**', '/**/.venv/**' ] }
639
+ )
629
640
  const helmChart = await parseHelmChart()
630
641
  const rootPackageJson = await parseJsonFile( `${gitRoot}/package.json` )
631
642
  const rootPyProjectToml = await parsePyProjectToml( `${gitRoot}/pyproject.toml` )
@@ -11,6 +11,7 @@ import { lt as semverLt } from 'semver'
11
11
  import YAML from 'js-yaml'
12
12
 
13
13
  import {
14
+ BUILD_TOOLS_MIN_NODE,
14
15
  BUILD_TOOLS_ROOT,
15
16
  debug,
16
17
  errorExit,
@@ -77,9 +78,8 @@ if ( args._unknown ) {
77
78
  }
78
79
  /* eslint-enable no-underscore-dangle */
79
80
 
80
- const minNodejsVersion = '22.13.0'
81
- if ( semverLt( process.version, minNodejsVersion ) ) {
82
- warning( `suggest upgrading to at least node ${minNodejsVersion}\n` )
81
+ if ( semverLt( process.version, BUILD_TOOLS_MIN_NODE ) ) {
82
+ warning( `suggest upgrading to at least node ${BUILD_TOOLS_MIN_NODE}\n` )
83
83
  }
84
84
 
85
85
  // First of all, fail if we are not in a git repository
@@ -1,15 +1,13 @@
1
1
  #!/usr/bin/env node
2
- /*
3
- * chart-to-registry will...
4
- */
2
+
5
3
  import { existsSync, rmSync } from 'node:fs'
6
4
 
7
5
  import chalk from 'chalk'
8
- import commandLineArgs from 'command-line-args'
9
- import commandLineUsage from 'command-line-usage'
6
+ import { Command } from 'commander'
10
7
  import { lt as semverLt } from 'semver'
11
8
 
12
9
  import {
10
+ BUILD_TOOLS_MIN_NODE,
13
11
  debug,
14
12
  errorExit,
15
13
  establishOauthAccess,
@@ -20,105 +18,44 @@ import {
20
18
  warning,
21
19
  } from './Utils.mjs'
22
20
 
23
- const commandLineOptions = [ // Use commandLineOptions to tie into the Usage statements
24
- {
25
- name : 'chart',
26
- type : String,
27
- defaultValue : 'helm',
28
- description : '{green directory containing the chart - default: helm}',
29
- },
30
- {
31
- name : 'location',
32
- type : String,
33
- description : '{green the location of the artifact registry the chart will be pushed to (default us-docker.pkg.dev)}',
34
- },
35
- {
36
- name : 'project',
37
- type : String,
38
- description : '{green the name of the google project containing the npmrc and slack config secrets (default leverege-registry)}',
39
- },
40
- {
41
- name : 'repository',
42
- type : String,
43
- description : '{green the target repository to receive the pushed chart}',
44
- },
45
- {
46
- name : 'auth-only',
47
- type : Boolean,
48
- description : '{green update artifact registry auth token and exit}',
49
- },
50
- {
51
- name : 'ignore-appv',
52
- type : Boolean,
53
- description : '{green ignore the Char.yaml appVersion format}',
54
- },
55
- {
56
- name : 'dry-run',
57
- type : Boolean,
58
- description : '{yellow perform everything except the actual chart push}',
59
- },
60
- {
61
- name : 'force',
62
- type : Boolean,
63
- description : '{yellow push the chart even if it already exists in the registry}',
64
- },
65
- {
66
- name : 'help',
67
- type : Boolean,
68
- description : '{green display this help screen}',
69
- },
70
- ]
71
-
72
- const sections = [
73
- {
74
- header : 'Leverege Helm Chart to Artifact Registry',
75
- content : `{green This tool is responsible for pushing a helm chart to its designated GCP
76
- Artifact Registry repository.}`
77
- },
78
- { header : 'Options',
79
- optionList : commandLineOptions,
80
- },
81
- ]
82
-
83
- const args = commandLineArgs( commandLineOptions, { camelCase : true, partial : true } )
84
- const usage = commandLineUsage( sections )
85
-
86
- if ( args.help ) {
87
- log( usage )
88
- process.exit( 0 )
89
- }
90
-
91
- /* eslint-disable no-underscore-dangle */
92
- if ( args._unknown ) {
93
- log( usage )
94
- log( `\nUnrecognized argument [${chalk.bold.red( args._unknown )}]\n` )
95
- process.exit( 1 )
96
- }
97
- /* eslint-enable no-underscore-dangle */
98
-
99
- const minNodejsVersion = '22.0.0'
100
- if ( semverLt( process.version, minNodejsVersion ) ) {
101
- errorExit( `\n***ERROR: must be running at least node ${minNodejsVersion}\n` )
21
+ const program = new Command()
22
+
23
+ program
24
+ .configureHelp( { styleOptionTerm : str => chalk.bold.white( str ) } )
25
+ .description( chalk.green( 'Pushes a helm chart to its designated GCP Artifact Registry repository.' ) )
26
+ .option( '--chart <directory>', chalk.green( 'directory containing the chart' ), 'helm' )
27
+ .option( '--location <location>', chalk.green( 'location of the artifact registry (default: from values.yaml)' ) )
28
+ .option( '--project <project>', chalk.green( 'GCP project containing the registry (default: from values.yaml)' ) )
29
+ .option( '--repository <repository>', chalk.green( 'target repository to receive the pushed chart' ) )
30
+ .option( '--auth-only', chalk.green( 'update artifact registry auth token and exit' ) )
31
+ .option( '--ignore-appv', chalk.green( 'ignore the Chart.yaml appVersion format check' ) )
32
+ .option( '--refresh-deps', chalk.green( 'force a helm dependency update before pushing' ) )
33
+ .option( '--dry-run', chalk.yellow( 'perform everything except the actual chart push' ) )
34
+ .option( '--force', chalk.yellow( 'push the chart even if it already exists in the registry' ) )
35
+
36
+ program.parse( process.argv )
37
+ const opts = program.opts()
38
+
39
+ if ( semverLt( process.version, BUILD_TOOLS_MIN_NODE ) ) {
40
+ errorExit( `\n***ERROR: must be running at least node ${BUILD_TOOLS_MIN_NODE}\n` )
102
41
  }
103
42
 
104
43
  // load up all we need to know about the chart
105
- const helmChart = await parseHelmChart( args.chart )
44
+ const helmChart = await parseHelmChart( opts.chart )
106
45
 
107
- if ( !helmChart.chartAppVersion.startsWith( 'v' ) && !args.ignoreAppv ) {
46
+ if ( !helmChart.chartAppVersion.startsWith( 'v' ) && !opts.ignoreAppv ) {
108
47
  warning( 'Chart.yaml appVersion does not begin with the letter "v"\n' )
109
48
  await proceed( 'You sure about this?' )
110
49
  }
111
50
 
112
- // helm push helm-package.tgz oci://REGISTRY_LOCATION/REGISTRY_PROJECT/REGISTRY_REPOSITORY/charts
113
- //
114
- const registryLocation = args.location || helmChart.registryLocation
115
- const registryProject = args.project || helmChart.registryProject
116
- const registryRepository = args.repository || helmChart.registryRepository
51
+ const registryLocation = opts.location || helmChart.registryLocation
52
+ const registryProject = opts.project || helmChart.registryProject
53
+ const registryRepository = opts.repository || helmChart.registryRepository
117
54
 
118
55
  // deal with oauth token shenanigans
119
56
  const oauthResults = await establishOauthAccess( registryLocation )
120
57
  debug( { oauthResults, registryLocation }, '<===OAuth Login' )
121
- if ( args.authOnly ) {
58
+ if ( opts.authOnly ) {
122
59
  process.exit( 0 )
123
60
  }
124
61
 
@@ -146,7 +83,7 @@ const {
146
83
  try {
147
84
  await shellCmd( `helm pull ${ociPushEndpoint}/${chartName} --version ${chartVersion}` )
148
85
  rmSync( chartPackage )
149
- if ( args.force ) {
86
+ if ( opts.force ) {
150
87
  warning( `chart ${chartName} version ${chartVersion} exists - force pushing` )
151
88
  } else {
152
89
  errorExit( `\n***ERROR: chart ${chartName} version ${chartVersion} already exists` )
@@ -155,7 +92,7 @@ try {
155
92
  debug( `Chart ${chartName} version ${chartVersion} does not exist - proceeding` )
156
93
  }
157
94
 
158
- if ( depsOutOfSync ) {
95
+ if ( depsOutOfSync || opts.refreshDeps ) {
159
96
  try {
160
97
  log( chalk.yellow.bold( '\nChart dependedencies are out of sync - updating...\n' ) )
161
98
  await shellCmd( 'helm dependency update ./helm', { stdio : 'inherit' } )
@@ -165,14 +102,14 @@ if ( depsOutOfSync ) {
165
102
  }
166
103
 
167
104
  try {
168
- await shellCmd( `helm package ${args.chart}` )
105
+ await shellCmd( `helm package ${opts.chart}` )
169
106
  if ( !existsSync( chartPackage ) ) { // eslint-disable-line security/detect-non-literal-fs-filename
170
107
  errorExit( `\n***ERROR: expected helm package to produce ${chartPackage}` )
171
108
  }
172
109
 
173
110
  log( `\nPushing ${chalk.green.bold( chartPackage )} => ${chalk.green.bold( ociPushEndpoint )}` )
174
111
  const pushItRealGood = `helm push ${chartPackage} ${ociPushEndpoint}`
175
- if ( !args.dryRun ) {
112
+ if ( !opts.dryRun ) {
176
113
  await shellCmd( pushItRealGood )
177
114
  } else {
178
115
  log( `\nDry run => ${chalk.green.bold( pushItRealGood )}` )
@@ -147,6 +147,7 @@ export default class Config {
147
147
  this.gitBranch = repoDescr.gitBranch
148
148
  this.gitHooksPath = repoDescr.gitHooksPath
149
149
  this.isMonoRepo = repoDescr.isMonoRepo
150
+ this.isYarnProject = repoDescr.isYarnProject
150
151
 
151
152
  const harHook = '.har'
152
153
  this.harDir = `${this.gitRoot}/${harHook}`
@@ -258,7 +259,7 @@ export default class Config {
258
259
 
259
260
  // for each script run sequentially
260
261
  for ( const script of scripts ) {
261
- const cmd = `npm run ${script}`
262
+ const cmd = this.isYarnProject ? `yarn ${script}` : `npm run ${script}`
262
263
  log( `hook-and-release in ${chalk.green( runDirectory )} => ${chalk.green( cmd )}` )
263
264
  if ( !this.cliArgs.debug ) {
264
265
  try {
@@ -6,5 +6,5 @@ apiVersion: v2
6
6
  icon: https://raw.githubusercontent.com/kubernetes/kubernetes/master/logo/logo.svg
7
7
  dependencies:
8
8
  - name: leverege
9
- version: "^1.1.0"
9
+ version: "^1.1.3"
10
10
  repository: "oci://us-docker.pkg.dev/leverege-registry/base-charts"
@@ -19,6 +19,7 @@ import { Chartwright } from './Chartwright.mjs'
19
19
  program
20
20
  .name( 'init-my-chart' )
21
21
  .description( 'Initialize a helm chart based on the latest Leverege leaf template' )
22
+ .option( '--preserve-old', 'Preserve existing helm chart by moving it to helm-old (instead of deleting it)' )
22
23
  .option( '--dry-run', 'Print output to console instead of generating the char' )
23
24
  .option( '--debug', 'Enable debug logging - use BUILD_TOOLS_DEBUG=1 for global' )
24
25
  .parse()
@@ -71,5 +72,10 @@ if ( options.dryRun ) {
71
72
  await chartwright.scribe( { Container, Chart, Values, ValuesText, Registry } )
72
73
 
73
74
  if ( movedOldHelm ) {
74
- log( chalk.yellow( '\nAn existing helm chart was detected and moved to helm-old. Please review and migrate any customizations as needed.' ) )
75
+ if ( options.preserveOld ) {
76
+ log( chalk.yellow( '\nAn existing helm chart was detected and moved to helm-old. Please review and migrate any customizations as needed.' ) )
77
+ } else {
78
+ fs.rmSync( `${packageRoot}/helm-old`, { recursive : true, force : true } )
79
+ log( chalk.yellow( '\nAn existing helm chart was detected and removed to make way for the new chart structure.' ) )
80
+ }
75
81
  }
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import chalk from 'chalk'
4
- import commandLineArgs from 'command-line-args'
5
- import commandLineUsage from 'command-line-usage'
4
+ import { Command } from 'commander'
6
5
 
7
6
  import {
8
7
  debug,
@@ -14,53 +13,27 @@ import {
14
13
  warning,
15
14
  } from './Utils.mjs'
16
15
 
17
- const commandLineOptions = [
18
- {
19
- name : 'chart',
20
- type : String,
21
- defaultValue : 'helm',
22
- description : '{green directory containing the chart - default: helm}',
23
- },
24
- {
25
- name : 'no-registry',
26
- type : Boolean,
27
- defaultValue : false,
28
- description : '{green push to the museum but not the artifact registry}',
29
- },
30
- {
31
- name : 'help',
32
- type : Boolean,
33
- description : '{green display this help screen}',
34
- },
35
- ]
16
+ const program = new Command()
36
17
 
37
- const sections = [
38
- {
39
- header : 'Leverege Helm Chart Museum Pusher',
40
- content : `{green This tool pushes Helm charts to both the legacy Chartmuseum (hosted on GCS)
18
+ program
19
+ .configureHelp( { styleOptionTerm : str => chalk.bold.white( str ) } )
20
+ .description( chalk.green( `Pushes Helm charts to both the legacy Chartmuseum (hosted on GCS)
41
21
  and a Google Artifact Registry. It maintains compatibility with existing
42
22
  Chartmuseum users while enabling a seamless transition to Artifact Registry
43
- without disrupting current configurations.}`
44
- },
45
- { header : 'Options',
46
- optionList : commandLineOptions,
47
- },
48
- ]
23
+ without disrupting current configurations.` ) )
24
+ .option( '--chart <directory>', chalk.green( 'directory containing the chart' ), 'helm' )
25
+ .option( '--no-registry', chalk.green( 'push to the museum but not the artifact registry' ) )
26
+ .option( '--refresh-deps', chalk.green( 'force a helm dependency update before pushing' ) )
49
27
 
50
- const args = commandLineArgs( commandLineOptions, { camelCase : true, partial : true } )
51
- const usage = commandLineUsage( sections )
52
-
53
- if ( args.help ) {
54
- log( usage )
55
- process.exit( 0 )
56
- }
28
+ program.parse( process.argv )
29
+ const opts = program.opts()
57
30
 
58
31
  const {
59
32
  chartName,
60
33
  chartVersion,
61
34
  chartAppVersion,
62
35
  depsOutOfSync,
63
- } = await parseHelmChart( args.chart )
36
+ } = await parseHelmChart( opts.chart )
64
37
 
65
38
  log( chalk.green( `Chart => ${chalk.bold.yellow( chartName )}` ) )
66
39
  log( chalk.green( `Version => ${chalk.bold.yellow( chartVersion )}` ) )
@@ -71,7 +44,7 @@ if ( !chartAppVersion.startsWith( 'v' ) ) {
71
44
  await proceed( 'You sure about this?' )
72
45
  }
73
46
 
74
- if ( depsOutOfSync ) {
47
+ if ( depsOutOfSync || opts.refreshDeps ) {
75
48
  try {
76
49
  log( chalk.yellow.bold( '\nChart dependedencies are out of sync - updating...\n' ) )
77
50
  await shellCmd( 'helm dependency update ./helm', { stdio : 'inherit' } )
@@ -83,22 +56,21 @@ if ( depsOutOfSync ) {
83
56
  let museumStatus = 0
84
57
  try {
85
58
  log( chalk.green( ' ... pushing to the Museum' ) )
86
- const museum = await shellCmd( `helm cm-push ${args.chart} leverege` )
59
+ const museum = await shellCmd( `helm cm-push ${opts.chart} leverege` )
87
60
  debug( { museum }, '<==output from helm push' )
88
61
  } catch ( ex ) {
89
- // log( ex.stderr )
90
62
  log( ex.message )
91
63
  museumStatus = 1
92
64
  }
93
65
 
94
- if ( args.noRegistry ) {
66
+ if ( !opts.registry ) {
95
67
  log( `${chalk.bold.yellow( '\nskipping the chart push to the artifact registry' )}` )
96
68
  process.exit( museumStatus )
97
69
  }
98
70
 
99
71
  try {
100
72
  log( chalk.green( ' ... pushing to the Artifact Registry' ) )
101
- const registry = await shellCmd( `chart-to-registry --chart ${args.chart} --ignore-appv` )
73
+ const registry = await shellCmd( `chart-to-registry --chart ${opts.chart} --ignore-appv` )
102
74
  debug( { registry }, '<==chart-to-registry' )
103
75
  process.exit( museumStatus )
104
76
  } catch ( ex ) {
@@ -24,10 +24,7 @@ import chalk from 'chalk'
24
24
  import { program } from 'commander'
25
25
  import ms from 'ms'
26
26
 
27
- import { debug, log, shellCmd, versionChecks } from './Utils.mjs'
28
-
29
- const MIN_NODE_VERSION = '22.0.0'
30
- const MIN_NPM_VERSION = '11.10.0'
27
+ import { debug, log, shellCmd, versionChecks, BUILD_TOOLS_MIN_NODE, BUILD_TOOLS_MIN_NPM } from './Utils.mjs'
31
28
 
32
29
  const NPMRC_FILE = `${os.homedir()}/.npmrc`
33
30
  const YARNRC_FILE = `${os.homedir()}/.yarnrc.yml`
@@ -85,8 +82,8 @@ const opts = program.opts()
85
82
  const gcpProject = opts.project
86
83
 
87
84
  await versionChecks( {
88
- node : { min : MIN_NODE_VERSION },
89
- npm : { min : MIN_NPM_VERSION, hint : 'required for npmMinimalAgeGate support' },
85
+ node : { min : BUILD_TOOLS_MIN_NODE },
86
+ npm : { min : BUILD_TOOLS_MIN_NPM, hint : 'required for npmMinimalAgeGate support' },
90
87
  strict : opts.versionCheck,
91
88
  } )
92
89