@leverege/build-tools 2.59.1 → 2.60.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.59.1",
3
+ "version": "2.60.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
@@ -1,4 +1,6 @@
1
1
  import fs from 'node:fs'
2
+ import path from 'node:path'
3
+ import url from 'node:url'
2
4
 
3
5
  import chalk from 'chalk'
4
6
  import handlebars from 'handlebars'
@@ -13,6 +15,8 @@ import {
13
15
  warning
14
16
  } from './Utils.mjs'
15
17
 
18
+ const DIRNAME = path.dirname( url.fileURLToPath( import.meta.url ) )
19
+
16
20
  // TODO: change default to node 22 (jod) after 01/01/25
17
21
  const dockerfileNodeVersion = 'jod-alpine'
18
22
 
@@ -20,74 +24,6 @@ const dockerfileNodeVersion = 'jod-alpine'
20
24
  // the build-tools repository, but it just became simpler to pull the contents
21
25
  // directly into these variables and forego the file loading.
22
26
  //
23
- const dockerfileTemplate = `
24
- # Version {{regvers}} @ {{date}}
25
- #
26
- # The FROM directive sets the Base Image for subsequent instructions
27
- FROM node:{{nodeimage}} as intermediate
28
- ENV NODE_ENV production
29
- ENV NPM_CONFIG_USERCONFIG /usr/src/app/.npmrc
30
-
31
- RUN mkdir -p /usr/src/app
32
- WORKDIR /usr/src/app
33
-
34
- # Install app dependencies
35
- COPY ./workspace/ /usr/src/app/
36
- ENV GRPC_VERBOSITY ERROR
37
-
38
- # --------------------------------------------------------------
39
- # copy the ssh keys into place, npm install, and remove them
40
- # --------------------------------------------------------------
41
-
42
- # Install packages to install private repos with ssh keys
43
- COPY ./.npmrc \${NPM_CONFIG_USERCONFIG}
44
- RUN apk --no-cache add openssh-client && \
45
- apk --update add --no-cache --virtual build-dep g++ gcc libgcc \\
46
- libstdc++ linux-headers make {{apkadds}} && \
47
- npm install -g {{npmVersion}}
48
-
49
- {{preInstallPluginfile}}
50
-
51
- # Use SKIP_PREPARE to disable hook-and-release from running
52
- ENV SKIP_PREPARE=true
53
-
54
- # Do the clean install and remove the npm token and ssh keys from the image
55
- RUN npm ci --only=production --no-optional {{npmlogging}} && \
56
- rm -f \${NPM_CONFIG_USERCONFIG} /root/.ssh/*
57
-
58
- # --------------------------------------------------------------
59
- # Docker Final Stage
60
- # --------------------------------------------------------------
61
-
62
- FROM node:{{nodeimage}}
63
- ENV NPM_CONFIG_USERCONFIG /usr/src/app/.npmrc
64
-
65
- # Copy .npmrc for private registry access for access to any @leverege packages
66
- COPY ./.npmrc \${NPM_CONFIG_USERCONFIG}
67
-
68
- # Install tini for PID 1 and replace shell with bash so we can source files
69
- RUN apk update && \
70
- apk add --no-cache bash curl tini vim {{apkadds}} && \
71
- npm install -g {{npmVersion}} && \
72
- rm /bin/sh && ln -s /bin/bash /bin/sh && \
73
- mkdir -p /usr/src/app /tmp/levlog && \
74
- chown node:node /usr/src/app
75
-
76
- # Pull in the Dockerfile.plugin file here
77
- {{pluginfile}}
78
-
79
- # Eliminate the sensitive info from the final stage image
80
- RUN rm -f \${NPM_CONFIG_USERCONFIG}
81
-
82
- ENTRYPOINT [ "/sbin/tini", "--" ]
83
- WORKDIR /usr/src/app
84
-
85
- COPY --chown=node:node --from=intermediate /usr/src/app /usr/src/app
86
-
87
- USER {{runuser}}
88
- COPY ./bashrc /home/node/.bashrc
89
- CMD [ "/bin/bash", "-c", "source /home/node/.bashrc && node index.js" ]`
90
-
91
27
  const pluginTemplate = `
92
28
  # Dockerfile.plugin - optionally extend the service Docker image
93
29
  #
@@ -103,72 +39,15 @@ const pluginTemplate = `
103
39
  # footprints small, so adding packages "just because" is not considered
