@leverege/build-tools 2.110.1 â 2.111.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/package.json +3 -3
- package/src/helm-charts/valkey/valkey-local.yaml +1 -1
- package/src/overwhelm.mjs +0 -2
- package/src/chart-to-museum.mjs +0 -55
- package/src/fetch-awesome-alerts.mjs +0 -75
- package/src/modify-gcs-access.mjs +0 -85
- package/src/test.json +0 -4
- package/src/testOauthLogic.mjs +0 -12
- package/src/unleash.mjs +0 -57
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leverege/build-tools",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.111.0",
|
|
4
4
|
"description": "A collection of build / support tools for Leverege developers",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
"googleapis": "^173.0.0",
|
|
99
99
|
"handlebars": "^4.7.9",
|
|
100
100
|
"ignore": "^7.0.5",
|
|
101
|
-
"inquirer": "14.0.2",
|
|
101
|
+
"inquirer": "^14.0.2",
|
|
102
102
|
"js-yaml": "^4.2.0",
|
|
103
103
|
"jsdoc": "^4.0.5",
|
|
104
104
|
"ms": "^2.1.3",
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
"p-limit": "^7.3.0",
|
|
108
108
|
"package-up": "^5.0.0",
|
|
109
109
|
"readline-sync": "^1.4.10",
|
|
110
|
-
"semver": "7.8.4",
|
|
110
|
+
"semver": "^7.8.4",
|
|
111
111
|
"shell-quote": "^1.8.4",
|
|
112
112
|
"simple-git": "^3.36.0",
|
|
113
113
|
"sloc": "^0.3.2",
|
package/src/overwhelm.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// XXX console.log( `TOP=>[${process.cwd()}] PWD=[${process.env.PWD}]` )
|
|
4
3
|
/* eslint-disable security/detect-non-literal-fs-filename */
|
|
5
4
|
|
|
6
5
|
import path from 'node:path'
|
|
@@ -8,7 +7,6 @@ import fs from 'node:fs'
|
|
|
8
7
|
|
|
9
8
|
import chalk from 'chalk'
|
|
10
9
|
import cliArgs from 'command-line-args'
|
|
11
|
-
// const cliHelp = require( 'command-line-usage' )
|
|
12
10
|
import deepmerge from 'deepmerge'
|
|
13
11
|
import { glob } from 'glob'
|
|
14
12
|
import ask from 'readline-sync'
|
package/src/chart-to-museum.mjs
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// *** DEPRECATED: this goes away when we move away from the chart museum and
|
|
3
|
-
// push-my-chart already handles this a artifact pushes
|
|
4
|
-
//
|
|
5
|
-
import chalk from 'chalk'
|
|
6
|
-
import commandLineArgs from 'command-line-args'
|
|
7
|
-
import commandLineUsage from 'command-line-usage'
|
|
8
|
-
import { lt as semverLt } from 'semver'
|
|
9
|
-
|
|
10
|
-
import { log, shellCmd } from './Utils.mjs'
|
|
11
|
-
|
|
12
|
-
const commandLineOptions = [
|
|
13
|
-
{
|
|
14
|
-
name : 'help',
|
|
15
|
-
type : Boolean,
|
|
16
|
-
description : '{green display this help screen}',
|
|
17
|
-
},
|
|
18
|
-
]
|
|
19
|
-
|
|
20
|
-
const sections = [
|
|
21
|
-
{
|
|
22
|
-
header : 'Leverege Helm Chart Museum Pusher',
|
|
23
|
-
content : `{green This legacy tool acts as a simple method for assembling and storing a local
|
|
24
|
-
helm chart structure on the Leverege Chart Museum using Google Cloud Storage.
|
|
25
|
-
This approach is considered legacy since we have transitioned to using the
|
|
26
|
-
Google Artifact Registry for distributing helm charts.
|
|
27
|
-
}`
|
|
28
|
-
},
|
|
29
|
-
{ header : 'Options',
|
|
30
|
-
optionList : commandLineOptions,
|
|
31
|
-
},
|
|
32
|
-
]
|
|
33
|
-
|
|
34
|
-
const args = commandLineArgs( commandLineOptions, { camelCase : true, partial : true } )
|
|
35
|
-
const usage = commandLineUsage( sections )
|
|
36
|
-
|
|
37
|
-
if ( args.help ) {
|
|
38
|
-
log( usage )
|
|
39
|
-
process.exit( 0 )
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const pushItGood = async () => {
|
|
43
|
-
const version = await shellCmd( 'helm version --short' )
|
|
44
|
-
const pusher = ( semverLt( version, '3.7.0' ) ? 'push' : 'cm-push' )
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
const museum = await shellCmd( `helm ${pusher} helm leverege` )
|
|
48
|
-
log( chalk.green( museum ) )
|
|
49
|
-
} catch ( ex ) {
|
|
50
|
-
log( chalk.red( ex.stderr ) )
|
|
51
|
-
process.exit( 1 )
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
pushItGood()
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import fs from 'node:fs'
|
|
4
|
-
import path from 'node:path'
|
|
5
|
-
|
|
6
|
-
import yaml from 'js-yaml'
|
|
7
|
-
import { Command } from 'commander'
|
|
8
|
-
import chalk from 'chalk'
|
|
9
|
-
|
|
10
|
-
import { log, err } from './Utils.mjs'
|
|
11
|
-
|
|
12
|
-
const program = new Command()
|
|
13
|
-
|
|
14
|
-
program
|
|
15
|
-
.name( 'fetch-alerts' )
|
|
16
|
-
.description( 'Fetch a Prometheus alert YAML file and convert it to a PrometheusRule CRD.' )
|
|
17
|
-
.argument( '<sourceFile>', 'YAML filename to fetch from awesome-prometheus' )
|
|
18
|
-
.option( '-o, --output <outputFile>', 'Output file name', 'converted-alerts.yaml' )
|
|
19
|
-
.option( '-n, --name <customName>', 'Override metadata.name in the PrometheusRule' )
|
|
20
|
-
.option( '--dry-run', 'Print output to console instead of writing to file' )
|
|
21
|
-
.parse()
|
|
22
|
-
|
|
23
|
-
const [ sourceFile ] = program.args
|
|
24
|
-
const { output : outputFile, dryRun, name : customName } = program.opts()
|
|
25
|
-
|
|
26
|
-
const BASE_URL = 'https://raw.githubusercontent.com/samber/awesome-prometheus-alerts/master/dist/rules'
|
|
27
|
-
const SOURCE_URL = `${BASE_URL}/${sourceFile}`
|
|
28
|
-
|
|
29
|
-
const defaultName = path.basename( sourceFile ).replace( /\.(yaml|yml)$/, '' )
|
|
30
|
-
const metadataName = customName || defaultName
|
|
31
|
-
|
|
32
|
-
async function fetchAndConvert() {
|
|
33
|
-
try {
|
|
34
|
-
log( chalk.blueBright( `đ Fetching YAML from ${SOURCE_URL}...` ) )
|
|
35
|
-
const response = await fetch( SOURCE_URL )
|
|
36
|
-
if ( !response.ok ) throw new Error( `Failed to fetch: ${response.statusText}` )
|
|
37
|
-
|
|
38
|
-
const rawYaml = await response.text()
|
|
39
|
-
const parsedYaml = yaml.load( rawYaml )
|
|
40
|
-
if ( !parsedYaml.groups ) throw new Error( 'Invalid YAML structure, missing "groups"' )
|
|
41
|
-
|
|
42
|
-
const prometheusRule = {
|
|
43
|
-
apiVersion : 'monitoring.coreos.com/v1',
|
|
44
|
-
kind : 'PrometheusRule',
|
|
45
|
-
metadata : {
|
|
46
|
-
name : metadataName,
|
|
47
|
-
namespace : 'prometheus',
|
|
48
|
-
},
|
|
49
|
-
spec : {
|
|
50
|
-
groups : parsedYaml.groups.map( group => ( {
|
|
51
|
-
name : `${group.name}-rules`,
|
|
52
|
-
rules : group.rules,
|
|
53
|
-
} ) ),
|
|
54
|
-
},
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const formattedYaml = yaml.dump( prometheusRule, {
|
|
58
|
-
noRefs : true,
|
|
59
|
-
indent : 2,
|
|
60
|
-
lineWidth : -1,
|
|
61
|
-
} )
|
|
62
|
-
|
|
63
|
-
if ( dryRun ) {
|
|
64
|
-
log( chalk.green( `\nđĸ Dry Run Output for: ${chalk.yellow( metadataName )}\n` ) )
|
|
65
|
-
log( formattedYaml )
|
|
66
|
-
} else {
|
|
67
|
-
fs.writeFileSync( outputFile, formattedYaml, 'utf8' ) // eslint-disable-line security/detect-non-literal-fs-filename
|
|
68
|
-
log( chalk.green( `â
Converted YAML written to ${chalk.cyan( outputFile )}` ) )
|
|
69
|
-
}
|
|
70
|
-
} catch ( error ) {
|
|
71
|
-
err( chalk.red( 'â Error:' ), error.message )
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
fetchAndConvert()
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { Command } from 'commander'
|
|
4
|
-
|
|
5
|
-
import { shellCmd, log, warning, errorExit } from './Utils.mjs'
|
|
6
|
-
|
|
7
|
-
const program = new Command()
|
|
8
|
-
|
|
9
|
-
program
|
|
10
|
-
.requiredOption( '--project <projectId>', 'GCP project ID of the GSA' )
|
|
11
|
-
.requiredOption( '--bucket <bucketName>', 'GCS bucket name (no gs:// prefix)' )
|
|
12
|
-
.requiredOption( '--gsa <gsaName>', 'Service account name, e.g. my-service' )
|
|
13
|
-
.requiredOption( '--role <roleId>', 'Custom role ID', 'leveregeStorageObjectReader' )
|
|
14
|
-
.option( '--org', 'Treat as GCP organizational level role' )
|
|
15
|
-
.option( '--add', 'Add IAM binding (default)' )
|
|
16
|
-
.option( '--remove', 'Remove IAM binding' )
|
|
17
|
-
.option( '--dry-run', 'Show command without executing' )
|
|
18
|
-
|
|
19
|
-
program.parse( process.argv )
|
|
20
|
-
|
|
21
|
-
const opts = program.opts()
|
|
22
|
-
|
|
23
|
-
// Validate mutually exclusive add/remove
|
|
24
|
-
if ( opts.add && opts.remove ) {
|
|
25
|
-
errorExit( 'You cannot specify both --add and --remove.' )
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const action = opts.remove ? 'remove' : 'add'
|
|
29
|
-
|
|
30
|
-
const {
|
|
31
|
-
project,
|
|
32
|
-
org,
|
|
33
|
-
bucket,
|
|
34
|
-
gsa,
|
|
35
|
-
role,
|
|
36
|
-
dryRun
|
|
37
|
-
} = opts
|
|
38
|
-
|
|
39
|
-
const orgId = await shellCmd( 'gcloud organizations list --format="value(ID)"' )
|
|
40
|
-
const gsaEmail = `${gsa}@${project}.iam.gserviceaccount.com`
|
|
41
|
-
const fullRole = org ? `organizations/${orgId}/roles/${role}` : `roles/${role}`
|
|
42
|
-
const bucketUri = `gs://${bucket}`
|
|
43
|
-
|
|
44
|
-
const iamMember = `serviceAccount:${gsaEmail}:${fullRole}`
|
|
45
|
-
|
|
46
|
-
const command = action === 'add' ?
|
|
47
|
-
[ 'gsutil', 'iam', 'ch', iamMember, bucketUri ] :
|
|
48
|
-
[ 'gsutil', 'iam', 'ch', '-d', iamMember, bucketUri ]
|
|
49
|
-
|
|
50
|
-
log( `đ§ ${action === 'add' ? 'Granting' : 'Removing'} ${fullRole} for ${gsaEmail} on ${bucketUri}...` )
|
|
51
|
-
|
|
52
|
-
if ( dryRun ) {
|
|
53
|
-
warning( 'đĄ DRY RUN mode â no commands executed.' )
|
|
54
|
-
log( `đ Command:\n$ ${command.join( ' ' )}` )
|
|
55
|
-
process.exit( 0 )
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
try {
|
|
59
|
-
const result = await shellCmd( command )
|
|
60
|
-
log( `â
IAM ${action} successful:\n${result}` )
|
|
61
|
-
} catch ( err ) {
|
|
62
|
-
errorExit( `â Failed to ${action} IAM binding: ${err.message}` )
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// === Post-change audit ===
|
|
66
|
-
log( 'đ Verifying IAM policy for this GSA on the bucket...\n' )
|
|
67
|
-
|
|
68
|
-
try {
|
|
69
|
-
const policyRaw = await shellCmd( [ 'gsutil', 'iam', 'get', bucketUri ] )
|
|
70
|
-
const policy = JSON.parse( policyRaw )
|
|
71
|
-
|
|
72
|
-
const matchingRoles = policy.bindings.filter(
|
|
73
|
-
b => b.members.includes( `serviceAccount:${gsaEmail}` )
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
if ( matchingRoles.length === 0 ) {
|
|
77
|
-
log( `âšī¸ No IAM bindings found for ${gsaEmail} on ${bucketUri}.` )
|
|
78
|
-
} else {
|
|
79
|
-
for ( const binding of matchingRoles ) {
|
|
80
|
-
log( `đ ${gsaEmail} has role: ${binding.role}` )
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
} catch ( err ) {
|
|
84
|
-
warning( `â ī¸ Failed to retrieve or parse IAM policy: ${err.message}` )
|
|
85
|
-
}
|
package/src/test.json
DELETED
package/src/testOauthLogic.mjs
DELETED
package/src/unleash.mjs
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import SimpleGit from 'simple-git'
|
|
4
|
-
|
|
5
|
-
import { shellCmd } from './Utils.mjs'
|
|
6
|
-
|
|
7
|
-
const git = new SimpleGit()
|
|
8
|
-
|
|
9
|
-
const getCurrentBranchName = async () => {
|
|
10
|
-
const branchInfo = await git.branch()
|
|
11
|
-
|
|
12
|
-
// first check to see if there are no branches - new repo?
|
|
13
|
-
if ( Object.keys( branchInfo.branches ).length === 0 ) { return '' }
|
|
14
|
-
|
|
15
|
-
return Object
|
|
16
|
-
.entries( branchInfo.branches )
|
|
17
|
-
.find( ( [ name, info ] ) => ( info.current ) )[0]
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const isProtected = async () => {
|
|
21
|
-
const theBranch = await getCurrentBranchName()
|
|
22
|
-
|
|
23
|
-
const protectedBranches = [ 'main', 'master', 'development' ]
|
|
24
|
-
const additionalProtectedBranches = [ ...process.argv.slice( 2 ) ]
|
|
25
|
-
|
|
26
|
-
// Check if the current branch starts with any of the additional
|
|
27
|
-
// protected branch name
|
|
28
|
-
let matchesAdditionalBranch = false
|
|
29
|
-
for ( let i = 0; i < additionalProtectedBranches.length; i++ ) {
|
|
30
|
-
matchesAdditionalBranch = matchesAdditionalBranch ||
|
|
31
|
-
theBranch.startsWith( additionalProtectedBranches[i] )
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return protectedBranches.includes( theBranch ) || matchesAdditionalBranch
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const npmRunner = async ( script ) => {
|
|
38
|
-
try {
|
|
39
|
-
const cmd = `npm run ${script}`
|
|
40
|
-
const results = await shellCmd( cmd, { stdio : 'inherit' } )
|
|
41
|
-
return results
|
|
42
|
-
} catch ( err ) { // eslint-disable-line no-unused-vars
|
|
43
|
-
process.exit( 1 )
|
|
44
|
-
}
|
|
45
|
-
return undefined
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
( async () => {
|
|
49
|
-
if ( await isProtected() ) {
|
|
50
|
-
const script = [ 'test', 'lint' ]
|
|
51
|
-
for ( let i = 0; i < script.length; i++ ) {
|
|
52
|
-
await npmRunner( script[i] ) // eslint-disable-line no-await-in-loop
|
|
53
|
-
}
|
|
54
|
-
} else {
|
|
55
|
-
process.exit( 0 )
|
|
56
|
-
}
|
|
57
|
-
} )()
|