@leverege/build-tools 2.56.2 → 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 +4 -4
- package/src/Utils.mjs +20 -15
- 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 +39 -136
- package/.husky/pre-commit +0 -1
- package/.husky/pre-push +0 -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,7 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"clean": "rm -rf lib",
|
|
12
12
|
"lint": "find ./src -name \\*.\\*js | xargs npx eslint --report-unused-disable-directives",
|
|
13
|
-
"prepare": "
|
|
13
|
+
"prepare": "hook-and-release",
|
|
14
14
|
"test": "echo \"no tests specified\" && exit 0"
|
|
15
15
|
},
|
|
16
16
|
"bin": {
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"helmup": "src/helmup.sh",
|
|
36
36
|
"helminit": "src/helmup.sh",
|
|
37
37
|
"helmwhat": "src/helmup.sh",
|
|
38
|
+
"hook-and-release": "src/hook-and-release.mjs",
|
|
38
39
|
"k8cryo": "src/k8cryo.sh",
|
|
39
40
|
"k8scale": "src/k8scale.sh",
|
|
40
41
|
"k8thaw": "src/k8cryo.sh",
|
|
@@ -77,11 +78,10 @@
|
|
|
77
78
|
"readline-sync": "^1.4.10",
|
|
78
79
|
"semver": "^7.6.3",
|
|
79
80
|
"simple-git": "^3.27.0",
|
|
80
|
-
"zx": "^8.2.
|
|
81
|
+
"zx": "^8.2.2"
|
|
81
82
|
},
|
|
82
83
|
"devDependencies": {
|
|
83
84
|
"@leverege/eslint-config-leverege": "^5.0.1",
|
|
84
|
-
"husky": "^9.1.6",
|
|
85
85
|
"npm": "^10.9.0"
|
|
86
86
|
}
|
|
87
87
|
}
|
package/src/Utils.mjs
CHANGED
|
@@ -116,26 +116,29 @@ export const getGcpSecret = async ( gcpProject, secretName, opts ) => {
|
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
|
|
119
|
+
const runGitCommand = async ( cmd, debugLabel ) => {
|
|
120
120
|
try {
|
|
121
|
-
const
|
|
122
|
-
debug( {
|
|
123
|
-
return
|
|
121
|
+
const result = await shellCmd( cmd )
|
|
122
|
+
debug( { result }, `<==${debugLabel}` )
|
|
123
|
+
return result
|
|
124
124
|
} catch ( error ) {
|
|
125
|
-
debug( { error },
|
|
126
|
-
|
|
125
|
+
debug( { error }, chalk.red( `***ERROR git failed [${cmd}]` ) )
|
|
126
|
+
return undefined
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
export const
|
|
131
|
-
|
|
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'
|
|
132
138
|
try {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
} catch ( err ) {
|
|
137
|
-
return { branch, upstream : undefined }
|
|
138
|
-
}
|
|
139
|
+
upstream = await runGitCommand( `git rev-parse --abbrev-ref ${branch}@{u}`, 'getGitUpstream' ) ?? 'no-upstream'
|
|
140
|
+
} catch ( error ) {}
|
|
141
|
+
return { branch, upstream }
|
|
139
142
|
}
|
|
140
143
|
|
|
141
144
|
export const gitRepoIsDirty = async () => {
|
|
@@ -387,7 +390,8 @@ export const getRepositoryDescr = async () => {
|
|
|
387
390
|
const currentDir = process.cwd()
|
|
388
391
|
const workingDir = process.env.PWD
|
|
389
392
|
const gitRoot = await getGitRootDirectory()
|
|
390
|
-
const
|
|
393
|
+
const gitHooksPath = await getGitHooksPath()
|
|
394
|
+
const { branch : gitBranch, upstream : gitUpstream } = await getGitBranchAndUpstream()
|
|
391
395
|
const subPkgs = await glob( `${gitRoot}/packages/**/package.json`, { ignore : '/**/node_modules/**' } )
|
|
392
396
|
const helmChart = await parseHelmChart()
|
|
393
397
|
const isMonoRepo = subPkgs?.length > 0
|
|
@@ -403,6 +407,7 @@ export const getRepositoryDescr = async () => {
|
|
|
403
407
|
currentDir,
|
|
404
408
|
workingDir,
|
|
405
409
|
gitBranch,
|
|
410
|
+
gitHooksPath,
|
|
406
411
|
gitRoot,
|
|
407
412
|
gitUpstream,
|
|
408
413
|
helmChart,
|
|
@@ -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
|
+
}
|
package/src/hook-and-release.mjs
CHANGED
|
@@ -1,161 +1,64 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import fs from 'node:fs'
|
|
4
3
|
import path from 'node:path'
|
|
5
4
|
|
|
6
|
-
import
|
|
7
|
-
import commandLineArgs from 'command-line-args'
|
|
8
|
-
import commandLineUsage from 'command-line-usage'
|
|
9
|
-
import SimpleGit from 'simple-git'
|
|
5
|
+
import { debug, getGitDiff, } from './Utils.mjs'
|
|
10
6
|
|
|
11
|
-
import
|
|
12
|
-
condir,
|
|
13
|
-
debug,
|
|
14
|
-
enableDebug,
|
|
15
|
-
getRepositoryDescr,
|
|
16
|
-
log,
|
|
17
|
-
shellCmd,
|
|
18
|
-
} from './Utils.mjs'
|
|
7
|
+
import Config from './hook-and-release/index.mjs'
|
|
19
8
|
|
|
20
|
-
const
|
|
21
|
-
|
|
9
|
+
const harConfig = await Config.create()
|
|
10
|
+
debug( { harConfig }, '<==hook-and-release config object' )
|
|
22
11
|
|
|
23
|
-
|
|
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 ) }
|
|
24
14
|
|
|
25
|
-
|
|
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
|
-
]
|
|
15
|
+
// if this branch isn't under protection then we're done
|
|
16
|
+
if ( !harConfig.isBranchProtected() ) { process.exit( 0 ) }
|
|
45
17
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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 )
|
|
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() ]
|
|
82
23
|
}
|
|
83
24
|
|
|
84
|
-
|
|
85
|
-
await
|
|
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' ] )
|
|
25
|
+
// otherwise get staged mods from git and parse out the package names
|
|
26
|
+
const gitDiff = await getGitDiff( '--name-only --cached' )
|
|
120
27
|
const stagedFiles = gitDiff.split( '\n' )
|
|
121
28
|
const packageDirs = new Set()
|
|
122
29
|
|
|
123
|
-
//
|
|
30
|
+
// loop through staged files and extract package directories
|
|
124
31
|
stagedFiles.forEach( ( file ) => {
|
|
125
32
|
const parts = file.split( path.sep ) // Split path to identify package
|
|
126
33
|
if ( parts.length > 1 && parts[0] === 'packages' ) {
|
|
127
34
|
const packageDir = parts[1]
|
|
128
|
-
|
|
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
|
+
}
|
|
129
48
|
}
|
|
130
49
|
} )
|
|
131
50
|
|
|
132
51
|
const packageDirsArray = Array.from( packageDirs )
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
52
|
+
const packageDirsWithPath = packageDirsArray.map( ( packageDir ) => {
|
|
53
|
+
return path.join( process.cwd(), 'packages', packageDir )
|
|
54
|
+
} )
|
|
136
55
|
|
|
137
|
-
|
|
138
|
-
|
|
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
|
|
56
|
+
debug( { stagedFiles, packageDirsArray, packageDirsWithPath }, '<==unleash: getPackageDirectory' )
|
|
57
|
+
return packageDirsWithPath
|
|
146
58
|
}
|
|
147
59
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
-
} )()
|
|
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/.husky/pre-commit
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
unleash
|
package/.husky/pre-push
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
unleash
|
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' )
|