@leverege/build-tools 2.46.0-beta.1 → 2.46.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leverege/build-tools",
3
- "version": "2.46.0-beta.1",
3
+ "version": "2.46.0",
4
4
  "description": "A collection of build / support tools for Leverege developers",
5
5
  "main": "index.js",
6
6
  "repository": {
package/src/Docker.mjs CHANGED
@@ -3,7 +3,7 @@ import fs from 'node:fs'
3
3
  import chalk from 'chalk'
4
4
  import handlebars from 'handlebars'
5
5
 
6
- import { errorExit, log, shellCmd, warning } from './Utils.mjs'
6
+ import { errorExit, log, proceed, shellCmd, warning } from './Utils.mjs'
7
7
 
8
8
  // The contents of these variables were initially located in files that live in
9
9
  // the build-tools repository, but it just became simpler to pull the contents
@@ -116,6 +116,10 @@ cmclear()
116
116
  {
117
117
  cmstat /status/clear
118
118
  }
119
+
120
+ dunm() {
121
+ du -sh /usr/src/app/node_modules/* | sort -sh
122
+ }
119
123
  `
120
124
 
121
125
  // Just uses the old dockreate of formatting the date.
@@ -169,10 +173,10 @@ const generateDockerfile = ( settings = defaultSettings ) => {
169
173
  try {
170
174
  const build = fs.readdirSync( './build' )
171
175
  if ( build.length === 0 ) {
172
- errorExit( `***ERROR: the build dir is empty - ${chalk.yellow( 'run npm build' )}` )
176
+ errorExit( `***ERROR: the build dir is empty - ${chalk.yellow( 'npm run build' )}` )
173
177
  }
174
178
  } catch ( err ) {
175
- errorExit( `***ERROR: expected the ./build directory to exist - ${chalk.yellow( 'run npm build' )}` )
179
+ errorExit( `***ERROR: expected the ./build directory to exist - ${chalk.yellow( 'npm run build' )}` )
176
180
  }
177
181
 
178
182
  // At this point the plugin template better exist.
@@ -184,6 +188,8 @@ const generateDockerfile = ( settings = defaultSettings ) => {
184
188
 
185
189
  const compiled = handlebars.compile( dockerfileTemplate )
186
190
  const replaced = compiled( settings )
191
+ // temporarily write the Dockerfile to the docker subdir - the container
192
+ // image builder will then move it over to the build subdir
187
193
  const dockerfile = './docker/Dockerfile'
188
194
  try {
189
195
  fs.writeFileSync( dockerfile, replaced )
@@ -212,19 +218,24 @@ const validateCloudBuildBucket = async ( artifactProject ) => {
212
218
  }
213
219
 
214
220
  const buildContainerImage = async ( { artifactProject, artifactRegistry, containerName, imageVersion } ) => {
215
- const cloudBuildWorkspace = './docker/workspace'
221
+ const buildWorkspace = './build/workspace' // passed to Cloud Build
216
222
 
217
- if ( fs.existsSync( cloudBuildWorkspace ) ) {
218
- fs.renameSync( cloudBuildWorkspace, `${cloudBuildWorkspace}-junk` )
219
- fs.rm( `${cloudBuildWorkspace}-junk`, { recursive : true }, ( err ) => {} ) // fire and forget
223
+ if ( fs.existsSync( buildWorkspace ) ) {
224
+ fs.renameSync( buildWorkspace, `${buildWorkspace}-junk` )
225
+ fs.rm( `${buildWorkspace}-junk`, { recursive : true }, ( err ) => {} ) // fire and forget
220
226
  }
221
227
 
222
- fs.mkdirSync( cloudBuildWorkspace )
223
-
224
- fs.cpSync( './build', './docker/workspace', { recursive : true } )
225
- fs.cpSync( `${process.env.HOME}/.npmrc`, './docker/.npmrc' )
226
- fs.cpSync( './package.json', './docker/workspace/package.json' )
227
- fs.renameSync( './package-lock.json', './docker/workspace/package-lock.json' )
228
+ // TODO: This is janky - I'll clean it up later
229
+ // NOTE: this is dealing with raw filesystem interactions, meaning there
230
+ // isn't a shell performing file globbing and what not
231
+ fs.renameSync( './build', './workspace' )
232
+ fs.mkdirSync( './build' )
233
+ fs.renameSync( './workspace', buildWorkspace )
234
+ fs.renameSync( './docker/Dockerfile', './build/Dockerfile' )
235
+ fs.cpSync( `${process.env.HOME}/.npmrc`, './build/.npmrc' )
236
+ fs.cpSync( './docker/bashrc', './build/bashrc' )
237
+ fs.cpSync( './package.json', `${buildWorkspace}/package.json` )
238
+ fs.renameSync( './package-lock.json', `${buildWorkspace}/package-lock.json` )
228
239
 
229
240
  setPreviousBuild( imageVersion ) // update docker/.previous file
230
241
 
@@ -239,7 +250,35 @@ const buildContainerImage = async ( { artifactProject, artifactRegistry, contain
239
250
  ${gcloudTags}
240
251
  ` ) )
241
252
 
242
- await shellCmd( `${gcloudBuild} ${gcloudLogs} ${gcloudTags} ./docker`, { stdio : 'inherit' } )
253
+ await shellCmd( `${gcloudBuild} ${gcloudLogs} ${gcloudTags} ./build`, { stdio : 'inherit' } )
254
+ }
255
+
256
+ const repoCleanup = async () => {
257
+ // remove garbase from the repo
258
+ const garbage = [
259
+ 'build',
260
+ 'dist',
261
+ 'docker/.keep',
262
+ 'docker/.npmrc',
263
+ 'docker/.gitignore',
264
+ 'docker/Dockerfile',
265
+ 'docker/workspace',
266
+ ]
267
+ garbage.forEach( trash => fs.rmSync( trash, { recursive : true, force : true } ) )
268
+
269
+ fs.writeFileSync( 'docker/.gitignore', '.previous' )
270
+
271
+ await shellCmd( 'git add -f docker' )
272
+
273
+ log( `
274
+ ${chalk.yellow.bold( '***IMPORTANT***' )}
275
+
276
+ Please make the following .gitignore modifications:
277
+ change /dist to ${chalk.green.bold( '/build' )}
278
+ remove ${chalk.red.bold( '/docker' )}
279
+ ` )
280
+
281
+ await proceed( 'Acknowledge the .gitignore mods were made?' )
243
282
  }
244
283
 
245
284
  export default {
@@ -249,4 +288,5 @@ export default {
249
288
  formCloudBuildBucketName,
250
289
  validateCloudBuildBucket,
251
290
  buildContainerImage,
291
+ repoCleanup,
252
292
  }
package/src/Utils.mjs CHANGED
@@ -134,7 +134,11 @@ export const parsePackageJson = async ( packageFileName ) => {
134
134
  },
135
135
 
136
136
 
137
- Where <registry folder> should be an existing folder in the artifact-registry.
137
+ Where <registry folder> should be an existing folder in the artifact-registry
138
+ and must not contain the service name. Visit the link below for a list of the
139
+ existing / valid registry folders.
140
+
141
+ https://console.cloud.google.com/artifacts/browse/leverege-registry?project=leverege-registry
138
142
  `
139
143
  const registry = packageJson?.leverege?.registry
140
144
  if ( !registry ) {
@@ -248,20 +252,35 @@ Where <registry folder> should be an existing folder in the artifact-registry.
248
252
  // DEPRECATED: old reference to ./dist should be ./build
249
253
  const { build, clean, dockerize, } = packageJson.scripts
250
254
 
251
- if ( build.match( 'dist' ) || clean.match( 'dist' ) || dockerize.match( 'dockreate|cd docker' ) ) {
255
+ if ( build.match( 'dist' ) || clean.match( 'dist' ) ) {
252
256
  const deprecationError = `
253
257
 
254
- Update the npm build, clean and dockerize scripts to use ./build instead of
255
- the old ./dist directory, and docker-to-registry instead of the deprecated
256
- dockreate script - note there is no longer a need to change dir into docker
257
- in the dockerize script.
258
+ Update the npm build and clean scripts to use ./build instead of the old
259
+ ./dist directory.
258
260
  `
259
261
  const deprecationInfo = `
260
262
  "scripts": {
261
- "build": "npm run clean && mkdir ./build && cp -r ./src/* ./build",
263
+ ${chalk.green.bold( '"build": "npm run clean && mkdir ./build && cp -r ./src/* ./build",' )}
262
264
  ...
263
- "clean": "rm -fr coverage build",
264
- "dockerize": "npm run build && docker-to-registry",
265
+ ${chalk.green.bold( '"clean": "rm -fr coverage build",' )}
266
+ },
267
+ `
268
+
269
+ deprecated( { deprecationError, deprecationInfo } )
270
+ }
271
+
272
+ // DEPRECATED: old dockerize reference to docker dir and dockreate script
273
+ if ( dockerize.match( 'dockreate|cd docker' ) ) {
274
+ const deprecationError = `
275
+
276
+ Update the npm dockerize script to use docker-to-registry instead of the
277
+ deprecated dockreate script, and remove the old "cd docker" as well. The new
278
+ dockerize target is simply:
279
+ `
280
+ const deprecationInfo = `
281
+ "scripts": {
282
+ ...
283
+ ${chalk.green.bold( '"dockerize": "npm run build && docker-to-registry",' )}
265
284
  ...
266
285
  },
267
286
  `
@@ -291,13 +310,40 @@ export const analyzeRepository = async () => {
291
310
  const subPkgs = await glob( `${gitRoot}/packages/**/package.json`, { ignore : '/**/node_modules/**' } )
292
311
  const isMonoRepo = subPkgs?.length > 0
293
312
 
313
+ // Verify the presence of a root package.json file for all monorepos
294
314
  let rootPackageJson
295
315
  try {
296
316
  rootPackageJson = await parseJsonFile( `${gitRoot}/package.json` )
297
317
  } catch ( error ) {
298
- rootPackageJson = { invalid : true, error : 'invalid or non-existent root package.json file' }
318
+ rootPackageJson = { isInvalid : true, error : 'invalid or non-existent root package.json file' }
319
+ }
320
+ const isNpmWorkspace = rootPackageJson?.workspaces?.length > 0
321
+ if ( isMonoRepo && rootPackageJson.isInvalid ) {
322
+ log( chalk.red.bold( `
323
+ ***REQUIRED: A package.json file is required at the monorepo root` ) )
324
+
325
+ log( chalk.green.bold( `
326
+ A basic root package.json resembles the following:` ) )
327
+
328
+ log( chalk.yellow.bold( `
329
+ {
330
+ "name": "@leverege/<your mono name>",
331
+ "description": "A monorepo for <what is it for?>",
332
+ "scripts": {
333
+ "lint": "npm run lint --workspaces",
334
+ "prepare": "husky",
335
+ "test": "npm run test --workspaces"
336
+ },
337
+ "author": "Leverege",
338
+ "license": "SEE LICENSE IN LICENSE.md",
339
+ "devDependencies": {
340
+ "husky": "^9.0.5"
341
+ },
342
+ "workspaces": [
343
+ ]
344
+ }` ) )
345
+ process.exit( 1 )
299
346
  }
300
- const isNpmWorkspace = subPkgs?.length > 0
301
347
 
302
348
  log( chalk.green.bold( '\nParsing and analyzing the package.json file\n' ) )
303
349
  let closestPackageJson
@@ -34,7 +34,9 @@ debug( { dockerInfo }, '<==The Docker Info' )
34
34
 
35
35
  const { artifactProject, artifactRegistry, containerName } = repoDescr
36
36
 
37
- await docker.validateCloudBuildBucket( artifactProject )
37
+ if ( imageVersion === 'guide-me' ) {
38
+ await docker.validateCloudBuildBucket( artifactProject )
39
+ }
38
40
 
39
41
  const registryFolder = `${artifactRegistry}/images/${containerName}`
40
42
 
@@ -42,6 +44,51 @@ const registryFolder = `${artifactRegistry}/images/${containerName}`
42
44
  log( chalk.green.bold( 'Updating dependencies and workspace...' ) )
43
45
  await shellCmd( 'npm install', { stdio : 'inherit' } )
44
46
 
47
+ if ( imageVersion === 'guide-me' ) {
48
+ await docker.repoCleanup() // adjusts gitignore files and removes cruft
49
+ /* eslint-disable max-len */
50
+ log( `
51
+
52
+
53
+ Moving to the new artifact-registry for docker image storage may also require
54
+ helm chart changes depending on how old the current charts are. Charts that
55
+ contain helm/values.yaml files that resemble this:
56
+
57
+ ${chalk.yellow.bold( `serviceConfig:
58
+ VERSION: v1.2.3
59
+ PREEMPTIBLE: true` )}
60
+
61
+ are pre-ignition era charts and should be replaced with the latest helm chart
62
+ templates available from ignition. Either dive in or ask devops for a hand
63
+ when converting these legacy / deprecated charts.
64
+
65
+
66
+ More recently updated helm charts that have already started the migration to
67
+ the new approach may already have registry entries like this:
68
+
69
+ ${chalk.yellow.bold( `image:
70
+ registry: gcr.io/leverege-docker-images
71
+ tag: ""` )}
72
+
73
+ The above registry statement references the deprecated container registry and
74
+ must be adjusted accordingly to resemble:
75
+
76
+ ${chalk.green.bold( 'registry: us-docker.pkg.dev/leverege-registry/<registry folder>/images' )}
77
+
78
+ There may also be a corresponding modification needed in the helm template
79
+ deployment.yaml file in the container image spec:
80
+
81
+ ${chalk.green.bold( 'image: {{ .Values.image.registry }}/{{ .Chart.Name }}:{{ default .Chart.AppVersion .Values.image.tag }}' )}
82
+
83
+
84
+ ${chalk.magenta.bold( `Upgrading all service charts to the latest ignition template chart structure
85
+ is the preferred approach to making the transition to the artifact registry.` )}
86
+
87
+ ` )
88
+ log( chalk.green.bold( '*** docker-to-registry guidance complete - ready for dockerization ***' ) )
89
+ process.exit( 0 )
90
+ }
91
+
45
92
  // Give the summary and the user a chance to proceed or not
46
93
  log( `
47
94
  ${chalk.green.bold( 'Build Information:' )}