@leverege/build-tools 2.104.0 → 2.105.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.
@@ -8,7 +8,7 @@ showInstalling "The Prometheus Operator (kube-prometheus-stack)"
8
8
 
9
9
  # https://artifacthub.io/packages/helm/prometheus-community/kube-prometheus-stack
10
10
  OCI_CHART="oci://ghcr.io/prometheus-community/charts/kube-prometheus-stack"
11
- [ -z "$PROMETHEUS_STACK_CHART_VERSION" ] && PROMETHEUS_STACK_CHART_VERSION="85.0.2"
11
+ [ -z "$PROMETHEUS_STACK_CHART_VERSION" ] && PROMETHEUS_STACK_CHART_VERSION="85.3.3"
12
12
  helm upgrade $NS --install prometheus-stack $OCI_CHART \
13
13
  --values prom-operator/prometheus-stack.yaml \
14
14
  --version $PROMETHEUS_STACK_CHART_VERSION $HELM_WHAT
@@ -223,6 +223,8 @@ alertmanager:
223
223
  color: >-
224
224
  {{- if eq .Status "resolved" -}}
225
225
  good
226
+ {{- else if eq .CommonLabels.severity "page" -}}
227
+ danger
226
228
  {{- else if eq .CommonLabels.severity "critical" -}}
227
229
  danger
228
230
  {{- else if eq .CommonLabels.severity "warning" -}}
@@ -287,12 +289,28 @@ alertmanager:
287
289
  - name: opsgenie
288
290
  opsgenie_configs:
289
291
  - api_key: "${OPSGENIE_APIKEY}"
292
+ send_resolved: true
293
+ message: '{{ .CommonLabels.alertname }}{{ if .CommonLabels.namespace }} [{{ .CommonLabels.namespace }}]{{ end }}'
294
+ source: "${PROJECT_NAME} / ${CLUSTER_NAME}"
295
+ entity: '{{ if .CommonLabels.app }}{{ .CommonLabels.app }}{{ else }}{{ .CommonLabels.namespace }}{{ end }}'
290
296
  priority: "{{ .CommonLabels.priority }}"
291
- tags: "{{ range .Alerts }}{{ .Labels.severity }},{{ end }}"
297
+ tags: "{{ range $i, $a := .Alerts }}{{ if $i }},{{ end }}{{ $a.Labels.severity }}{{ end }}"
298
+ details:
299
+ namespace: "{{ .CommonLabels.namespace }}"
300
+ alertname: "{{ .CommonLabels.alertname }}"
301
+ app: "{{ .CommonLabels.app }}"
302
+ severity: "{{ .CommonLabels.severity }}"
303
+ cluster: "${CLUSTER_NAME}"
304
+ project: "${PROJECT_ID}"
292
305
  description: |-
293
306
  {{ range .Alerts }}
294
- *Alert:* {{ .Annotations.summary }} - `{{ .Labels.severity }}`
307
+ *Project:* ${PROJECT_NAME}
308
+ *Cluster:* ${CLUSTER_NAME}
309
+ *Alert:* {{ .Annotations.summary }} - {{ .Labels.severity }}
295
310
  *Description:* {{ .Annotations.description }}
311
+ {{- if .Annotations.runbook_url }}
312
+ *Runbook:* {{ .Annotations.runbook_url }}
313
+ {{- end }}
296
314
  *Dashboard:* {{ .Annotations.dashboard }}
297
315
  {{ end }}
298
316
 
@@ -363,3 +381,7 @@ alertmanager:
363
381
  - severity="page" # 📢 paging DevOps
364
382
  receiver: opsgenie
365
383
  continue: true # 👈 KEEP GOING to slack
384
+
385
+ - matchers:
386
+ - severity="page"
387
+ receiver: slack
@@ -3,6 +3,7 @@ apiVersion: monitoring.coreos.com/v1
3
3
  kind: PrometheusRule
4
4
  metadata:
5
5
  name: cnpg-rules
6
+ namespace: prometheus
6
7
  spec:
7
8
  groups:
8
9
  - name: CNPG
@@ -93,7 +94,7 @@ spec:
93
94
 
94
95
  - alert: PostgresqlRestarted
95
96
  expr: time() - cnpg_pg_postmaster_start_time < 60
96
- for: 0m
97
+ for: 2m
97
98
  labels:
98
99
  severity: critical
99
100
  annotations:
@@ -15,7 +15,7 @@ spec:
15
15
  expr: vector(1) # This will always be true, triggering the alert
