@leverege/build-tools 2.101.0 → 2.101.1
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 +2 -2
- package/src/bash-funcs +0 -22
- package/src/DockerPy.mjs +0 -266
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leverege/build-tools",
|
|
3
|
-
"version": "2.101.
|
|
3
|
+
"version": "2.101.1",
|
|
4
4
|
"description": "A collection of build / support tools for Leverege developers",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"helmup": "src/helmup.sh",
|
|
49
49
|
"helmwhat": "src/helmup.sh",
|
|
50
50
|
"hook-and-release": "src/hook-and-release.mjs",
|
|
51
|
-
"init-my-chart": "src/init-my-chart.mjs",
|
|
51
|
+
"init-my-chart": "src/init-my-chart/init-my-chart.mjs",
|
|
52
52
|
"k8scale": "src/k8scale.sh",
|
|
53
53
|
"k8x": "src/k8x.sh",
|
|
54
54
|
"klog": "src/klog.sh",
|
package/src/bash-funcs
CHANGED
|
@@ -229,28 +229,6 @@ function waitForIAM() {
|
|
|
229
229
|
done
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
-
# *** DEPRECATED *** REMOVE AFTER BITNAMI ERADICATED ***
|
|
233
|
-
# *** DEPRECATED *** REMOVE AFTER BITNAMI ERADICATED ***
|
|
234
|
-
# *** DEPRECATED *** REMOVE AFTER BITNAMI ERADICATED ***
|
|
235
|
-
#
|
|
236
|
-
function addBitnamiRepo() {
|
|
237
|
-
warning '*** the addBitnamiRepo function should be removed - DEPRECATED ***'
|
|
238
|
-
if [ ! -z "$BITNAMI_LATEST" ] || [ "$1" == "latest" ];
|
|
239
|
-
then
|
|
240
|
-
BITNAMI_URL="https://charts.bitnami.com/bitnami"
|
|
241
|
-
else
|
|
242
|
-
cat<<CATNAMI
|
|
243
|
-
Using the pre 2022 legacy charts from bitnami. To use latest run:
|
|
244
|
-
|
|
245
|
-
`color y "BITNAMI_LATEST=1 $HELMUP_ARGS"`
|
|
246
|
-
|
|
247
|
-
CATNAMI
|
|
248
|
-
BITNAMI_URL="https://raw.githubusercontent.com/bitnami/charts/eb5f9a9513d987b519f0ecd732e7031241c50328/bitnami"
|
|
249
|
-
fi
|
|
250
|
-
|
|
251
|
-
addHelmRepo bitnami $BITNAMI_URL
|
|
252
|
-
}
|
|
253
|
-
|
|
254
232
|
function removeHelmRepo(){
|
|
255
233
|
[ ! -z "$SKIP_RM_HELM_REPO" ] && return
|
|
256
234
|
helm repo remove $1 &> $DEVNULL
|
package/src/DockerPy.mjs
DELETED
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DEPRECATED - DO NOT MODIFY
|
|
3
|
-
*/
|
|
4
|
-
import fs from 'node:fs'
|
|
5
|
-
import path from 'node:path'
|
|
6
|
-
import url from 'node:url'
|
|
7
|
-
|
|
8
|
-
import chalk from 'chalk'
|
|
9
|
-
import handlebars from 'handlebars'
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
errorExit,
|
|
13
|
-
getCleanTag,
|
|
14
|
-
getDateTimestamp,
|
|
15
|
-
getGcpAccount,
|
|
16
|
-
log,
|
|
17
|
-
proceed,
|
|
18
|
-
shellCmd,
|
|
19
|
-
warning
|
|
20
|
-
} from './Utils.mjs'
|
|
21
|
-
|
|
22
|
-
const DIRNAME = path.dirname( url.fileURLToPath( import.meta.url ) )
|
|
23
|
-
|
|
24
|
-
// The contents of these variables were initially located in files that live in
|
|
25
|
-
// the build-tools repository, but it just became simpler to pull the contents
|
|
26
|
-
// directly into these variables and forego the file loading.
|
|
27
|
-
//
|
|
28
|
-
const pluginTemplate = `
|
|
29
|
-
# Dockerfile.plugin - optionally extend the service Docker image
|
|
30
|
-
#
|
|
31
|
-
# This file may be used to run additional docker commands during the image
|
|
32
|
-
# build process without needing to maintain a local custom Dockerfile. For
|
|
33
|
-
# example, uncommenting the following docker RUN command will cause the
|
|
34
|
-
# curl and vim packages to be added to the deployed image thus making them
|
|
35
|
-
# available from the pod's command line on k8s:
|
|
36
|
-
#
|
|
37
|
-
# RUN apk update && apk add --no-cache curl vim
|
|
38
|
-
#
|
|
39
|
-
# Keep in mind that the Alpine Linux base image is used to keep image
|
|
40
|
-
# footprints small, so adding packages "just because" is not considered
|
|
41
|
-
# a best practice.
|
|
42
|
-
`
|
|
43
|
-
const dockerfileTemplate = fs.readFileSync( path.join( DIRNAME, './templates/dockerfileTemplatePy.hbs' ), 'utf8' )
|
|
44
|
-
const cloudBuildSteps = fs.readFileSync( path.join( DIRNAME, './templates/cloudBuildTargetGKE.hbs' ), 'utf8' )
|
|
45
|
-
let bashrcTemplate = fs.readFileSync( path.join( DIRNAME, './templates/bashrcTemplate.hbs' ), 'utf8' )
|
|
46
|
-
const bashrcPyTemplate = fs.readFileSync( path.join( DIRNAME, './templates/bashrcTemplatePy.hbs' ), 'utf8' )
|
|
47
|
-
bashrcTemplate = `${bashrcTemplate}\n${bashrcPyTemplate}`
|
|
48
|
-
|
|
49
|
-
const defaultSettings = {
|
|
50
|
-
date : getDateTimestamp(),
|
|
51
|
-
imageBase : 'python:3.12.8-slim-bookworm',
|
|
52
|
-
npmlogging : process.env.VERBOSE_NPM_LOGGING ? '--ddd' : '--silent',
|
|
53
|
-
npmVersion : 'npm@11',
|
|
54
|
-
pluginfile : '# NO PLUGIN',
|
|
55
|
-
preInstallPluginfile : '# NO PRE-INSTALL PLUGIN',
|
|
56
|
-
regvers : 'package.version',
|
|
57
|
-
runuser : 'python',
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// the previous build version is simply informational for the user
|
|
61
|
-
const previousFile = './docker/.previous'
|
|
62
|
-
|
|
63
|
-
function getPreviousBuild() {
|
|
64
|
-
return fs.existsSync( previousFile ) ? fs.readFileSync( previousFile ) : 'FIRST BUILD'
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const setPreviousBuild = ( version ) => {
|
|
68
|
-
fs.writeFileSync( previousFile, version )
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// the base image string to be in the form of an image name and a version
|
|
72
|
-
// for example:
|
|
73
|
-
//
|
|
74
|
-
// python:3.12.8-slim-bookworm becomes python-3.12.8
|
|
75
|
-
// nvcr.io/nvidia/cuda:12.3.1-base-ubuntu22.04 becomes cuda-12.3.1
|
|
76
|
-
//
|
|
77
|
-
// which will then be used to tag the image for information purposes only
|
|
78
|
-
const extractBaseImageTag = ( imageStr ) => {
|
|
79
|
-
const match = imageStr.match( /(\w+:\d+(?:\.\d+)*)(?=-)/ ) // eslint-disable-line security/detect-unsafe-regex
|
|
80
|
-
return match ? match[1].replace( ':', '-' ) : null
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function generateDockerfile( options ) {
|
|
84
|
-
|
|
85
|
-
const settings = { ...defaultSettings, ...options }
|
|
86
|
-
settings.image = settings.imageBase
|
|
87
|
-
// TODO: this is a janky way to pass the image tag back out
|
|
88
|
-
defaultSettings.buildTag = extractBaseImageTag( settings.image )
|
|
89
|
-
|
|
90
|
-
// Ensure the presence of the docker dir with plugin and bashrc - this code
|
|
91
|
-
// could probably be tightened up a little.
|
|
92
|
-
try {
|
|
93
|
-
fs.readdirSync( './docker' )
|
|
94
|
-
} catch ( err ) {
|
|
95
|
-
warning( 'creating the missing ./docker directory' )
|
|
96
|
-
fs.mkdirSync( './docker' ) // TODO: blindly assumes the mkdir succeeds
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const bashrcFile = './docker/bashrc'
|
|
100
|
-
let bf = bashrcTemplate
|
|
101
|
-
const bashrcFilePlugin = './docker/Bashrc.plugin'
|
|
102
|
-
if ( fs.existsSync( bashrcFilePlugin ) ) {
|
|
103
|
-
const bashrcAdditions = fs.readFileSync( bashrcFilePlugin )
|
|
104
|
-
bf = `${bf}\n${bashrcAdditions}`
|
|
105
|
-
}
|
|
106
|
-
fs.writeFileSync( bashrcFile, bf )
|
|
107
|
-
|
|
108
|
-
const dockerfilePlugin = './docker/Dockerfile.plugin'
|
|
109
|
-
if ( !fs.existsSync( dockerfilePlugin ) ) {
|
|
110
|
-
warning( `creating the missing ${dockerfilePlugin} file in the docker directory` )
|
|
111
|
-
fs.writeFileSync( dockerfilePlugin, pluginTemplate )
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
try {
|
|
115
|
-
const build = fs.readdirSync( './build' )
|
|
116
|
-
if ( build.length === 0 ) {
|
|
117
|
-
errorExit( `***ERROR: the build dir is empty - ${chalk.yellow( 'npm run build' )}` )
|
|
118
|
-
}
|
|
119
|
-
} catch ( err ) {
|
|
120
|
-
errorExit( `***ERROR: expected the ./build directory to exist - ${chalk.yellow( 'npm run build' )}` )
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// At this point the plugin template better exist.
|
|
124
|
-
if ( fs.existsSync( dockerfilePlugin ) ) {
|
|
125
|
-
settings.pluginfile = fs.readFileSync( dockerfilePlugin )
|
|
126
|
-
} else {
|
|
127
|
-
errorExit( `***ERROR: something went wrong with ${dockerfilePlugin} plugin creation` )
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const dockerfilePrePlugin = './docker/DockerfilePreInstall.plugin'
|
|
131
|
-
if ( fs.existsSync( dockerfilePrePlugin ) ) {
|
|
132
|
-
settings.preInstallPluginfile = fs.readFileSync( dockerfilePrePlugin )
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const compiled = handlebars.compile( dockerfileTemplate, { noEscape : true } )
|
|
136
|
-
const replaced = compiled( settings )
|
|
137
|
-
// temporarily write the Dockerfile to the docker subdir - the container
|
|
138
|
-
// image builder will then move it over to the build subdir
|
|
139
|
-
const dockerfile = './docker/Dockerfile'
|
|
140
|
-
try {
|
|
141
|
-
fs.writeFileSync( dockerfile, replaced )
|
|
142
|
-
} catch ( err ) {
|
|
143
|
-
errorExit( `***ERROR: failed to write ${dockerfile}\n${err}` )
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const previousBuild = getPreviousBuild()
|
|
147
|
-
const dockerInfo = { dockerfile, previousBuild, ...settings }
|
|
148
|
-
delete dockerInfo.pluginfile
|
|
149
|
-
return dockerInfo
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function formCloudBuildBucketName( artifactProject ) {
|
|
153
|
-
return `gs://${artifactProject}_cloudbuild`
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
async function validateCloudBuildBucket( artifactProject ) {
|
|
157
|
-
const bucketName = formCloudBuildBucketName( artifactProject )
|
|
158
|
-
log( chalk.green.bold( `Verifying the build bucket exists => ${bucketName}\n` ) )
|
|
159
|
-
try {
|
|
160
|
-
await shellCmd( `gsutil ls -p ${artifactProject} -b ${bucketName}` )
|
|
161
|
-
} catch ( error ) {
|
|
162
|
-
errorExit( `***Error: from Docker.validateCloudBuildBucket\n\n${chalk.bold.yellow( error )}` )
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
async function buildContainerImage( {
|
|
167
|
-
artifactProject, artifactRegistry, containerName,
|
|
168
|
-
imageVersion, isNpmWorkspace, options
|
|
169
|
-
} ) {
|
|
170
|
-
const buildWorkspace = './build/workspace' // passed to Cloud Build
|
|
171
|
-
const imageName = `${artifactRegistry}/images/${containerName}`
|
|
172
|
-
|
|
173
|
-
// clean up any residual build cruft (should be clean though)
|
|
174
|
-
if ( fs.existsSync( buildWorkspace ) ) {
|
|
175
|
-
fs.renameSync( buildWorkspace, `${buildWorkspace}-junk` )
|
|
176
|
-
fs.rm( `${buildWorkspace}-junk`, { recursive : true }, ( err ) => {} ) // fire and forget
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// TODO: This is janky - I'll clean it up later
|
|
180
|
-
// NOTE: this is dealing with raw filesystem interactions, meaning there
|
|
181
|
-
// isn't a shell performing file globbing and what not
|
|
182
|
-
fs.renameSync( './build', './workspace' )
|
|
183
|
-
fs.mkdirSync( './build' )
|
|
184
|
-
fs.renameSync( './workspace', buildWorkspace )
|
|
185
|
-
fs.renameSync( './docker/Dockerfile', './build/Dockerfile' )
|
|
186
|
-
fs.renameSync( './docker/bashrc', './build/bashrc' )
|
|
187
|
-
// fs.cpSync( `${process.env.HOME}/.npmrc`, './build/.npmrc' )
|
|
188
|
-
// fs.cpSync( './package.json', `${buildWorkspace}/package.json` )
|
|
189
|
-
// fs.cpSync( './package-lock.json', `${buildWorkspace}/package-lock.json` )
|
|
190
|
-
|
|
191
|
-
setPreviousBuild( imageVersion ) // update docker/.previous file
|
|
192
|
-
|
|
193
|
-
const { fullName } = await getGcpAccount()
|
|
194
|
-
const imageBuilder = getCleanTag( fullName )
|
|
195
|
-
const imageArch = defaultSettings.buildTag
|
|
196
|
-
const imageInfoTag = `zzinfo_${imageArch}_${imageBuilder}_${defaultSettings.date}`
|
|
197
|
-
const gcloudProjectNumber = await shellCmd( `gcloud projects describe ${artifactProject} --format="value(projectNumber)"` )
|
|
198
|
-
|
|
199
|
-
// build the cloudbuild.yaml from the handlebars template
|
|
200
|
-
const cloudBuildFile = './build/cloudbuild.yaml'
|
|
201
|
-
const cbst = handlebars.compile( cloudBuildSteps, { noEscape : true } )
|
|
202
|
-
const cbs = cbst( { artifactProject, artifactRegistry, imageName, imageVersion, imageInfoTag, } )
|
|
203
|
-
fs.writeFileSync( cloudBuildFile, cbs )
|
|
204
|
-
|
|
205
|
-
// build up the cloud build command and options
|
|
206
|
-
const cloudBuildCmd = `gcloud builds submit --project ${artifactProject}`
|
|
207
|
-
const cloudBuildLogs = `--gcs-log-dir ${formCloudBuildBucketName( artifactProject )}/log`
|
|
208
|
-
const cloudBuildCfg = `--config=${cloudBuildFile}`
|
|
209
|
-
const cloudBuildSA = `--service-account=${gcloudProjectNumber}-compute@cloudbuild.gserviceaccount.com`
|
|
210
|
-
|
|
211
|
-
log( chalk.green.bold( `
|
|
212
|
-
*** Submitting Build as ${imageBuilder} ***
|
|
213
|
-
${cloudBuildCmd} \\
|
|
214
|
-
${cloudBuildLogs} \\
|
|
215
|
-
${cloudBuildCfg} \\
|
|
216
|
-
${cloudBuildSA}
|
|
217
|
-
` ) )
|
|
218
|
-
|
|
219
|
-
if ( process.env.DRY_RUN === '1' ) {
|
|
220
|
-
log( `Would have run => ${cloudBuildCmd} ${cloudBuildLogs} ${cloudBuildCfg} ./build` )
|
|
221
|
-
log( '\n***Exiting from DRY_RUN\n' )
|
|
222
|
-
process.exit( 0 )
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
await shellCmd( `${cloudBuildCmd} ${cloudBuildLogs} ${cloudBuildCfg} ./build`, { stdio : 'inherit' } )
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
async function repoCleanup() {
|
|
229
|
-
// remove garbage from the repo
|
|
230
|
-
const garbage = [
|
|
231
|
-
'build',
|
|
232
|
-
'dist',
|
|
233
|
-
'docker/.keep',
|
|
234
|
-
'docker/.npmrc',
|
|
235
|
-
'docker/.gitignore',
|
|
236
|
-
'docker/.previous',
|
|
237
|
-
'docker/Dockerfile',
|
|
238
|
-
'docker/workspace',
|
|
239
|
-
]
|
|
240
|
-
|
|
241
|
-
garbage.forEach( trash => fs.rmSync( trash, { recursive : true, force : true } ) )
|
|
242
|
-
|
|
243
|
-
fs.writeFileSync( 'docker/.gitignore', '.previous\nDockerfile' )
|
|
244
|
-
|
|
245
|
-
await shellCmd( 'git add -f docker' )
|
|
246
|
-
|
|
247
|
-
log( `
|
|
248
|
-
${chalk.yellow.bold( '***IMPORTANT***' )}
|
|
249
|
-
|
|
250
|
-
Please make the following .gitignore modifications:
|
|
251
|
-
change /dist to ${chalk.green.bold( '/build' )}
|
|
252
|
-
remove ${chalk.red.bold( '/docker' )}
|
|
253
|
-
` )
|
|
254
|
-
|
|
255
|
-
await proceed( 'Acknowledge the .gitignore mods were made?' )
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
export default {
|
|
259
|
-
getPreviousBuild,
|
|
260
|
-
setPreviousBuild,
|
|
261
|
-
generateDockerfile,
|
|
262
|
-
formCloudBuildBucketName,
|
|
263
|
-
validateCloudBuildBucket,
|
|
264
|
-
buildContainerImage,
|
|
265
|
-
repoCleanup,
|
|
266
|
-
}
|