@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.
- package/.har/config.json +11 -0
- package/.har/pre-commit +1 -0
- package/.har/pre-push +1 -0
- package/package.json +7 -5
- package/src/Utils.mjs +49 -17
- package/src/docker-to-registry.mjs +2 -2
- package/src/hook-and-release/CLIParser.mjs +23 -0
- package/src/hook-and-release/Config.mjs +249 -0
- package/src/hook-and-release/index.mjs +3 -0
- package/src/hook-and-release.mjs +64 -0
- package/src/overwhelm.mjs +1 -1
- package/registry-compass.yaml +0 -20
- package/src/chart-compass.mjs +0 -96
package/.har/config.json
ADDED
package/.har/pre-commit
ADDED
|
@@ -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.
|
|
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
|
-
"
|
|
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.
|
|
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
|
|
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.
|
|
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
|
-
|
|
119
|
+
const runGitCommand = async ( cmd, debugLabel ) => {
|
|
119
120
|
try {
|
|
120
|
-
const
|
|
121
|
-
debug( {
|
|
122
|
-
return
|
|
121
|
+
const result = await shellCmd( cmd )
|
|
122
|
+
debug( { result }, `<==${debugLabel}` )
|
|
123
|
+
return result
|
|
123
124
|
} catch ( error ) {
|
|
124
|
-
debug( { error },
|
|
125
|
-
|
|
125
|
+
debug( { error }, chalk.red( `***ERROR git failed [${cmd}]` ) )
|
|
126
|
+
return undefined
|
|
126
127
|
}
|
|
127
128
|
}
|
|
128
129
|
|
|
129
|
-
export const
|
|
130
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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,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
|
|
272
|
+
const configBlock = valuesLocal?.config
|
|
273
273
|
|
|
274
274
|
// only care about validating config at this time
|
|
275
275
|
if ( configBlock ) {
|
package/registry-compass.yaml
DELETED
|
@@ -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
|
package/src/chart-compass.mjs
DELETED
|
@@ -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' )
|