16
16
  for: 1m # Alert if condition is true for 1 minute
17
17
  labels:
18
- severity: warning
18
+ severity: page # warning
19
19
  annotations:
20
20
  summary: "Test Alert for Slack"
21
21
  description: "This is a test alert to verify the Slack receiver configuration."
@@ -1,17 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  /*
3
- * refresh-npm-token will check the access time of the $HOME/.npmrc npm token
4
- * file and if it is older than 24 hours then it will be updated to whatever
5
- * value is currently in the NPM_DEVELOPER_SECRET on leverege-artifacts. It
6
- * will also check to see if the deprecated $HOME/.npmrc.ro file exists and
7
- * will suggest to the user to remove it. If either of the token files exist
8
- * the first 6 and last four characters of the token will be extracted and
9
- * reported via slack to allow DevOps operators to clean up old tokens in npm.
3
+ * refresh-npm-token checks the modification time of $HOME/.npmrc and if it
4
+ * is older than the configured age threshold, fetches three secrets from GCP
5
+ * Secret Manager: the raw npm token (REFRESH_NPM_TOKEN) and two rc file
6
+ * templates (REFRESH_NPM_NPMRC, REFRESH_NPM_YARNRC). The ${REFRESH_NPM_TOKEN}
7
+ * placeholder in each template is replaced with the live token and the result
8
+ * is written to ~/.npmrc and ~/.yarnrc.yml, giving DevOps full control over
9
+ * both files.
10
10
  *
11
- * For testing the Unix touch command may be used to modify the access access
12
- * time of the npmrc token or the --force switch to ignore the age of the file.
11
+ * For testing, the Unix touch command may be used to modify the modification
12
+ * time of ~/.npmrc or the --force switch may be used to ignore the age check.
13
13
  * The BUILD_TOOLS_DEBUG env variable may also be set to enable debugging and
14
- * disable the slack channel spam.
14
+ * disable the slack channel notifications.
15
15
  *
16
16
  * touch -d 2023-08-20 ~/.npmrc; BUILD_TOOLS_DEBUG=1 refresh-npm-token.mjs
17
17
  */
@@ -21,210 +21,135 @@ import fs from 'node:fs'
21
21
  import os from 'node:os'
22
22
 
23
23
  import chalk from 'chalk'
24
- import commandLineArgs from 'command-line-args'
25
- import commandLineUsage from 'command-line-usage'
24
+ import { program } from 'commander'
26
25
  import ms from 'ms'
27
- import { lt as semverLt } from 'semver'
28
- import YAML from 'js-yaml'
29
26
 