104
40
  # a best practice.
105
41
  `
106
-
107
- const bashrcTemplate = `#!/bin/bash
108
- #
109
- alias h=history
110
-
111
- alias ls='ls -CF --color=auto'
112
- alias ll='ls -lh'
113
- alias lla='ls -lha'
114
- alias glep='grep -l -s'
115
- alias m=less
116
- alias menv='env | sort | less'
117
-
118
- alias whatsmyip='wget -qO- ifconfig.co'
119
-
120
- alias err='wget -q -O- localhost:5111/logLevel/error'
121
- alias wrn='wget -q -O- localhost:5111/logLevel/warn'
122
- alias inf='wget -q -O- localhost:5111/logLevel/info'
123
- alias dbg='wget -q -O- localhost:5111/logLevel/debug'
124
- alias trc='wget -q -O- localhost:5111/logLevel/trace'
125
-
126
- socks()
127
- {
128
- netstat -ant | awk '{print }' | sort | uniq -c | sort -n
129
- }
130
-
131
- cmetrics()
132
- {
133
- wget -qO- localhost:5111/metrics
134
- }
135
-
136
- cmstat()
137
- {
138
- wget -qO- localhost:5111
139
- }
140
-
141
- cmclear()
142
- {
143
- # Future me - thinking this should call cmstat and pass in the endpoint as
144
- # a parameter? Well don't do it - without escaping the dollar 1 in cmstat
145
- # the port will end up being 51111, and escaping causes linting to complain
146
- # about unnecessary escaping.
147
- wget -qO- localhost:5111/status/clear
148
- }
149
-
150
- dunm() {
151
- du -sh /usr/src/app/node_modules/* | sort -sh
152
- }
153
- `
154
- const cloudBuildSteps = `
155
- steps:
156
- - name: 'gcr.io/cloud-builders/docker'
157
- args:
158
- - 'build'
159
- - '--network=cloudbuild'
160
- - '-t'
161
- - '{{imageName}}:{{imageVersion}}'
162
- - '.'
163
-
164
- images:
165
- - '{{imageName}}:{{imageVersion}}'
166
- `
42
+ const dockerfileTemplate = fs.readFileSync( path.join( DIRNAME, './templates/dockerfileTemplate.hbs' ), 'utf8' )
43
+ const bashrcTemplate = fs.readFileSync( path.join( DIRNAME, './templates/bashrcTemplate.hbs' ), 'utf8' )
44
+ const cloudBuildSteps = fs.readFileSync( path.join( DIRNAME, './templates/cloudBuildSteps.hbs' ), 'utf8' )
167
45
 
168
46
  const defaultSettings = {
169
47
  apkadds : '',
170
48
  date : getDateTimestamp(),
171
49
  nodeimage : 'jod-alpine',
50
+ imageBase : 'node:jod-alpine',
172
51
  npmlogging : process.env.VERBOSE_NPM_LOGGING ? '--ddd' : '--silent',
173
52
  npmVersion : 'npm@11',
174
53
  pluginfile : '# NO PLUGIN',
@@ -196,7 +75,7 @@ const generateDockerfile = ( options ) => {
196
75
  if ( !settings.nodeimage ) {
197
76
  settings.nodeimage = dockerfileNodeVersion
198
77
  }
199
-
78
+ settings.image = settings.imageBase || `node:${settings.nodeimage}`
200
79
  // Ensure the presence of the docker dir with plugin and bashrc - this code
201
80
  // could probably be tightened up a little.
202
81
  try {
@@ -207,7 +86,9 @@ const generateDockerfile = ( options ) => {
207
86
  }
208
87
 
209
88
  const bashrcFile = './docker/bashrc'
210
- if ( !fs.existsSync( bashrcFile ) ) {
89
+ // DISABLING exists check. With addition of Bashrc.plugin, the file needs to
90
+ // always be created or we encounter errors
91
+ if ( true ) { // !fs.existsSync( bashrcFile ) ) {
211
92
  let bf = bashrcTemplate
212
93
  const bashrcFilePlugin = './docker/Bashrc.plugin'
213
94
  if ( fs.existsSync( bashrcFilePlugin ) ) {
package/src/circleate.sh CHANGED
@@ -120,6 +120,7 @@ jobs:
120
120
  path: reports
121
121
 
122
122
  docs:
123
+ circleci_ip_ranges: true
123
124
  docker:
124
125
  - image: $CIRCLE_NODE_IMG
125
126
  steps:
@@ -339,6 +340,7 @@ jobs:
339
340
  path: reports
340
341
 
341
342
  docs:
343
+ circleci_ip_ranges: true
342
344
  docker:
343
345
  - image: $CIRCLE_NODE_IMG
344
346
  steps:
@@ -96,6 +96,8 @@ if ( semver.lt( semver.coerce( repoDescr.buildToolsVersion ), minimumBuildToolsV
96
96
 
97
97
  const dockerInfo = await docker.generateDockerfile( {
98
98
  regvers : repoDescr.packageVersion,
99
+ imageBase : repoDescr.closestPackageJson.leverege?.imageBase,
100
+ buildEnv : repoDescr.closestPackageJson.leverege?.buildEnv || 'alpine',
99
101
  nodeimage : repoDescr.closestPackageJson.leverege?.nodeimg, // left as nodeimg in package.json for backwards compat
100
102
  } )
101
103
  debug( { dockerInfo }, '<==The Docker Info' )
@@ -216,7 +218,8 @@ log( `
216
218
  NPM Workspace: ${chalk.green.bold( isNpmWorkspace )}
217
219
 
218
220
  ${chalk.green.bold( 'Docker Information:' )}
219
- NodeImage: ${chalk.green.bold( dockerInfo.nodeimage )}
221
+ NodeImage: ${chalk.green.bold( dockerInfo.imageBase || `node:${dockerInfo.nodeimage}` )}
222
+ Docker Env: ${chalk.green.bold( dockerInfo.buildEnv || 'alpine' )}
220
223
  AddedPkgs: ${chalk.green.bold( dockerInfo.apkadds )}
221
224
  Run User: ${chalk.green.bold( dockerInfo.runuser )}
222
225
  Previous: ${chalk.yellow.bold( dockerInfo.previousBuild )}
@@ -0,0 +1,46 @@
1
+ #!/bin/bash
2
+ #
3
+ alias h=history
4
+
5
+ alias ls='ls -CF --color=auto'
6
+ alias ll='ls -lh'
7
+ alias lla='ls -lha'
8
+ alias glep='grep -l -s'
9
+ alias m=less
10
+ alias menv='env | sort | less'
11
+
12
+ alias whatsmyip='wget -qO- ifconfig.co'
13
+
14
+ alias err='wget -q -O- localhost:5111/logLevel/error'
15
+ alias wrn='wget -q -O- localhost:5111/logLevel/warn'
16
+ alias inf='wget -q -O- localhost:5111/logLevel/info'
17
+ alias dbg='wget -q -O- localhost:5111/logLevel/debug'
18
+ alias trc='wget -q -O- localhost:5111/logLevel/trace'
19
+
20
+ socks()
21
+ {
22
+ netstat -ant | awk '{print }' | sort | uniq -c | sort -n
23
+ }
24
+
25
+ cmetrics()
26
+ {
27
+ wget -qO- localhost:5111/metrics
28
+ }
29
+
30
+ cmstat()
31
+ {
32
+ wget -qO- localhost:5111
33
+ }
34
+
35
+ cmclear()
36
+ {
37
+ # Future me - thinking this should call cmstat and pass in the endpoint as
38
+ # a parameter? Well don't do it - without escaping the dollar 1 in cmstat
39
+ # the port will end up being 51111, and escaping causes linting to complain
40
+ # about unnecessary escaping.
41
+ wget -qO- localhost:5111/status/clear
42
+ }
43
+
44
+ dunm() {
45
+ du -sh /usr/src/app/node_modules/* | sort -sh
46
+ }
@@ -0,0 +1,13 @@
1
+ steps:
2
+ - name: 'gcr.io/cloud-builders/docker'
3
+ args:
4
+ - 'build'
5
+ - '--network=cloudbuild'
6
+ - '-t'
7
+ - '{{imageName}}:{{imageVersion}}'
8
+ - '--cache-from'
9
+ - '{{imageName}}:{{imageVersion}}'
10
+ - '.'
11
+
12
+ images:
13
+ - '{{imageName}}:{{imageVersion}}'
@@ -0,0 +1,86 @@
1
+ # Version {{regvers}} @ {{date}}
2
+
3
+ # The FROM directive sets the Base Image for subsequent instructions
4
+ FROM {{image}} as intermediate
5
+
6
+ ARG BUILD_ENV="{{buildEnv}}"
7
+
8
+ ENV NODE_ENV production
9
+ ENV NPM_CONFIG_USERCONFIG /usr/src/app/.npmrc
10
+
11
+ RUN mkdir -p /usr/src/app
12
+ WORKDIR /usr/src/app
13
+
14
+ # Install app dependencies
15
+ COPY ./workspace/ /usr/src/app/
16
+ ENV GRPC_VERBOSITY ERROR
17
+
18
+ # --------------------------------------------------------------
19
+ # copy the ssh keys into place, npm install, and remove them
20
+ # --------------------------------------------------------------
21
+
22
+ # Install packages to install private repos with ssh keys
23
+ COPY ./.npmrc ${NPM_CONFIG_USERCONFIG}
24
+
25
+ RUN if [ "${BUILD_ENV}" = "debian" ]; then \
26
+ apt-get update && \
27
+ apt-get install -y wget openssh-client build-essential && \
28
+ npm install -g npm@10; \
29
+ else \
30
+ apk --no-cache add openssh-client && \
31
+ apk --update add --no-cache --virtual build-dep g++ gcc libgcc libstdc++ linux-headers make {{apkadds}} && \
32
+ npm install -g npm@10; \
33
+ fi
34
+
35
+ # Use SKIP_PREPARE to disable hook-and-release from running
36
+ ENV SKIP_PREPARE=true
37
+
38
+ {{preInstallPluginfile}}
39
+
40
+ # Do the clean install and remove the npm token and ssh keys from the image
41
+ RUN npm ci --only=production --no-optional {{npmlogging}} && \
42
+ rm -f ${NPM_CONFIG_USERCONFIG} /root/.ssh/*
43
+
44
+ # --------------------------------------------------------------
45
+ # Docker Final Stage
46
+ # --------------------------------------------------------------
47
+
48
+ FROM {{image}}
49
+
50
+ ARG BUILD_ENV="{{buildEnv}}"
51
+
52
+ ENV NPM_CONFIG_USERCONFIG /usr/src/app/.npmrc
53
+
54
+ # Copy .npmrc for private registry access for access to any @leverege packages
55
+ COPY ./.npmrc ${NPM_CONFIG_USERCONFIG}
56
+
57
+ # Install tini for PID 1 and replace shell with bash so we can source files
58
+ RUN if [ "$BUILD_ENV" = "debian" ]; then \
59
+ apt-get update && \
60
+ apt-get install -y tini bash curl vim {{apkadds}} && \
61
+ npm install -g npm@10 && \
62
+ rm /bin/sh && ln -s /bin/bash /bin/sh && \
63
+ mkdir -p /usr/src/app /tmp/levlog && chown node:node /usr/src/app; \
64
+ else \
65
+ apk update && \
66
+ apk add --no-cache bash curl tini vim {{apkadds}} && \
67
+ npm install -g npm@10 && \
68
+ rm /bin/sh && ln -s /bin/bash /bin/sh && \
69
+ mkdir -p /usr/src/app /tmp/levlog && chown node:node /usr/src/app; \
70
+ fi
71
+
72
+
73
+ # Pull in the Dockerfile.plugin file here
74
+ {{pluginfile}}
75
+
76
+ # Eliminate the sensitive info from the final stage image
77
+ RUN rm -f ${NPM_CONFIG_USERCONFIG}
78
+
79
+ ENTRYPOINT [ "tini", "--" ]
80
+ WORKDIR /usr/src/app
81
+
82
+ COPY --chown=node:node --from=intermediate /usr/src/app /usr/src/app
83
+
84
+ USER {{runuser}}
85
+ COPY ./bashrc /home/node/.bashrc
86
+ CMD [ "/bin/bash", "-c", "source /home/node/.bashrc && node index.js" ]
@@ -1,167 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // A simple utility for easily building CNPG based psql images. The resultant
4
- // image will contain PostgreSQL, the JS query and Timescale extensions, and
5
- // the extensions that are required by CNPG like barman, pgaudit, pgvector and
6
- // pg-failover-slots.
7
- //
8
- // Latest Versions:
9
- // postgres => https://www.postgresql.org/
10
- // timescale => https://docs.timescale.com/about/latest/
11
- // CNPG images => https://github.com/cloudnative-pg/postgres-containers/pkgs/container/postgresql
12
-
13
- import fs from 'node:fs'
14
- import path from 'node:path'
15
-
16
- import chalk from 'chalk'
17
- import cliArgs from 'command-line-args'
18
- import cliHelp from 'command-line-usage'
19
- import Handlebars from 'handlebars'
20
-
21
- import {
22
- debug,
23
- log,
24
- err,
25
- errorExit,
26
- shellCmd,
27
- } from './Utils.mjs'
28
-
29
- // Define CLI options
30
- const optionList = [
31
- { name : 'sub-tag', type : String, description : '{green sub-tag to add to the image tag (required)}', defaultOption : true },
32
- { name : 'pg-version', type : String, description : '{green pgsql version (default: 16.6)}' },
33
- { name : 'version', type : Boolean, description : '{green show script version}' },
34
- { name : 'help', type : Boolean, description : '{green display this help screen}' },
35
- ]
36
-
37
- const sections = [
38
- {
39
- header : 'Leverege CNPG Docker Image Builder',
40
- content : `{green This tool will build a PostgreSQL based image that is suitable for
41
- deployment by the CNPG operator. It builds the docker image by using an
42
- official CNPG docker image as a base and added the jsquery and timescale
43
- extensions for use within a Leverege k8s cluster. The resultant image may be
44
- used in the standard PostgreSQL configuration which is used by the stack
45
- components, as well as timescale based services like transponder tsdb and
46
- dense history.}`
47
- },
48
- {
49
- header : 'Options',
50
- optionList
51
- },
52
- {
53
- header : 'Leverege Registry Image Tag',
54
- content : `{green The full registry image tag that is used for tagging the docker image in the artifact registry}`,
55
- },
56
- ]
57
- const args = cliArgs( optionList, { partial : true } )
58
- const help = cliHelp( sections )
59
-
60
- debug( { args, help }, '<==Command Line Info?' )
61
-
62
- // Show help if needed
63
- if ( args.help ) {
64
- console.log( help )
65
- process.exit( 0 )
66
- }
67
-
68
- // Define defaults
69
- const PG_VERSION = args.pgVersion || '16.4'
70
- const { subTag } = args
71
- if ( !subTag ) {
72
- errorExit( `Error: An image version must be specified.` )
73
- }
74
-
75
- const LEVEREGE_REGISTRY = 'us-docker.pkg.dev/leverege-registry/system/images/leverege-pgsql'
76
- const LEVEREGE_IMAGE_TAG = `${PG_VERSION}-cnpg-lvrg-${subTag}`
77
- const LEVEREGE_IMAGE_NAME_WITH_TAG = `${LEVEREGE_REGISTRY}:${LEVEREGE_IMAGE_TAG}`
78
-
79
- const DOCKERFILE_TEMPLATE = `
80
- FROM ghcr.io/cloudnative-pg/postgresql:{{PG_VERSION}}-bookworm
81
-
82
- USER root
83
-
84
- RUN set -xe; \\
85
- apt-get update; \\
86
- apt-get install -y --no-install-recommends \\
87
- "postgresql-\${PG_MAJOR}-jsquery"; \\
88
- rm -fr /tmp/*; \\
89
- rm -rf /var/lib/apt/lists/*;
90
-
91
- RUN apt-get update \\
92
- && apt-get install -y lsb-release wget \\
93
- && echo "deb https://packagecloud.io/timescale/timescaledb/debian/ \$(lsb_release -c -s) main" | tee /etc/apt/sources.list.d/timescaledb.list \\
94
- && wget --quiet -O - https://packagecloud.io/timescale/timescaledb/gpgkey | apt-key add - \\
95
- && apt-get update \\
96
- && apt-get install -y "timescaledb-2-postgresql-\${PG_MAJOR}" \\
97
- && apt-get remove -y lsb-release wget \\
98
- && rm -fr /tmp/* \\
99
- && rm -rf /var/lib/apt/lists/*;
100
-
101
- RUN usermod -u 26 postgres
102
- USER 26
103
- `
104
-
105
- // Check for existing image
106
- const checkExistingImage = async ( imageName ) => {
107
- const dockerResults= await shellCmd( `docker image list ${imageName} --quiet` )
108
- debug( { imageName, dockerResults }, '<==docker image list' )
109
- return dockerResults !== ''
110
- }
111
-
112
- // Build and push Docker image
113
- const buildAndPushImage = async () => {
114
- const template = Handlebars.compile( DOCKERFILE_TEMPLATE )
115
- const renderedDockerfile = template( { PG_VERSION } )
116
- debug( { renderedDockerfile }, '<==Dockerfile' )
117
-
118
- // Write the Dockerfile to a temporary location
119
- const dockerfilePath = path.resolve( 'Dockerfile.temp' )
120
- fs.writeFileSync( dockerfilePath, renderedDockerfile )
121
-
122
- // Build the image
123
- console.log( chalk.yellow( 'Building Docker image...' ) )
124
- await shellCmd( `docker build --file ${dockerfilePath} --tag ${LEVEREGE_IMAGE_NAME_WITH_TAG} .` )
125
-
126
- // Push the image
127
- console.log( chalk.green( 'Pushing Docker image...' ) )
128
- await shellCmd( `docker push ${LEVEREGE_IMAGE_NAME_WITH_TAG}` )
129
-
130
- // Clean up the temporary Dockerfile
131
- fs.unlinkSync( dockerfilePath )
132
- }
133
-
134
- // Main execution flow
135
- try {
136
- if ( await checkExistingImage( LEVEREGE_IMAGE_NAME_WITH_TAG ) ) {
137
- console.error(
138
- `${chalk.red( '*** ERROR ***' )
139
- } The image already exists:\n` +
140
- ` Image : ${chalk.yellow( LEVEREGE_IMAGE_NAME_WITH_TAG )}\n` +
141
- ` Registry: ${chalk.green( LEVEREGE_REGISTRY )}\n` +
142
- ` Tag : ${chalk.green( LEVEREGE_IMAGE_TAG )}\n`
143
- )
144
- process.exit( 1 )
145
- }
146
-
147
- console.log( `${chalk.cyan( 'About to build a new Docker image:\n' )
148
- } PostgreSQL => ${chalk.green( PG_VERSION )}\n` +
149
- ` Image Name => ${chalk.green( LEVEREGE_IMAGE_NAME_WITH_TAG )}\n` )
150
-
151
- console.log( `Enter "${chalk.green( 'yes' )}" to proceed or anything else to exit.` )
152
- const confirmation = await new Promise( ( resolve ) => {
153
- process.stdin.once( 'data', data => resolve( data.toString().trim() ) )
154
- } )
155
-
156
- if ( confirmation !== 'yes' ) {
157
- console.log( chalk.red( 'Aborted by user.' ) )
158
- process.exit( 1 )
159
- }
160
-
161
- await buildAndPushImage()
162
- console.log( chalk.green( 'Docker image build and push completed successfully!' ) )
163
- process.exit( 0 )
164
- } catch ( error ) {
165
- console.error( chalk.red( 'An error occurred:' ), error.message )
166
- process.exit( 1 )
167
- }