@leverege/build-tools 2.56.0 → 2.56.2

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 @@
1
+ unleash
@@ -0,0 +1 @@
1
+ unleash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leverege/build-tools",
3
- "version": "2.56.0",
3
+ "version": "2.56.2",
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": "npx husky",
14
+ "test": "echo \"no tests specified\" && exit 0"
14
15
  },
15
16
  "bin": {
16
17
  "build-tools": "src/build-tools.mjs",
@@ -56,7 +57,7 @@
56
57
  "author": "Leverege Devs",
57
58
  "license": "SEE LICENSE IN LICENSE.md",
58
59
  "dependencies": {
59
- "@google-cloud/artifact-registry": "^3.4.0",
60
+ "@google-cloud/artifact-registry": "^3.5.0",
60
61
  "ansi-colors": "^4.1.3",
61
62
  "chalk": "^5.3.0",
62
63
  "command-line-args": "^6.0.1",
@@ -66,7 +67,7 @@
66
67
  "execa": "^9.5.1",
67
68
  "glob": "^11.0.0",
68
69
  "handlebars": "^4.7.8",
69
- "inquirer": "^12.0.1",
70
+ "inquirer": "^12.1.0",
70
71
  "js-yaml": "^4.1.0",
71
72
  "ms": "^2.1.3",
72
73
  "npm-registry-fetch": "^18.0.2",
@@ -76,10 +77,11 @@
76
77
  "readline-sync": "^1.4.10",
77
78
  "semver": "^7.6.3",
78
79
  "simple-git": "^3.27.0",
79
- "zx": "^8.2.0"
80
+ "zx": "^8.2.1"
80
81
  },
81
82
  "devDependencies": {
82
83
  "@leverege/eslint-config-leverege": "^5.0.1",
84
+ "husky": "^9.1.6",
83
85
  "npm": "^10.9.0"
84
86
  }
85
87
  }
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 */
@@ -382,13 +383,14 @@ export const parseHelmChart = async ( helmroot = './helm' ) => {
382
383
  } )
383
384
  }
384
385
 