30
- import { debug, log, shellCmd, touchFile } from './Utils.mjs'
31
-
32
- const AUTH_TOKEN_REGEX = /_authToken=(.+)/
33
- const YARNRC_FILE_NAME = `${os.homedir()}/.yarnrc.yml`
34
-
35
- const refreshTokenOptions = [ // Use refreshTokenOptions to tie into the Usage statements
36
- {
37
- name : 'project',
38
- type : String,
39
- default : false,
40
- description : '{green the name of the google project containing the npmrc and slack config secrets (default leverege-registry)}',
41
- },
42
- {
43
- name : 'npmrc-age',
44
- type : String,
45
- default : '24h',
46
- description : '{green the age of the local ~/.npmrc file before a refetch is performed (default 24h)}'
47
- },
48
- {
49
- name : 'force',
50
- type : Boolean,
51
- default : false,
52
- description : '{green ignores age of the ~/.npmrc file and always fetches}',
53
- },
54
- {
55
- name : 'dry-run',
56
- type : Boolean,
57
- default : false,
58
- description : '{green performs sanity checks on the settings / environment without updating ~/.npmrc}',
59
- },
60
- {
61
- name : 'help',
62
- type : Boolean,
63
- default : false,
64
- description : '{green display this help screen}',
65
- },
66
- {
67
- name : 'update-yarnrc',
68
- type : Boolean,
69
- defaultValue : true,
70
- description : '{green updates the npmAuthToken variable of your .yarnrc.yml file (in addition to .npmrc/.npmrc.ro)}'
71
- }
72
- ]
73
-
74
- const sections = [
75
- {
76
- header : 'Leverege NPM Token Refresher',
77
- content : `{green This tool helps you retrieve an npmrc file stored in a secret within a GCP
78
- Secret Manager. It enables NPM administrators to manage a single NPM token
79
- for use by a development team. The tool checks the age of your local ~/.npmrc
80
- file, and if it exceeds the specified --npmrc-age setting, it will fetch the
81
- secret, overwriting the existing ~/.npmrc file.
82
-
83
- This tool may be invoked directly from the command line, or from scripts in
84
- the build-tools repository. For example, helmup will invoke this command for
85
- refreshing the token and to provide an audit log to slack when deployments
86
- are made.}`
87
- },
88
- { header : 'Options',
89
- optionList : refreshTokenOptions,
90
- },
91
- {
92
- header : 'Secret Manager Secrets (required)',
93
- content : [
94
- '{bold REFRESH_NPM_NPMRC} {green full npmrc file with a valid token}',
95
- `{green ;;;;
96
- ; lines that start with semi-colons are comments
97
- ; run "npm help 7 config" for documentation of the various options
98
- ;
99
- ; expires on 11/20/23
100
- //registry.npmjs.org/:_authToken=<a valid npm token goes here>
27
+ import { debug, log, shellCmd, versionChecks } from './Utils.mjs'
28
+
29
+ const MIN_NODE_VERSION = '22.0.0'
30
+ const MIN_NPM_VERSION = '11.10.0'
31
+
32
+ const NPMRC_FILE = `${os.homedir()}/.npmrc`
33
+ const YARNRC_FILE = `${os.homedir()}/.yarnrc.yml`
34
+
35
+ program
36
+ .name( 'refresh-npm-token' )
37
+ .description( chalk.green( `Fetches the current npm token and rc file templates from GCP Secret Manager
38
+ and overwrites ~/.npmrc and ~/.yarnrc.yml. DevOps controls the full content
39
+ of both rc files via the template secrets, ensuring consistent security
40
+ policies (e.g. npmMinimalAgeGate) across all developer machines.
41
+
42
+ Run automatically via helmup or directly from the command line. The tool
43
+ exits silently if the local ~/.npmrc is younger than the configured age.` ) )
44
+ .option( '--project <id>', 'GCP project containing the token and rc template secrets', process.env.REFRESH_NPM_PROJECT || 'leverege-registry' )
45
+ .option( '--npmrc-age <duration>', 'age of ~/.npmrc before a refresh is triggered (default 24h)', '24h' )
46
+ .option( '--force', 'ignore file age and always fetch' )
47
+ .option( '--beta', 'use the _BETA suffix on the rc templates for testing' )
48
+ .option( '--dry-run', 'fetch and validate secrets without overwriting local rc files' )
49
+ .option( '--no-update-yarnrc', 'skip writing the REFRESH_NPM_YARNRC template to ~/.yarnrc.yml' )
50
+ .option( '--no-version-check', 'warn on version requirements but do not exit' )
51
+ .addHelpText( 'after', `
52
+ ${chalk.bold( 'Secret Manager Secrets (required)' )}
53
+
54
+ ${chalk.bold( 'REFRESH_NPM_TOKEN' )} ${chalk.green( 'the raw npm token used to authenticate with the npm registry' )}
55
+ ${chalk.bold( 'REFRESH_NPM_NPMRC' )} ${chalk.green( 'complete ~/.npmrc template use ${REFRESH_NPM_TOKEN} as the token placeholder' )}
56
+ ${chalk.green( ` e.g.
57
+ //registry.npmjs.org/:_authToken=\${REFRESH_NPM_TOKEN}
101
58
  loglevel=error
102
59
  progress=true
103
60
 
104
61
  init.license=SEE LICENSE IN LICENSE.md
105
- init.private=true
62
+ init.private=true` )}
63
+ ${chalk.bold( 'REFRESH_NPM_YARNRC' )} ${chalk.green( 'complete ~/.yarnrc.yml template — use ${REFRESH_NPM_TOKEN} as the token placeholder' )}
64
+ ${chalk.green( ` e.g.
65
+ # Don't allow installing dependencies published less than this setting
66
+ npmMinimalAgeGate: 1d
67
+ npmAuthToken: \${REFRESH_NPM_TOKEN}` )}
106
68
 
107
- There may be times when a token is expired, lost or a new developer needs
108
- to seed their ~/.npmrc file for the first time. Help a brother out and let
109
- them know to run this command to fetch the current npmrc file:
69
+ ${chalk.bold( 'REFRESH_NPM_NPMRC_BETA' )} ${chalk.yellow( 'same as REFRESH_NPM_NPMRC, used when --beta is set' )}
70
+ ${chalk.bold( 'REFRESH_NPM_YARNRC_BETA' )} ${chalk.yellow( 'same as REFRESH_NPM_YARNRC, used when --beta is set' )}
110
71
 
111
- gcloud secrets versions access latest \\
112
- --secret=REFRESH_NPM_NPMRC \\
113
- --project=leverege-registry > ~/.npmrc
72
+ ${chalk.bold( 'REFRESH_NPM_SLACK_CONFIG' )} ${chalk.green( `resembles the following JSON struct
73
+ {
74
+ "url" : "https://hooks.slack.com/services/T....H/Bx....1/44....gLr7",
75
+ "channel" : "#some-devops-channel"
76
+ }` )}
114
77
 
115
- Note, ^^that command will need a different --project name for non-leverege
116
- developers.
117
- }`,
118
- `{bold REFRESH_NPM_SLACK_CONFIG} {green resembles the following JSON struct
119
- \\{
120
- "url" : "https://hooks.slack.com/services/T....H/Bx....1/44....gLr7",
121
- "channel" : "#some-devops-channel"
122
- \\} }`
123
- ],
124
- },
125
- { header : 'Environment Variables (optional)',
126
- content : `{bold REFRESH_NPM_PROJECT} {green may be used in lieu of --project
127
- }`,
128
- },
129
- ]
78
+ ${chalk.bold( 'Environment Variables (optional)' )}
130
79
 
131
- const args = commandLineArgs( refreshTokenOptions, { camelCase : true, partial : true } )
132
- const usage = commandLineUsage( sections )
80
+ ${chalk.bold( 'REFRESH_NPM_PROJECT' )} ${chalk.green( 'may be used in lieu of --project' )}
81
+ ` )
82
+ .parse()
133
83
 
134
- if ( args.help ) {
135
- log( usage )
136
- process.exit( 0 )
137
- }
84
+ const opts = program.opts()
85
+ const gcpProject = opts.project
138
86
 
139
- /* eslint-disable no-underscore-dangle */
140
- if ( args._unknown ) {
141
- log( usage )
142
- log( `\nUnrecognized argument [${chalk.bold.red( args._unknown )}]\n` )
143
- process.exit( 1 )
144
- }
145
- /* eslint-enable no-underscore-dangle */
146
-
147
- const gcpProject = args.project ? args.project : process.env.REFRESH_NPM_PROJECT || 'leverege-registry'
148
-
149
- if ( semverLt( process.version, '18.0.0' ) ) {
150
- log( chalk.red( '\n\n***ERROR: must be running at least node 18\n' ) )
151
- process.exit( 1 )
152
- }
87
+ await versionChecks( {
88
+ node : { min : MIN_NODE_VERSION },
89
+ npm : { min : MIN_NPM_VERSION, hint : 'required for npmMinimalAgeGate support' },
90
+ strict : opts.versionCheck,
91
+ } )
153
92
 
154
93
  // max age in seconds of the npmrc file before refresh
155
- const refreshThreshold = ms( args.npmrcAge || '24h' ) / 1000 // 1 day of seconds
94
+ const refreshThreshold = ms( opts.npmrcAge || '24h' ) / 1000
156
95
  if ( refreshThreshold < 60 ) {
157
96
  log( chalk.yellow.bold( `
158
- ***WARNING the npmrc-age of ${args.npmrcAge} results in an age threshold of ${refreshThreshold} seconds
97
+ ***WARNING the npmrc-age of ${opts.npmrcAge} results in an age threshold of ${refreshThreshold} seconds
159
98
  try using 24h for one day or 60m for an hour
160
99
  ` ) )
161
100
  }
162
101
 
163
- // used to pull the sanitized token [npm_mQZ0......Xmvp] reference from the npmrc file
164
- const fetchToken = ( filename ) => {
165
- const results = {
166
- filename,
167
- exists : false,
168
- token : 'none',
169
- lastUpdated : -1
170
- }
171
-
102
+ const getNpmrcAge = () => {
172
103
  try {
173
- if ( fs.existsSync( filename ) ) {
174
- results.exists = true
175
- const stat = fs.statSync( filename )
176
- results.lastUpdated = Math.trunc( ( Date.now() - stat.mtimeMs ) / 1000 )
177
- // grab the current token for logging a redacted version
178
- const currentNpmrc = fs.readFileSync( filename, 'utf8' )
179
- const found = currentNpmrc.match( /_authToken=(.*)\n/ )
180
- if ( found ) {
181
- results.token = `${found[1].slice( 0, 8 )}......${found[1].slice( -4 )}`
182
- }
183
- }
184
- } catch ( statErr ) {
185
- log( { statErr }, `<==fs.statSync failed on file ${filename}` )
104
+ if ( !fs.existsSync( NPMRC_FILE ) ) return Infinity
105
+ const stat = fs.statSync( NPMRC_FILE )
106
+ return Math.trunc( ( Date.now() - stat.mtimeMs ) / 1000 )
107
+ } catch {
108
+ return Infinity
186
109
  }
187
-
188
- return results
189
110
  }
190
111
 
191
- // fetch the tokens - note the RO token is deprecated and might not exist
192
- const npmrc = fetchToken( `${os.homedir()}/.npmrc` )
193
- const npmrcRo = fetchToken( `${os.homedir()}/.npmrc.ro` )
194
-
195
- debug( { npmrc, npmrcRo }, '<==Your current tokens' ) // debug
112
+ debug( { npmrcAge : getNpmrcAge(), refreshThreshold }, '<==Age check' )
196
113
 
197
114
  // skip file age check if this is a dry or forced run
198
- if ( !args.dryRun && !args.force ) {
199
- if ( npmrc.exists && npmrc.lastUpdated < refreshThreshold ) { process.exit( 0 ) }
115
+ if ( !opts.dryRun && !opts.force ) {
116
+ if ( getNpmrcAge() < refreshThreshold ) { process.exit( 0 ) }
200
117
  }
201
118
 
202
119
  const getGcpSecretCommand = ( secretName ) => {
203
120
  return `gcloud secrets versions access latest --project=${gcpProject} --secret=${secretName}`
204
121
  }
205
122
 
206
- // fetch the contents of the npmrc secret file stored on the specified project
207
- let npmrcFile
208
- let npmAuthToken
123
+ // fetch the token and both rc file templates from Secret Manager
124
+ let token
125
+ let npmrcTemplate
126
+ let yarnrcTemplate
209
127
  try {
210
- const npmTokenFetcher = getGcpSecretCommand( 'REFRESH_NPM_NPMRC' )
211
- debug( { npmTokenFetcher }, '<==Secret Fetcher' )
212
-
213
- npmrcFile = await shellCmd( npmTokenFetcher )
214
- npmAuthToken = npmrcFile.match( AUTH_TOKEN_REGEX )?.[1]
215
- debug( { npmAuthToken }, '<==npmAuthToken' )
216
- debug( { npmrcFile }, '<==shellCmd Output npmrc file' )// debug
128
+ const betaSuffix = opts.beta ? '_BETA' : ''
129
+ const tokenFetcher = getGcpSecretCommand( 'REFRESH_NPM_TOKEN' )
130
+ const npmrcFetcher = getGcpSecretCommand( `REFRESH_NPM_NPMRC${betaSuffix}` )
131
+ const yarnrcFetcher = getGcpSecretCommand( `REFRESH_NPM_YARNRC${betaSuffix}` )
132
+ debug( { tokenFetcher, npmrcFetcher, yarnrcFetcher }, '<==Secret fetchers' )
133
+
134
+ token = ( await shellCmd( tokenFetcher ) ).trim()
135
+ npmrcTemplate = await shellCmd( npmrcFetcher )
136
+ yarnrcTemplate = await shellCmd( yarnrcFetcher )
137
+ debug( { token : `${token.slice( 0, 8 )}......${token.slice( -4 )}` }, '<==Token (redacted)' )
217
138
  } catch ( err ) {
218
139
  log( chalk.yellow( `\nFailed Command => [${err.escapedCommand}]\n\n` ), chalk.red( err.stderr ) )
219
140
  process.exit( 1 )
220
141
  }
221
142
 
143
+ // substitute ${REFRESH_NPM_TOKEN} placeholder in both templates
144
+ const npmrcContent = npmrcTemplate.replaceAll( '${REFRESH_NPM_TOKEN}', () => token )
145
+ const yarnrcContent = yarnrcTemplate.replaceAll( '${REFRESH_NPM_TOKEN}', () => token )
146
+
222
147
  // fetch and parse the slack config for audits
223
148
  const slackSecretName = 'REFRESH_NPM_SLACK_CONFIG'
224
149
  let slackConfig
225
150
  try {
226
151
  const slackConfigFetcher = getGcpSecretCommand( slackSecretName )
227
- const slackSecret = await shellCmd( slackConfigFetcher )
152
+ const slackSecret = await shellCmd( slackConfigFetcher )
228
153
  slackConfig = JSON.parse( slackSecret )
229
154
  debug( { slackSecretName, slackConfig, slackConfigFetcher }, `<==shellCmd Output ${slackSecretName}` )
230
155
  } catch ( err ) {
@@ -236,29 +161,27 @@ try {
236
161
  process.exit( 1 )
237
162
  }
238
163
 
239
- // update the user's npmrc file if this isn't a dry run
164
+ // play nice and capture legacy rc file if it doesn't already exist
165
+ const captureLegacyRc = ( file ) => {
166
+ if ( fs.existsSync( file ) && !fs.existsSync( `${file}.LEGACY` ) ) {
167
+ fs.renameSync( file, `${file}.LEGACY` )
168
+ log( chalk.yellow( ` preserved ${file} as ${file}.LEGACY` ) )
169
+ }
170
+ }
171
+
172
+ // overwrite the local rc files unless this is a dry run
240
173
  try {
241
- if ( args.dryRun ) {
242
- log( chalk.yellow( '\n*** Dry Run - files will not be updated' ) )
174
+ if ( opts.dryRun ) {
175
+ log( chalk.yellow( '\n*** Dry Run - local rc files will not be updated' ) )
243
176
  } else {
244
- const { filename } = npmrc
245
- log( chalk.yellow( '\n*** Refreshing your ~/.npmrc npm token file' ) )
246
- if ( fs.existsSync( filename ) ) {
247
- fs.copyFileSync( filename, `${filename}-BAK` ) // make a backup for safety
248
- }
249
- fs.writeFileSync( filename, npmrcFile )
177
+ log( chalk.yellow( '\n*** Refreshing ~/.npmrc and ~/.yarnrc.yml' ) )
250
178
 
251
- if ( args.updateYarnrc && npmAuthToken ) {
252
- if ( !fs.existsSync( YARNRC_FILE_NAME ) ) {
253
- touchFile( YARNRC_FILE_NAME ) // create the file if it doesn't exist to avoid js-yaml errors
254
- } else {
255
- fs.copyFileSync( YARNRC_FILE_NAME, `${YARNRC_FILE_NAME}-BAK` )
256
- }
257
- const yarnRcContent = YAML.load( fs.readFileSync( YARNRC_FILE_NAME, 'utf-8' ) ) || { npmAuthToken : 'none' }
258
- debug( { yarnRcContent }, '<==yarnrc content' )
259
- yarnRcContent.npmAuthToken = npmAuthToken
179
+ captureLegacyRc( NPMRC_FILE )
180
+ fs.writeFileSync( NPMRC_FILE, npmrcContent )
260
181
 
261
- fs.writeFileSync( YARNRC_FILE_NAME, YAML.dump( yarnRcContent ) )
182
+ if ( opts.updateYarnrc ) {
183
+ captureLegacyRc( YARNRC_FILE )
184
+ fs.writeFileSync( YARNRC_FILE, yarnrcContent )
262
185
  }
263
186
  }
264
187
  } catch ( fileErr ) {
@@ -267,14 +190,15 @@ try {
267
190
  }
268
191
 
269
192
  // slack out the details to the configured channel
193
+ const redactedToken = `${token.slice( 0, 8 )}......${token.slice( -4 )}`
270
194
  const now = ( new Date() ).toLocaleString()
271
195
  const account = await shellCmd( 'gcloud config get account' )
272
196
  const slackData = {
273
- text : `--- npmrc refreshed by \`${account}\` at ${now}\n tokens RW [\`${npmrc.token}\`] RO [\`${npmrcRo.token}\`]`,
197
+ text : `--- npmrc refreshed by \`${account}\` at ${now}\n token [\`${redactedToken}\`]`,
274
198
  channel : slackConfig.channel,
275
199
  }
276
200
 
277
- if ( process.env.BUILD_TOOLS_DEBUG || args.dryRun ) {
201
+ if ( process.env.BUILD_TOOLS_DEBUG || opts.dryRun ) {
278
202
  log( { slackConfig, slackData }, '<==Slack skipped' )
279
203
  } else {
280
204
  try {
@@ -290,8 +214,3 @@ if ( process.env.BUILD_TOOLS_DEBUG || args.dryRun ) {
290
214
  log( { fetchError }, chalk.red( '\n\n***ERROR: fetch call failed\n' ) )
291
215
  }
292
216
  }
293
-
294
- if ( npmrcRo.exists ) {
295
- log( chalk.red( '\nWARNING - the need for the ~/.npmrc.ro file has been eliminated - please remove' ) )
296
- process.exit( 1 )
297
- }