@leverege/build-tools 2.66.5 → 2.66.7
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 +6 -3
- package/src/.swo +0 -0
- package/src/Docker.mjs +4 -1
- package/src/DockerPy.mjs +4 -1
- package/src/Utils.mjs +15 -9
- package/src/helm-audit.mjs +54 -55
- package/src/helm-charts/prom-operator/rules/kubestate-rules.yaml +1 -1
- package/src/helm-charts/prom-operator/rules/prometheus-rules.yaml +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leverege/build-tools",
|
|
3
|
-
"version": "2.66.
|
|
3
|
+
"version": "2.66.7",
|
|
4
4
|
"description": "A collection of build / support tools for Leverege developers",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"getfbcfg": "src/getfbcfg.mjs",
|
|
35
35
|
"getjson": "src/getjson.mjs",
|
|
36
36
|
"git-tar": "src/git-tar.sh",
|
|
37
|
+
"helm-audit": "src/helm-audit.mjs",
|
|
37
38
|
"helmcycle": "src/helmup.sh",
|
|
38
39
|
"helmdn": "src/helmdn.sh",
|
|
39
40
|
"helmup": "src/helmup.sh",
|
|
@@ -68,7 +69,7 @@
|
|
|
68
69
|
"commander": "^13.1.0",
|
|
69
70
|
"deepmerge": "^4.3.1",
|
|
70
71
|
"enquirer": "^2.4.1",
|
|
71
|
-
"execa": "^9.5.
|
|
72
|
+
"execa": "^9.5.3",
|
|
72
73
|
"glob": "^11.0.2",
|
|
73
74
|
"handlebars": "^4.7.8",
|
|
74
75
|
"ignore": "^7.0.4",
|
|
@@ -78,12 +79,14 @@
|
|
|
78
79
|
"ms": "^2.1.3",
|
|
79
80
|
"npm-registry-fetch": "^18.0.2",
|
|
80
81
|
"ora": "^8.2.0",
|
|
82
|
+
"p-limit": "^6.2.0",
|
|
81
83
|
"package-up": "^5.0.0",
|
|
82
84
|
"readline-sync": "^1.4.10",
|
|
83
85
|
"semver": "^7.7.1",
|
|
86
|
+
"shell-quote": "^1.8.2",
|
|
84
87
|
"simple-git": "^3.27.0",
|
|
85
88
|
"toml": "^3.0.0",
|
|
86
|
-
"zx": "^8.5.
|
|
89
|
+
"zx": "^8.5.4"
|
|
87
90
|
},
|
|
88
91
|
"devDependencies": {
|
|
89
92
|
"@leverege/eslint-config-leverege": "^5.0.1",
|
package/src/.swo
ADDED
|
Binary file
|
package/src/Docker.mjs
CHANGED
|
@@ -215,6 +215,8 @@ const buildContainerImage = async ( {
|
|
|
215
215
|
|
|
216
216
|
const { fullName : builderName } = await getGcpAccount()
|
|
217
217
|
const gcloudBuild = `gcloud builds submit --project ${artifactProject}`
|
|
218
|
+
const gcloudProjectNumber = await shellCmd( `gcloud projects describe ${artifactProject} --format="value(projectNumber)"` )
|
|
219
|
+
const cloudBuildSA = `--service-account=${gcloudProjectNumber}-compute@cloudbuild.gserviceaccount.com`
|
|
218
220
|
const gcloudLogs = `--gcs-log-dir ${formCloudBuildBucketName( artifactProject )}/log`
|
|
219
221
|
let gcloudTags = `--tag ${imageName}:${imageVersion}`
|
|
220
222
|
|
|
@@ -231,7 +233,8 @@ const buildContainerImage = async ( {
|
|
|
231
233
|
*** Submitting Build as ${builderName} ***
|
|
232
234
|
${gcloudBuild} \\
|
|
233
235
|
${gcloudLogs} \\
|
|
234
|
-
${gcloudTags}
|
|
236
|
+
${gcloudTags} \\
|
|
237
|
+
${cloudBuildSA}
|
|
235
238
|
` ) )
|
|
236
239
|
|
|
237
240
|
if ( process.env.DRY_RUN === '1' ) {
|
package/src/DockerPy.mjs
CHANGED
|
@@ -185,6 +185,8 @@ async function buildContainerImage( {
|
|
|
185
185
|
|
|
186
186
|
const { fullName : builderName } = await getGcpAccount()
|
|
187
187
|
const gcloudBuild = `gcloud builds submit --project ${artifactProject}`
|
|
188
|
+
const gcloudProjectNumber = await shellCmd( `gcloud projects describe ${artifactProject} --format="value(projectNumber)"` )
|
|
189
|
+
const cloudBuildSA = `--service-account=${gcloudProjectNumber}-compute@cloudbuild.gserviceaccount.com`
|
|
188
190
|
const gcloudLogs = `--gcs-log-dir ${formCloudBuildBucketName( artifactProject )}/log`
|
|
189
191
|
let gcloudTags = `--tag ${imageName}:${imageVersion}`
|
|
190
192
|
|
|
@@ -201,7 +203,8 @@ async function buildContainerImage( {
|
|
|
201
203
|
*** Submitting Build as ${builderName} ***
|
|
202
204
|
${gcloudBuild} \\
|
|
203
205
|
${gcloudLogs} \\
|
|
204
|
-
${gcloudTags}
|
|
206
|
+
${gcloudTags} \\
|
|
207
|
+
${cloudBuildSA}
|
|
205
208
|
` ) )
|
|
206
209
|
|
|
207
210
|
if ( process.env.DRY_RUN === '1' ) {
|
package/src/Utils.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import ignore from 'ignore'
|
|
|
8
8
|
import inquirer from 'inquirer'
|
|
9
9
|
import { glob } from 'glob'
|
|
10
10
|
import { packageUp } from 'package-up'
|
|
11
|
+
import { parse } from 'shell-quote'
|
|
11
12
|
import YAML from 'js-yaml'
|
|
12
13
|
|
|
13
14
|
// __dirname goes away with ESM so we take this approach instead and
|
|
@@ -72,20 +73,25 @@ export const proceed = async ( query = 'Do you wish to proceed?' ) => {
|
|
|
72
73
|
} )
|
|
73
74
|
}
|
|
74
75
|
|
|
75
|
-
export const shellCmd = async (
|
|
76
|
+
export const shellCmd = async ( cmd, opts = {} ) => {
|
|
76
77
|
try {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
let command, args
|
|
79
|
+
|
|
80
|
+
if ( Array.isArray( cmd ) ) {
|
|
81
|
+
[ command, ...args ] = cmd
|
|
82
|
+
} else {
|
|
83
|
+
const parsed = parse( cmd ).filter( x => typeof x === 'string' )
|
|
84
|
+
// the leading ; forces a break from previous line otherwise trailing ) and leading [ collide
|
|
85
|
+
;[ command, ...args ] = parsed // eslint-disable-line semi-style
|
|
86
|
+
}
|
|
81
87
|
|
|
82
|
-
debug( { command, args }, '<==execa $ invoke' )
|
|
83
|
-
const results = await $( opts )
|
|
84
|
-
debug( { results }, '<==execa $ results' )
|
|
88
|
+
debug( { command, args }, '<== execa $ invoke' )
|
|
89
|
+
const results = await $( opts )( command, args )
|
|
90
|
+
debug( { results }, '<== execa $ results' )
|
|
85
91
|
|
|
86
92
|
return results.stdout
|
|
87
93
|
} catch ( error ) {
|
|
88
|
-
debug( { error }, '<==shellCmd' )
|
|
94
|
+
debug( { error }, '<== shellCmd' )
|
|
89
95
|
throw error
|
|
90
96
|
}
|
|
91
97
|
}
|
package/src/helm-audit.mjs
CHANGED
|
@@ -1,71 +1,71 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// helm-audit.mjs
|
|
4
|
-
//
|
|
4
|
+
// kind of a better "helm list" but still experimental
|
|
5
5
|
|
|
6
|
-
import { shellCmd, log, debug } from './Utils.mjs'
|
|
7
6
|
import ora from 'ora'
|
|
8
7
|
import pLimit from 'p-limit'
|
|
9
8
|
import chalk from 'chalk'
|
|
9
|
+
import { shellCmd, log, errorExit } from './Utils.mjs'
|
|
10
10
|
|
|
11
|
-
const spinner = ora('Gathering Helm release info...').start()
|
|
12
|
-
const limit = pLimit(5) // limit concurrent shellCmds to avoid API overload
|
|
13
|
-
const OMIT_NAMESPACES = new Set(['estafette'])
|
|
11
|
+
const spinner = ora( 'Gathering Helm release info...' ).start()
|
|
12
|
+
const limit = pLimit( 5 ) // limit concurrent shellCmds to avoid API overload
|
|
13
|
+
const OMIT_NAMESPACES = new Set( [ 'estafette' ] )
|
|
14
14
|
|
|
15
15
|
async function getHelmReleases() {
|
|
16
|
-
const json = await shellCmd('helm list -A -o json')
|
|
17
|
-
return JSON.parse(json).filter(r => !OMIT_NAMESPACES.has(r.namespace))
|
|
16
|
+
const json = await shellCmd( 'helm list -A -o json' )
|
|
17
|
+
return JSON.parse( json ).filter( r => !OMIT_NAMESPACES.has( r.namespace ) )
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
async function getDeployedImageTag(ns, release) {
|
|
20
|
+
async function getDeployedImageTag( ns, release ) {
|
|
21
21
|
try {
|
|
22
|
-
const image = await shellCmd(`kubectl get deployment -n ${ns} -l app.kubernetes.io/instance=${release} -o jsonpath={.items[0].spec.template.spec.containers[0].image}`)
|
|
23
|
-
const tag = image.trim().split(':')[1]
|
|
22
|
+
const image = await shellCmd( `kubectl get deployment -n ${ns} -l app.kubernetes.io/instance=${release} -o jsonpath={.items[0].spec.template.spec.containers[0].image}` )
|
|
23
|
+
const tag = image.trim().split( ':' )[1]
|
|
24
24
|
return tag && tag !== 'not found' ? tag : ''
|
|
25
25
|
} catch {
|
|
26
26
|
return ''
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
async function getChartAppVersion(ns, release) {
|
|
30
|
+
async function getChartAppVersion( ns, release ) {
|
|
31
31
|
try {
|
|
32
|
-
const metadata = await shellCmd(`helm get metadata ${release} -n ${ns}`)
|
|
33
|
-
const match = metadata.match(/^APP_VERSION:\s*(.*?)\s*$/m)
|
|
32
|
+
const metadata = await shellCmd( `helm get metadata ${release} -n ${ns}` )
|
|
33
|
+
const match = metadata.match( /^APP_VERSION:\s*(.*?)\s*$/m )
|
|
34
34
|
return match ? match[1].trim() : '(unknown)'
|
|
35
35
|
} catch {
|
|
36
36
|
return '(unknown)'
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
async function getHelmValue(ns, release, key) {
|
|
40
|
+
async function getHelmValue( ns, release, key ) {
|
|
41
41
|
try {
|
|
42
|
-
const values = await shellCmd(`helm get values ${release} -n ${ns} -o json`)
|
|
43
|
-
const parsed = JSON.parse(values)
|
|
42
|
+
const values = await shellCmd( `helm get values ${release} -n ${ns} -o json` )
|
|
43
|
+
const parsed = JSON.parse( values )
|
|
44
44
|
return parsed.helmup?.[key] || ''
|
|
45
45
|
} catch {
|
|
46
46
|
return ''
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
function normalizeTag(tag) {
|
|
51
|
-
return tag?.replace(/^v/, '').toLowerCase() || ''
|
|
50
|
+
function normalizeTag( tag ) {
|
|
51
|
+
return tag?.replace( /^v/, '' ).toLowerCase() || ''
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
function formatRow(name, chartVersion, appVersion, imageTag, deployT, culprit) {
|
|
55
|
-
const release = chalk.green(name.slice(0, 25).padEnd(32))
|
|
56
|
-
const chartVer = chalk.cyan(chartVersion.padEnd(18))
|
|
57
|
-
const appVer = chalk.cyan(appVersion.padEnd(18))
|
|
58
|
-
const normApp = normalizeTag(appVersion)
|
|
59
|
-
const normImage = normalizeTag(imageTag)
|
|
60
|
-
|
|
61
|
-
let imageFormatted = imageTag.padEnd(20)
|
|
62
|
-
if (normImage && normApp && normImage === normApp) {
|
|
63
|
-
imageFormatted = chalk.green(imageFormatted)
|
|
64
|
-
} else if (imageTag) {
|
|
65
|
-
imageFormatted = chalk.red(imageFormatted)
|
|
54
|
+
function formatRow( name, chartVersion, appVersion, imageTag, deployT, culprit ) {
|
|
55
|
+
const release = chalk.green( name.slice( 0, 25 ).padEnd( 32 ) )
|
|
56
|
+
const chartVer = chalk.cyan( chartVersion.padEnd( 18 ) )
|
|
57
|
+
const appVer = chalk.cyan( appVersion.padEnd( 18 ) )
|
|
58
|
+
const normApp = normalizeTag( appVersion )
|
|
59
|
+
const normImage = normalizeTag( imageTag )
|
|
60
|
+
|
|
61
|
+
let imageFormatted = imageTag.padEnd( 20 )
|
|
62
|
+
if ( normImage && normApp && normImage === normApp ) {
|
|
63
|
+
imageFormatted = chalk.green( imageFormatted )
|
|
64
|
+
} else if ( imageTag ) {
|
|
65
|
+
imageFormatted = chalk.red( imageFormatted )
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
const deployInfo = deployT ? chalk.gray(`${deployT} by ${culprit || '(unknown)'}`) : ''
|
|
68
|
+
const deployInfo = deployT ? chalk.gray( `${deployT} by ${culprit || '(unknown)'}` ) : ''
|
|
69
69
|
return ` ${release}${chartVer}${appVer}${imageFormatted}${deployInfo}`
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -74,43 +74,42 @@ async function audit() {
|
|
|
74
74
|
const releases = await getHelmReleases()
|
|
75
75
|
|
|
76
76
|
// sort by namespace, then release name
|
|
77
|
-
releases.sort((a, b) => {
|
|
78
|
-
const nsCompare = a.namespace.localeCompare(b.namespace)
|
|
79
|
-
return nsCompare !== 0 ? nsCompare : a.name.localeCompare(b.name)
|
|
80
|
-
})
|
|
77
|
+
releases.sort( ( a, b ) => {
|
|
78
|
+
const nsCompare = a.namespace.localeCompare( b.namespace )
|
|
79
|
+
return nsCompare !== 0 ? nsCompare : a.name.localeCompare( b.name )
|
|
80
|
+
} )
|
|
81
81
|
|
|
82
82
|
spinner.text = 'Gathering chart, image, and audit metadata...'
|
|
83
83
|
|
|
84
|
-
const rows = await Promise.all(releases.map(({ name, namespace, chart }) => limit(async () => {
|
|
85
|
-
const chartVersion = chart?.split('-').pop() || '(unknown)'
|
|
86
|
-
const [appVersion, imageTag, deployT, culprit] = await Promise.all([
|
|
87
|
-
getChartAppVersion(namespace, name),
|
|
88
|
-
getDeployedImageTag(namespace, name),
|
|
89
|
-
getHelmValue(namespace, name, 'deployT'),
|
|
90
|
-
getHelmValue(namespace, name, 'culprit'),
|
|
91
|
-
])
|
|
84
|
+
const rows = await Promise.all( releases.map( ( { name, namespace, chart } ) => limit( async () => {
|
|
85
|
+
const chartVersion = chart?.split( '-' ).pop() || '(unknown)'
|
|
86
|
+
const [ appVersion, imageTag, deployT, culprit ] = await Promise.all( [
|
|
87
|
+
getChartAppVersion( namespace, name ),
|
|
88
|
+
getDeployedImageTag( namespace, name ),
|
|
89
|
+
getHelmValue( namespace, name, 'deployT' ),
|
|
90
|
+
getHelmValue( namespace, name, 'culprit' ),
|
|
91
|
+
] )
|
|
92
92
|
return {
|
|
93
|
-
row: formatRow(name, chartVersion, appVersion, imageTag, deployT, culprit),
|
|
93
|
+
row : formatRow( name, chartVersion, appVersion, imageTag, deployT, culprit ),
|
|
94
94
|
namespace
|
|
95
95
|
}
|
|
96
|
-
})))
|
|
96
|
+
} ) ) )
|
|
97
97
|
|
|
98
98
|
spinner.stop()
|
|
99
|
-
log(`${'RELEASE'.padEnd(34)}${'CHART VERSION'.padEnd(18)}${'APP VERSION'.padEnd(18)}${'IMAGE TAG'.padEnd(20)}DEPLOY INFO`)
|
|
99
|
+
log( `${'RELEASE'.padEnd( 34 )}${'CHART VERSION'.padEnd( 18 )}${'APP VERSION'.padEnd( 18 )}${'IMAGE TAG'.padEnd( 20 )}DEPLOY INFO` )
|
|
100
100
|
|
|
101
101
|
let lastNamespace = ''
|
|
102
|
-
for (const { row, namespace } of rows) {
|
|
103
|
-
if (namespace !== lastNamespace) {
|
|
104
|
-
if (lastNamespace !== '') log('')
|
|
105
|
-
log(chalk.bold.green(namespace))
|
|
102
|
+
for ( const { row, namespace } of rows ) {
|
|
103
|
+
if ( namespace !== lastNamespace ) {
|
|
104
|
+
if ( lastNamespace !== '' ) log( '' )
|
|
105
|
+
log( chalk.bold.green( namespace ) )
|
|
106
106
|
lastNamespace = namespace
|
|
107
107
|
}
|
|
108
|
-
log(row)
|
|
108
|
+
log( row )
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
audit().catch(err => {
|
|
112
|
+
audit().catch( ( err ) => {
|
|
113
113
|
spinner.stop()
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
})
|
|
114
|
+
errorExit( err )
|
|
115
|
+
} )
|
|
@@ -176,7 +176,7 @@ spec:
|
|
|
176
176
|
# LABELS = {{ $labels }}
|
|
177
177
|
- alert: KubernetesHpaMetricsUnavailability
|
|
178
178
|
expr: kube_horizontalpodautoscaler_status_condition{status="false", condition="ScalingActive"} == 1
|
|
179
|
-
for: 0m
|
|
179
|
+
for: 3m # awesome was => 0m
|
|
180
180
|
labels:
|
|
181
181
|
severity: warning
|
|
182
182
|
annotations:
|