385
- export const analyzeRepository = async ( giveGuidance ) => {
386
+ export const getRepositoryDescr = async () => {
387
+ const currentDir = process.cwd()
388
+ const workingDir = process.env.PWD
386
389
  const gitRoot = await getGitRootDirectory()
390
+ const { branch : gitBranch, upstream : gitUpstream } = await getGitUpstream()
387
391
  const subPkgs = await glob( `${gitRoot}/packages/**/package.json`, { ignore : '/**/node_modules/**' } )
388
392
  const helmChart = await parseHelmChart()
389
393
  const isMonoRepo = subPkgs?.length > 0
390
-
391
- // Verify the presence of a root package.json file for all monorepos
392
394
  let rootPackageJson
393
395
  try {
394
396
  rootPackageJson = await parseJsonFile( `${gitRoot}/package.json` )
@@ -396,6 +398,31 @@ export const analyzeRepository = async ( giveGuidance ) => {
396
398
  rootPackageJson = { isInvalid : true, error : 'invalid or non-existent root package.json file' }
397
399
  }
398
400
  const isNpmWorkspace = rootPackageJson?.workspaces?.length > 0
401
+
402
+ return {
403
+ currentDir,
404
+ workingDir,
405
+ gitBranch,
406
+ gitRoot,
407
+ gitUpstream,
408
+ helmChart,
409
+ isMonoRepo,
410
+ isNpmWorkspace,
411
+ rootPackageJson,
412
+ subPkgs,
413
+ }
414
+ }
415
+
416
+ export const analyzeRepository = async ( giveGuidance ) => {
417
+ const {
418
+ gitRoot,
419
+ subPkgs,
420
+ helmChart,
421
+ isMonoRepo,
422
+ rootPackageJson,
423
+ isNpmWorkspace,
424
+ } = await getRepositoryDescr()
425
+
399
426
  if ( isMonoRepo && rootPackageJson.isInvalid ) {
400
427
  log( chalk.red.bold( `
401
428
  ***REQUIRED: A package.json file is required at the monorepo root` ) )
@@ -22,7 +22,7 @@ import {
22
22
  shellCmd } from './Utils.mjs'
23
23
 
24
24
  const commandLineOptions = [ // Use commandLineOptions to tie into the Usage statements
25
- /* eslint-disable max-len */
25
+
26
26
  {
27
27
  name : 'location',
28
28
  type : String,
@@ -48,7 +48,7 @@ const commandLineOptions = [ // Use commandLineOptions to tie into the Usage sta
48
48
  type : Boolean,
49
49
  description : '{green display this help screen}',
50
50
  },
51
- /* eslint-enable max-len */
51
+
52
52
  ]
53
53
 
54
54
  const sections = [
@@ -20,7 +20,6 @@ import {
20
20
  shellCmd } from './Utils.mjs'
21
21
 
22
22
  const commandLineOptions = [ // Use commandLineOptions to tie into the Usage statements
23
- /* eslint-disable max-len */
24
23
  {
25
24
  name : 'location',
26
25
  type : String,
@@ -51,7 +50,6 @@ const commandLineOptions = [ // Use commandLineOptions to tie into the Usage sta
51
50
  type : Boolean,
52
51
  description : '{green display this help screen}',
53
52
  },
54
- /* eslint-enable max-len */
55
53
  ]
56
54
 
57
55
  const sections = [
@@ -118,7 +118,6 @@ await shellCmd( 'npm install', { stdio : 'inherit' } )
118
118
 
119
119
  if ( giveGuidance ) {
120
120
  await docker.repoCleanup() // adjusts gitignore files and removes cruft
121
- /* eslint-disable max-len */
122
121
  log( `
123
122
 
124
123
 
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /* eslint-disable no-console */
3
3
  // https://github.com/google/zx
4
- /* eslint-disable max-len */
5
4
  import pkg from 'enquirer'
6
5
  import { $, fs, argv, path, chalk } from 'zx'
7
6
 
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  // https://github.com/google/zx
3
- /* eslint-disable max-len */
4
3
  /* eslint-disable no-console */
5
4
  import pkg from 'enquirer'
6
5
  import { $, fs, argv, path, chalk } from 'zx'
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'node:fs'
4
+ import path from 'node:path'
5
+
6
+ import chalk from 'chalk'
7
+ import commandLineArgs from 'command-line-args'
8
+ import commandLineUsage from 'command-line-usage'
9
+ import SimpleGit from 'simple-git'
10
+
11
+ import {
12
+ condir,
13
+ debug,
14
+ enableDebug,
15
+ getRepositoryDescr,
16
+ log,
17
+ shellCmd,
18
+ } from './Utils.mjs'
19
+
20
+ const git = new SimpleGit()
21
+ const repoDescr = await getRepositoryDescr()
22
+
23
+ debug( { repoDescr }, '--------LOCAL UNLEASH-------' )
24
+
25
+ const hookAndReleaseOptions = [
26
+ {
27
+ name : 'init',
28
+ type : Boolean,
29
+ default : false,
30
+ description : '{green bootstraps the repo .har directory and adds appropriate git hook}',
31
+ },
32
+ {
33
+ name : 'debug',
34
+ type : Boolean,
35
+ default : false,
36
+ description : '{yellow enables verbose debugging}',
37
+ },
38
+ {
39
+ name : 'help',
40
+ type : Boolean,
41
+ default : false,
42
+ description : '{green display this help screen}',
43
+ },
44
+ ]
45
+
46
+ const sections = [
47
+ {
48
+ header : 'Leverege Hook and Release Script',
49
+ content : '{green This tool help...}',
50
+ },
51
+ {
52
+ header : 'Options',
53
+ optionList : hookAndReleaseOptions,
54
+ },
55
+ ]
56
+
57
+ const args = commandLineArgs( hookAndReleaseOptions, { camelCase : true, partial : true } )
58
+ const usage = commandLineUsage( sections )
59
+
60
+ if ( args.debug ) {
61
+ enableDebug()
62
+ }
63
+
64
+ if ( args.help ) {
65
+ log( usage )
66
+ process.exit( 0 )
67
+ }
68
+
69
+ /* eslint-disable no-underscore-dangle */
70
+ if ( args._unknown ) {
71
+ log( usage )
72
+ log( `\nUnrecognized argument [${chalk.bold.red( args._unknown )}]\n` )
73
+ process.exit( 1 )
74
+ }
75
+ /* eslint-enable no-underscore-dangle */
76
+
77
+ if ( args.init ) {
78
+ const harDir = `${repoDescr.gitRoot}/.har`
79
+ if ( fs.existsSync( harDir ) ) {
80
+ log( `this repo already has ${harDir}` )
81
+ process.exit( 1 )
82
+ }
83
+
84
+ fs.mkdirSync( harDir )
85
+ await git.addConfig( 'core.hookspath', '.har' )
86
+ process.exit( 0 )
87
+ }
88
+
89
+ const getCurrentBranchName = async () => {
90
+ const branchInfo = await git.branch()
91
+
92
+ // first check to see if there are no branches - new repo?
93
+ if ( Object.keys( branchInfo.branches ).length === 0 ) { return '' }
94
+
95
+ return Object
96
+ .entries( branchInfo.branches )
97
+ .find( ( [ name, info ] ) => ( info.current ) )[0]
98
+ }
99
+
100
+ const isProtected = async () => {
101
+ const theBranch = await getCurrentBranchName()
102
+
103
+ const protectedBranches = [ 'main', 'master', 'development' ]
104
+ const additionalProtectedBranches = [ ...process.argv.slice( 2 ) ]
105
+
106
+ // Check if the current branch starts with any of the additional
107
+ // protected branch name
108
+ let matchesAdditionalBranch = false
109
+ for ( let i = 0; i < additionalProtectedBranches.length; i++ ) {
110
+ matchesAdditionalBranch = matchesAdditionalBranch ||
111
+ theBranch.startsWith( additionalProtectedBranches[i] )
112
+ }
113
+
114
+ return protectedBranches.includes( theBranch ) || matchesAdditionalBranch
115
+ }
116
+
117
+ // Identify the package directory based on staged files
118
+ const getPackageDirectory = async () => {
119
+ const gitDiff = await git.diff( [ '--name-only', '--cached' ] )
120
+ const stagedFiles = gitDiff.split( '\n' )
121
+ const packageDirs = new Set()
122
+
123
+ // Loop through staged files and extract package directories
124
+ stagedFiles.forEach( ( file ) => {
125
+ const parts = file.split( path.sep ) // Split path to identify package
126
+ if ( parts.length > 1 && parts[0] === 'packages' ) {
127
+ const packageDir = parts[1]
128
+ packageDirs.add( packageDir )
129
+ }
130
+ } )
131
+
132
+ const packageDirsArray = Array.from( packageDirs )
133
+ debug( { stagedFiles, packageDirsArray }, '<==unleash: getPackageDirectory' )
134
+ return packageDirsArray
135
+ }
136
+
137
+ const npmRunner = async ( script, packageDir ) => {
138
+ try {
139
+ const cmd = `npm run ${script}`
140
+ const results = await shellCmd( cmd, { cwd : path.join( process.cwd(), 'packages', packageDir ), stdio : 'inherit' } )
141
+ return results
142
+ } catch ( err ) {
143
+ process.exit( 1 )
144
+ }
145
+ return undefined
146
+ }
147
+
148
+ ( async () => {
149
+ if ( await isProtected() ) {
150
+ const packageDirs = await getPackageDirectory()
151
+ for ( let pi = 0; pi < packageDirs.length; pi++ ) {
152
+ const packageDir = packageDirs[pi]
153
+ const script = [ 'test', 'lint' ]
154
+ for ( let i = 0; i < script.length; i++ ) {
155
+ await npmRunner( script[i], packageDir ) // eslint-disable-line no-await-in-loop
156
+ }
157
+ }
158
+ } else {
159
+ process.exit( 0 )
160
+ }
161
+ } )()
package/src/overwhelm.mjs CHANGED
@@ -266,19 +266,20 @@ const ahoy = glob.sync( '*/', opt )
266
266
 
267
267
  // Verifies that all values in a config block are quoted
268
268
  const validValuesLocalConfig = ( vlf ) => {
269
- if ( ! fs.existsSync( vlf ) ) { return undefined }
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 ) {
276
- for ( const [ key, value ] of Object.entries( configBlock ) ) {
277
- if( ! isString( value ) ) {
276
+ Object.entries( configBlock ).forEach( ( cfgLine ) => {
277
+ const [ key, value ] = cfgLine
278
+ if ( !isString( value ) ) {
278
279
  err( { configBlock }, '***Bad config block' )
279
280
  errorExit( `Is ${key} missing quotes around ${value} in ${vlf}?` )
280
281
  }
281
- }
282
+ } )
282
283
  }
283
284
 
284
285
  return true // TODO: return the already read valuesLocal info?
@@ -29,7 +29,6 @@ import { lt as semverLt } from 'semver'
29
29
  import { debug, log, shellCmd } from './Utils.mjs'
30
30
 
31
31
  const refreshTokenOptions = [ // Use refreshTokenOptions to tie into the Usage statements
32
- /* eslint-disable max-len */
33
32
  {
34
33
  name : 'project',
35
34
  type : String,
@@ -60,7 +59,6 @@ const refreshTokenOptions = [ // Use refreshTokenOptions to tie into the Usage s
60
59
  default : false,
61
60
  description : '{green display this help screen}',
62
61
  },
63
- /* eslint-enable max-len */
64
62
  ]
65
63
 
66
64
  const sections = [
@@ -245,7 +243,6 @@ try {
245
243
  const now = ( new Date() ).toLocaleString()
246
244
  const account = await shellCmd( 'gcloud config get account' )
247
245
  const slackData = {
248
- // eslint-disable-next-line max-len
249
246
  text : `--- npmrc refreshed by \`${account}\` at ${now}\n tokens RW [\`${npmrc.token}\`] RO [\`${npmrcRo.token}\`]`,
250
247
  channel : slackConfig.channel,
251
248
  }
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /* eslint-disable security/detect-unsafe-regex */
3
3
  /* eslint-disable no-console */
4
- /* eslint-disable max-len */
5
4
 
6
5
  import path from 'node:path'
7
6