@leverege/build-tools 2.59.0 → 2.59.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
CHANGED
|
@@ -0,0 +1,167 @@
|
|
|
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
|
+
}
|
|
@@ -4,7 +4,7 @@ showInstalling "Redis"
|
|
|
4
4
|
|
|
5
5
|
OCI_CHART="oci://registry-1.docker.io/bitnamicharts/redis"
|
|
6
6
|
|
|
7
|
-
[ -z "$REDIS_CHART_VERSION" ] && REDIS_CHART_VERSION="20.6.
|
|
7
|
+
[ -z "$REDIS_CHART_VERSION" ] && REDIS_CHART_VERSION="20.6.1"
|
|
8
8
|
|
|
9
9
|
helm upgrade --install redis $OCI_CHART \
|
|
10
10
|
--values redis/redis-local.yaml \
|
|
@@ -129,6 +129,10 @@ serviceAccount:
|
|
|
129
129
|
create: false
|
|
130
130
|
name: velero
|
|
131
131
|
|
|
132
|
+
metrics:
|
|
133
|
+
serviceMonitor:
|
|
134
|
+
enabled: true
|
|
135
|
+
|
|
132
136
|
# Workload Identity Federation (WIF) uses service accounts and IAM roles to
|
|
133
137
|
# define a service's permissions - the useSecret setting will be set to false
|
|
134
138
|
# for WIF enabled clusters.
|
package/src/k8cryo.sh
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
#
|
|
3
|
-
. `build-tools --bashfun`
|
|
4
|
-
|
|
5
|
-
daysToKeep=${1:-60}
|
|
6
|
-
let hoursToKeep="$daysToKeep*24"
|
|
7
|
-
printf "\ncryo backup set to keep for $daysToKeep days / $hoursToKeep hours\n"
|
|
8
|
-
|
|
9
|
-
if [ "`basename $0`" == "k8thaw" ];
|
|
10
|
-
then
|
|
11
|
-
errorExit "k8thaw - UNDER CONSTRUCTION"
|
|
12
|
-
fi
|
|
13
|
-
|
|
14
|
-
# Gets the UTC time in the same format that velero schedules use for
|
|
15
|
-
# generating the Date Time Stamp for scheduled backups.
|
|
16
|
-
DTS="`date -u +\"%Y%m%d%H%M%S\"`"
|
|
17
|
-
|
|
18
|
-
printf "\nExecuting = > velero backup create velero-cryo-$DTS --ttl ${hoursToKeep}h\n"
|
|
19
|
-
|
|
20
|
-
velero backup create velero-cryo-$DTS --ttl ${hoursToKeep}h
|
package/src/tag-release.mjs
DELETED
|
@@ -1,692 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/* eslint-disable security/detect-unsafe-regex */
|
|
3
|
-
/* eslint-disable no-console */
|
|
4
|
-
|
|
5
|
-
import path from 'node:path'
|
|
6
|
-
|
|
7
|
-
import cliArgs from 'command-line-args'
|
|
8
|
-
import cliHelp from 'command-line-usage'
|
|
9
|
-
import { $, fs } from 'zx'
|
|
10
|
-
import pkg from 'enquirer'
|
|
11
|
-
import colors from 'ansi-colors'
|
|
12
|
-
import { readPackage } from 'read-pkg'
|
|
13
|
-
|
|
14
|
-
const { prompt } = pkg
|
|
15
|
-
|
|
16
|
-
const NPMJS_TAGS = {
|
|
17
|
-
ALPHA : 'alpha',
|
|
18
|
-
BETA : 'beta',
|
|
19
|
-
LATEST : 'latest',
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const DEFAULT_PACKAGES_PATH = './packages/*'
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Functions
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
const validateVersionArg = ( { args } ) => {
|
|
29
|
-
if ( !args.version ) {
|
|
30
|
-
return
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const isValid = /^\d+\.\d+\.\d+(-[a-zA-Z]+\.\d+)?$/.test( args.version )
|
|
34
|
-
if ( !isValid ) {
|
|
35
|
-
console.log( `
|
|
36
|
-
${colors.bold.red( 'ERROR:' )} Invalid version arg: ${colors.bold.yellow( args.version )}.
|
|
37
|
-
Use SemVer specs (e.g: ${colors.bold.yellow( '2.25.5-beta.1' )}).
|
|
38
|
-
` )
|
|
39
|
-
process.exit( 1 )
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const validateNpmjsTag = ( { args, config } ) => {
|
|
44
|
-
const npmjsTags = Object.values( NPMJS_TAGS )
|
|
45
|
-
if ( args['npmjs-tag'] && !npmjsTags.includes( args['npmjs-tag'] ) ) {
|
|
46
|
-
console.log( `
|
|
47
|
-
${colors.bold.red( 'ERROR:' )} Invalid npmjs tag: ${colors.bold.yellow( args['npmjs-tag'] )}.
|
|
48
|
-
Possible values: ${colors.bold.yellow( npmjsTags.join( ', ' ) )}.
|
|
49
|
-
` )
|
|
50
|
-
process.exit( 1 )
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (
|
|
54
|
-
( config?.isBetaRelease === true || args?.version?.includes( '-beta.' ) ) &&
|
|
55
|
-
args['npmjs-tag'] === NPMJS_TAGS.LATEST
|
|
56
|
-
) {
|
|
57
|
-
console.log( `
|
|
58
|
-
${colors.bold.red( 'ERROR:' )} It's not possible to publish a beta release to npmjs with tag ${colors.bold.yellow( 'latest' )}.
|
|
59
|
-
` )
|
|
60
|
-
process.exit( 1 )
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const validateArgs = ( args ) => {
|
|
65
|
-
validateVersionArg( { args } )
|
|
66
|
-
validateNpmjsTag( { args } )
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const getCurrentBranch = async () => {
|
|
70
|
-
const { stdout } =
|
|
71
|
-
await $`git branch --show-current`
|
|
72
|
-
.nothrow()
|
|
73
|
-
.quiet()
|
|
74
|
-
|
|
75
|
-
return stdout.split( '\n' )[0]
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const getLatestBranches = async ( { n = 10, branchFilter } ) => {
|
|
79
|
-
const grepFilter = branchFilter || ''
|
|
80
|
-
|
|
81
|
-
const { stdout } =
|
|
82
|
-
await $`git branch -r --sort=-committerdate --format "%(refname:lstrip=3)" | grep "${grepFilter}"`
|
|
83
|
-
.nothrow()
|
|
84
|
-
.quiet()
|
|
85
|
-
|
|
86
|
-
const branches = stdout.split( '\n' ).slice( 0, -1 ).filter( branch => branch !== 'HEAD' )
|
|
87
|
-
return branches.slice( 0, n )
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const promptForBranch = async ( latestBranches, currentBranch ) => {
|
|
91
|
-
if ( latestBranches.length === 0 ) {
|
|
92
|
-
console.log( `
|
|
93
|
-
${colors.bold.red( 'ERROR:' )} Could not find git branches.
|
|
94
|
-
` )
|
|
95
|
-
process.exit( 1 )
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const { branch } = await prompt( {
|
|
99
|
-
type : 'select',
|
|
100
|
-
name : 'branch',
|
|
101
|
-
message : 'Which branch would you like to release?',
|
|
102
|
-
choices : latestBranches.map( option => ( { value : option } ) ),
|
|
103
|
-
initial : currentBranch
|
|
104
|
-
} )
|
|
105
|
-
return branch
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const getBranch = async ( branchFilter ) => {
|
|
109
|
-
const currentBranch = await getCurrentBranch()
|
|
110
|
-
const latestBranches = await getLatestBranches( branchFilter )
|
|
111
|
-
return promptForBranch( latestBranches, currentBranch )
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const getGitRootDirectory = async () => {
|
|
115
|
-
const { stdout } = await $`git rev-parse --show-toplevel`.quiet()
|
|
116
|
-
return stdout.split( '\n' )[0]
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const getSubDirectories = async ( repositoryRoot, directory ) => {
|
|
120
|
-
const absolutePathDirectory = path.join( repositoryRoot, directory )
|
|
121
|
-
const relativeDirectory = path.relative( repositoryRoot, absolutePathDirectory )
|
|
122
|
-
try {
|
|
123
|
-
const entries = await fs.promises.readdir( absolutePathDirectory, { withFileTypes : true } )
|
|
124
|
-
const subDirectories = entries.filter( entry => entry.isDirectory() )
|
|
125
|
-
return subDirectories.map( entry => path.join( relativeDirectory, entry.name ) )
|
|
126
|
-
} catch ( err ) {
|
|
127
|
-
return []
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const fileExists = async ( filePath ) => {
|
|
132
|
-
try {
|
|
133
|
-
await fs.promises.access( filePath )
|
|
134
|
-
return true
|
|
135
|
-
} catch ( err ) {
|
|
136
|
-
return false
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const findPackagesInDirectories = async ( repositoryRoot, directories ) => {
|
|
141
|
-
return directories.reduce( async ( accPromise, directory ) => {
|
|
142
|
-
const acc = await accPromise
|
|
143
|
-
const hasWildcard = directory.endsWith( '*' )
|
|
144
|
-
const basePath = hasWildcard ? directory.slice( 0, -1 ) : directory
|
|
145
|
-
const directoriesToSearch = hasWildcard ?
|
|
146
|
-
await getSubDirectories( repositoryRoot, basePath ) :
|
|
147
|
-
[ basePath ]
|
|
148
|
-
|
|
149
|
-
for ( let i = 0; i < directoriesToSearch.length; i++ ) {
|
|
150
|
-
const currentDirectory = directoriesToSearch[i]
|
|
151
|
-
const pkgPath = path.join( directoriesToSearch[i], 'package.json' )
|
|
152
|
-
const pkgExists = await fileExists( path.join( repositoryRoot, pkgPath ) ) // eslint-disable-line no-await-in-loop
|
|
153
|
-
if ( pkgExists ) {
|
|
154
|
-
acc.push( currentDirectory )
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
return acc
|
|
158
|
-
|
|
159
|
-
}, Promise.resolve( [] ) )
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const getMonorepoPackagePaths = async ( repositoryRoot, packagesPath ) => {
|
|
163
|
-
let pkg
|
|
164
|
-
try {
|
|
165
|
-
pkg = await readPackage( { cwd : repositoryRoot } )
|
|
166
|
-
} catch ( err ) {}
|
|
167
|
-
|
|
168
|
-
return findPackagesInDirectories( repositoryRoot, pkg?.workspaces || [ packagesPath ] )
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const selectPackageToUpdate = async ( repositoryRoot, packagePaths ) => {
|
|
172
|
-
const currentPath = process.cwd()
|
|
173
|
-
const currentPackageRelativePath = path.relative( repositoryRoot, currentPath )
|
|
174
|
-
|
|
175
|
-
const { packageName } = await prompt( {
|
|
176
|
-
type : 'select',
|
|
177
|
-
name : 'packageName',
|
|
178
|
-
message : 'What package are you releasing?',
|
|
179
|
-
choices : packagePaths,
|
|
180
|
-
initial : currentPackageRelativePath
|
|
181
|
-
} )
|
|
182
|
-
|
|
183
|
-
return path.join( repositoryRoot, packageName )
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const getPackagePath = async ( { repositoryRoot, packagesPath = DEFAULT_PACKAGES_PATH } ) => {
|
|
187
|
-
const packagePaths = await getMonorepoPackagePaths( repositoryRoot, packagesPath )
|
|
188
|
-
if ( packagePaths.length > 0 ) {
|
|
189
|
-
return selectPackageToUpdate( repositoryRoot, packagePaths )
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return repositoryRoot
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
const checkoutToBranch = async ( { branch } ) => {
|
|
196
|
-
try {
|
|
197
|
-
await $`git checkout ${branch}`
|
|
198
|
-
} catch ( err ) {
|
|
199
|
-
console.log( err.stderr || err )
|
|
200
|
-
process.exit( 1 )
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const getPackageJsonVersion = async ( packagePath ) => {
|
|
205
|
-
if ( !packagePath ) {
|
|
206
|
-
console.log( `
|
|
207
|
-
${colors.bold.red( 'ERROR:' )} Could not find a package.json file.
|
|
208
|
-
The tag-release script must run from a npm project.
|
|
209
|
-
` )
|
|
210
|
-
return process.exit( 1 )
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const packageJson = await readPackage( { cwd : packagePath } )
|
|
214
|
-
return packageJson.version
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const getNextVersions = ( currentVersion ) => {
|
|
218
|
-
const regex = /^(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-(\w+)\.(\d+))?$/i
|
|
219
|
-
const [ , dirtyMajor, dirtyMinor, dirtyPatch, testTag, dirtyTestVersion ] = currentVersion.match( regex )
|
|
220
|
-
const major = parseInt( dirtyMajor )
|
|
221
|
-
const minor = parseInt( dirtyMinor ) || 0
|
|
222
|
-
const patch = parseInt( dirtyPatch ) || 0
|
|
223
|
-
const testVersion = parseInt( dirtyTestVersion ) || 0
|
|
224
|
-
|
|
225
|
-
const nextMajor = `${major + 1}.0.0`
|
|
226
|
-
const nextMinor = `${major}.${minor + 1}.0`
|
|
227
|
-
const nextPatch = `${major}.${minor}.${patch + 1}`
|
|
228
|
-
|
|
229
|
-
const nextAlpha = testTag === 'alpha' ?
|
|
230
|
-
`${major}.${minor}.${patch}-alpha.${testVersion + 1}` :
|
|
231
|
-
`${major}.${minor}.${patch + 1}-alpha.1`
|
|
232
|
-
|
|
233
|
-
const nextBeta = testTag === 'beta' ?
|
|
234
|
-
`${major}.${minor}.${patch}-beta.${testVersion + 1}` :
|
|
235
|
-
`${major}.${minor}.${patch + 1}-beta.1`
|
|
236
|
-
|
|
237
|
-
const nextTestTag = testTag && ![ 'alpha', 'beta' ].includes( testTag ) ?
|
|
238
|
-
`${major}.${minor}.${patch}-${testTag}.${testVersion + 1}` :
|
|
239
|
-
null
|
|
240
|
-
|
|
241
|
-
return {
|
|
242
|
-
nextMajor,
|
|
243
|
-
nextMinor,
|
|
244
|
-
nextPatch,
|
|
245
|
-
nextAlpha,
|
|
246
|
-
nextBeta,
|
|
247
|
-
nextTestTag,
|
|
248
|
-
testTag,
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
const promptForVersion = async ( currentVersion ) => {
|
|
253
|
-
const {
|
|
254
|
-
nextMajor,
|
|
255
|
-
nextMinor,
|
|
256
|
-
nextPatch,
|
|
257
|
-
nextAlpha,
|
|
258
|
-
nextBeta,
|
|
259
|
-
nextTestTag,
|
|
260
|
-
testTag
|
|
261
|
-
} = getNextVersions( currentVersion )
|
|
262
|
-
|
|
263
|
-
const choices = [
|
|
264
|
-
{ hint : '(major release)', value : nextMajor },
|
|
265
|
-
{ hint : '(minor release)', value : nextMinor },
|
|
266
|
-
{ hint : '(patch release)', value : nextPatch },
|
|
267
|
-
{ hint : '(alpha release)', value : nextAlpha },
|
|
268
|
-
{ hint : '(beta release)', value : nextBeta },
|
|
269
|
-
...( nextTestTag ? [ { hint : `(${testTag} release)`, value : nextTestTag } ] : [] ),
|
|
270
|
-
{ hint : '(current version)', value : currentVersion },
|
|
271
|
-
{ value : 'custom' },
|
|
272
|
-
]
|
|
273
|
-
const { version } = await prompt( {
|
|
274
|
-
type : 'select',
|
|
275
|
-
name : 'version',
|
|
276
|
-
message : `What version are you releasing (current version is ${currentVersion})?`,
|
|
277
|
-
choices,
|
|
278
|
-
} )
|
|
279
|
-
|
|
280
|
-
if ( version === 'custom' ) {
|
|
281
|
-
const { customVersion } = await prompt( {
|
|
282
|
-
type : 'input',
|
|
283
|
-
name : 'customVersion',
|
|
284
|
-
message : `What custom version are you releasing (current version is ${currentVersion})?`,
|
|
285
|
-
initial : currentVersion
|
|
286
|
-
} )
|
|
287
|
-
return customVersion
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
return version
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
const getVersion = async ( { branch, packagePath } ) => {
|
|
294
|
-
const currentVersion = await getPackageJsonVersion( packagePath )
|
|
295
|
-
return promptForVersion( currentVersion )
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
const getPackageName = async ( { packagePath } ) => {
|
|
299
|
-
const noTrailingSlashPath = packagePath.slice( -1 ) === '/' ?
|
|
300
|
-
packagePath.substr( 0, packagePath.length - 1 ) :
|
|
301
|
-
packagePath
|
|
302
|
-
return noTrailingSlashPath.split( '/' ).slice( -1 )[0]
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
const getBuildMessage = ( { isPackageInRepositoryRoot, packageName, version } ) => {
|
|
306
|
-
if ( isPackageInRepositoryRoot ) {
|
|
307
|
-
return `BUILD v${version}`
|
|
308
|
-
}
|
|
309
|
-
return `BUILD ${packageName}/v${version}`
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
const getGitTagSuffix = async () => {
|
|
313
|
-
const { tagSuffix } = await prompt( {
|
|
314
|
-
type : 'input',
|
|
315
|
-
name : 'tagSuffix',
|
|
316
|
-
message : 'What suffix you like to add to the tag name for git? (e.g: "-RC.1" for v1.2.3-RC.1)',
|
|
317
|
-
} )
|
|
318
|
-
return tagSuffix
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
const getGitAnnotationMessage = async ( { tagName } ) => {
|
|
322
|
-
const { annotationMessage } = await prompt( {
|
|
323
|
-
type : 'input',
|
|
324
|
-
name : 'annotationMessage',
|
|
325
|
-
message : 'What annotation message would you like to add to git tag?',
|
|
326
|
-
initial : tagName
|
|
327
|
-
} )
|
|
328
|
-
return annotationMessage
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
const confirmPushCommit = async ( buildMessage ) => {
|
|
332
|
-
const { confirm } = await prompt( [ {
|
|
333
|
-
type : 'confirm',
|
|
334
|
-
name : 'confirm',
|
|
335
|
-
message : `${colors.bold.red( '[Warning]' )} Commit and push ${colors.bold.yellow( buildMessage )} to git remote?`
|
|
336
|
-
} ] )
|
|
337
|
-
return confirm
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
const isPackageInRepositoryRoot = async ( { repositoryRoot, packagePath } ) => {
|
|
341
|
-
return repositoryRoot === packagePath
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
const promptForNpmjsTag = async ( { isBetaRelease } ) => {
|
|
345
|
-
const choices = Object.values( NPMJS_TAGS ).map( option => ( {
|
|
346
|
-
value : option,
|
|
347
|
-
...( ( isBetaRelease && option === NPMJS_TAGS.LATEST ) && { disabled : '(not available for beta releases)' } )
|
|
348
|
-
} ) )
|
|
349
|
-
const { npmjsTag } = await prompt( {
|
|
350
|
-
type : 'select',
|
|
351
|
-
name : 'npmjsTag',
|
|
352
|
-
message : 'Which npmjs tag would you like to use when publishing?',
|
|
353
|
-
choices,
|
|
354
|
-
initial : isBetaRelease ? NPMJS_TAGS.BETA : NPMJS_TAGS.LATEST,
|
|
355
|
-
} )
|
|
356
|
-
return npmjsTag
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
const confirmTagRelease = async ( { isBetaRelease, publishable } ) => {
|
|
360
|
-
const message = [
|
|
361
|
-
'Releasing will commit',
|
|
362
|
-
isBetaRelease ? ' and push' : ', push, and tag',
|
|
363
|
-
' the version in git',
|
|
364
|
-
publishable ? ' and npm' : '',
|
|
365
|
-
'. Proceed?'
|
|
366
|
-
].join( '' )
|
|
367
|
-
|
|
368
|
-
const { confirmResponse } = await prompt( {
|
|
369
|
-
type : 'select',
|
|
370
|
-
name : 'confirmResponse',
|
|
371
|
-
message,
|
|
372
|
-
choices : [ 'yes', 'no', 'advanced' ],
|
|
373
|
-
initial : 'yes',
|
|
374
|
-
} )
|
|
375
|
-
|
|
376
|
-
if ( confirmResponse === 'no' ) {
|
|
377
|
-
console.log( 'Aborting...' )
|
|
378
|
-
process.exit()
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
return confirmResponse
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
const isWorkspacePackage = async () => {
|
|
385
|
-
const gitRootDirectory = await getGitRootDirectory()
|
|
386
|
-
try {
|
|
387
|
-
const packageJson = await readPackage( { cwd : gitRootDirectory } )
|
|
388
|
-
return packageJson?.workspaces?.length > 0
|
|
389
|
-
} catch ( err ) {
|
|
390
|
-
return false
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
const updateNpmPackageJsonAndLock = async ( config ) => {
|
|
395
|
-
const { version, packagePath, isPackageInRepositoryRoot } = config
|
|
396
|
-
|
|
397
|
-
const isWorkspace = await isWorkspacePackage()
|
|
398
|
-
|
|
399
|
-
try {
|
|
400
|
-
if ( !isPackageInRepositoryRoot ) {
|
|
401
|
-
await $`npm version --no-git-tag-version ${version} --prefix ${packagePath}`.quiet().nothrow()
|
|
402
|
-
if ( isWorkspace ) {
|
|
403
|
-
await $`npm install`
|
|
404
|
-
} else {
|
|
405
|
-
await $`npm install --prefix ${packagePath}`
|
|
406
|
-
}
|
|
407
|
-
} else {
|
|
408
|
-
await $`npm version --no-git-tag-version ${version}`.quiet().nothrow()
|
|
409
|
-
}
|
|
410
|
-
} catch ( err ) {
|
|
411
|
-
console.log( err.stderr || err )
|
|
412
|
-
process.exit( 1 )
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
const createNewBuildCommit = async ( { buildMessage } ) => {
|
|
417
|
-
try {
|
|
418
|
-
await $`git add .`
|
|
419
|
-
await $`git commit --allow-empty -m ${buildMessage}`
|
|
420
|
-
} catch ( err ) {
|
|
421
|
-
console.log( err.stderr || err )
|
|
422
|
-
process.exit( 1 )
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
const pushToGitRemote = async () => {
|
|
427
|
-
try {
|
|
428
|
-
await $`git push`
|
|
429
|
-
} catch ( err ) {
|
|
430
|
-
console.log( err.stderr || err )
|
|
431
|
-
process.exit( 1 )
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
const commitAndPushNewBuild = async ( config ) => {
|
|
436
|
-
const { buildMessage, noConfirm } = config
|
|
437
|
-
|
|
438
|
-
const confirmAnswer = noConfirm || await confirmPushCommit( buildMessage )
|
|
439
|
-
if ( !confirmAnswer ) {
|
|
440
|
-
console.log( 'Aborting...' )
|
|
441
|
-
process.exit()
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
await updateNpmPackageJsonAndLock( config )
|
|
445
|
-
await createNewBuildCommit( config )
|
|
446
|
-
await pushToGitRemote()
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
const confirmPushTag = async ( tagName, annotationMessage ) => {
|
|
450
|
-
const { confirm } = await prompt( [ {
|
|
451
|
-
type : 'confirm',
|
|
452
|
-
name : 'confirm',
|
|
453
|
-
message : `${colors.bold.red( '[Warning]' )} Push new tag ${colors.bold.yellow( tagName )} with annotation message "${colors.bold.yellow( annotationMessage )}" to git remote?`
|
|
454
|
-
} ] )
|
|
455
|
-
return confirm
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
const createGitTag = async ( tagName, annotationMessage ) => {
|
|
459
|
-
try {
|
|
460
|
-
await $`git tag -a ${tagName} -m "${annotationMessage}"`
|
|
461
|
-
} catch ( err ) {
|
|
462
|
-
console.log( err.stderr || err )
|
|
463
|
-
process.exit( 1 )
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
const pushGitTag = async ( tagName ) => {
|
|
468
|
-
try {
|
|
469
|
-
await $`git push origin ${tagName}`
|
|
470
|
-
} catch ( err ) {
|
|
471
|
-
console.log( err.stderr || err )
|
|
472
|
-
process.exit( 1 )
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
const createAndPushGitTag = async ( { tagName, annotationMessage, noConfirm } ) => {
|
|
477
|
-
const confirmAnswer = noConfirm || await confirmPushTag( tagName, annotationMessage )
|
|
478
|
-
if ( confirmAnswer ) {
|
|
479
|
-
await createGitTag( tagName, annotationMessage )
|
|
480
|
-
await pushGitTag( tagName )
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
const confirmPublishToNpmjs = async ( version, npmjsTag ) => {
|
|
485
|
-
const { confirm } = await prompt( [ {
|
|
486
|
-
type : 'confirm',
|
|
487
|
-
name : 'confirm',
|
|
488
|
-
message : `${colors.bold.red( '[Warning]' )} Publish new version ${colors.bold.yellow( version )} to npmjs with tag ${colors.bold.yellow( npmjsTag )}?`
|
|
489
|
-
} ] )
|
|
490
|
-
return confirm
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
const publishToNpmjs = async ( { version, npmjsTag, noConfirm } ) => {
|
|
494
|
-
const confirmAnswer = noConfirm || await confirmPublishToNpmjs( version, npmjsTag )
|
|
495
|
-
if ( !confirmAnswer ) {
|
|
496
|
-
console.log( 'Aborting...' )
|
|
497
|
-
process.exit()
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
try {
|
|
501
|
-
await $`npm publish --tag ${npmjsTag}`
|
|
502
|
-
} catch ( err ) {
|
|
503
|
-
console.log( err.stderr || err )
|
|
504
|
-
process.exit( 1 )
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
const displayReleaseInfo = ( config ) => {
|
|
509
|
-
const {
|
|
510
|
-
branch,
|
|
511
|
-
version,
|
|
512
|
-
repositoryRoot,
|
|
513
|
-
packageName,
|
|
514
|
-
packagePath,
|
|
515
|
-
buildMessage,
|
|
516
|
-
tagName,
|
|
517
|
-
annotationMessage,
|
|
518
|
-
publishable,
|
|
519
|
-
npmjsTag,
|
|
520
|
-
isBetaRelease,
|
|
521
|
-
noGitTag,
|
|
522
|
-
} = config
|
|
523
|
-
|
|
524
|
-
console.log( `
|
|
525
|
-
|
|
526
|
-
${colors.bold.green( '============ Tag Release Summary ============' )}
|
|
527
|
-
${colors.blue( 'Branch:' )} ${branch}
|
|
528
|
-
${colors.blue( 'Version:' )} ${version}
|
|
529
|
-
${colors.blue( 'Root directory:' )} ${repositoryRoot}
|
|
530
|
-
${colors.blue( 'Package name:' )} ${packageName}
|
|
531
|
-
${colors.blue( 'package.json path:' )} ${path.join( packagePath, 'package.json' )}${buildMessage ? `
|
|
532
|
-
${colors.blue( 'Commit message:' )} ${buildMessage}` : ''}${isBetaRelease || noGitTag ? '' : `
|
|
533
|
-
${colors.blue( 'Git tag:' )} ${tagName}`}${isBetaRelease || noGitTag ? '' : `
|
|
534
|
-
${colors.blue( 'Git tag annotation:' )} ${annotationMessage}`}${publishable ? `
|
|
535
|
-
${colors.blue( 'Npmjs tag:' )} ${npmjsTag}` : ''}
|
|
536
|
-
${colors.bold.green( '=============================================' )}
|
|
537
|
-
` )
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
/**
|
|
541
|
-
* Script
|
|
542
|
-
*/
|
|
543
|
-
|
|
544
|
-
const optionList = [
|
|
545
|
-
{
|
|
546
|
-
name : 'branch',
|
|
547
|
-
type : String,
|
|
548
|
-
alias : 'b',
|
|
549
|
-
description : 'branch where the tag will be created',
|
|
550
|
-
},
|
|
551
|
-
{
|
|
552
|
-
name : 'npmjs-tag',
|
|
553
|
-
type : String,
|
|
554
|
-
alias : 'n',
|
|
555
|
-
description : 'npmjs package tag to be used when publishing (for npmjs lib repositories)',
|
|
556
|
-
typeLabel : 'alpha|beta|latest'
|
|
557
|
-
},
|
|
558
|
-
{
|
|
559
|
-
name : 'version',
|
|
560
|
-
type : String,
|
|
561
|
-
alias : 'v',
|
|
562
|
-
description : 'version to be tagged',
|
|
563
|
-
},
|
|
564
|
-
{
|
|
565
|
-
name : 'publishable',
|
|
566
|
-
type : Boolean,
|
|
567
|
-
alias : 'p',
|
|
568
|
-
description : 'flag to indicate the repository is publishable to npmjs',
|
|
569
|
-
},
|
|
570
|
-
{
|
|
571
|
-
name : 'package-path',
|
|
572
|
-
type : String,
|
|
573
|
-
alias : 'a',
|
|
574
|
-
description : 'relative path to the package from the projec\'s root in case it\'s a monorepo',
|
|
575
|
-
},
|
|
576
|
-
{
|
|
577
|
-
name : 'tag-suffix',
|
|
578
|
-
type : String,
|
|
579
|
-
alias : 't',
|
|
580
|
-
description : 'tag suffix to be appended to the version when pushing to git',
|
|
581
|
-
},
|
|
582
|
-
{
|
|
583
|
-
name : 'annotation-message',
|
|
584
|
-
type : String,
|
|
585
|
-
alias : 'm',
|
|
586
|
-
description : 'annotation message that will annotate the git tag',
|
|
587
|
-
},
|
|
588
|
-
{
|
|
589
|
-
name : 'branch-filter',
|
|
590
|
-
type : String,
|
|
591
|
-
alias : 'f',
|
|
592
|
-
description : 'branch filter used to filter available branches in interactive mode',
|
|
593
|
-
},
|
|
594
|
-
{
|
|
595
|
-
name : 'no-commit',
|
|
596
|
-
type : Boolean,
|
|
597
|
-
description : 'do not create a new commit on git (in case the goal is just tagging it)',
|
|
598
|
-
},
|
|
599
|
-
{
|
|
600
|
-
name : 'no-git-tag',
|
|
601
|
-
type : Boolean,
|
|
602
|
-
description : 'do not create a new tag on git',
|
|
603
|
-
},
|
|
604
|
-
{
|
|
605
|
-
name : 'no-confirm',
|
|
606
|
-
type : Boolean,
|
|
607
|
-
description : 'push to git and publish to npmjs without asking for confirmation',
|
|
608
|
-
},
|
|
609
|
-
{
|
|
610
|
-
name : 'help',
|
|
611
|
-
type : Boolean,
|
|
612
|
-
alias : 'h',
|
|
613
|
-
description : 'show this help',
|
|
614
|
-
},
|
|
615
|
-
]
|
|
616
|
-
|
|
617
|
-
const sections = [
|
|
618
|
-
{
|
|
619
|
-
header : 'Tag release script',
|
|
620
|
-
content : 'This script is intended to give users a simple way to create git tags, push them and publish to Npmjs (if the --publishable flag is passed)',
|
|
621
|
-
},
|
|
622
|
-
{ header : 'Options',
|
|
623
|
-
optionList,
|
|
624
|
-
},
|
|
625
|
-
]
|
|
626
|
-
|
|
627
|
-
const args = cliArgs( optionList, { partial : true } )
|
|
628
|
-
const help = cliHelp( sections )
|
|
629
|
-
|
|
630
|
-
if ( args.help ) {
|
|
631
|
-
console.log( help )
|
|
632
|
-
process.exit()
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
validateArgs( args )
|
|
636
|
-
|
|
637
|
-
const config = {}
|
|
638
|
-
|
|
639
|
-
config.noConfirm = !!args['no-confirm']
|
|
640
|
-
|
|
641
|
-
config.noCommit = !!args['no-commit']
|
|
642
|
-
|
|
643
|
-
config.noGitTag = !!args['no-git-tag']
|
|
644
|
-
|
|
645
|
-
config.repositoryRoot = await getGitRootDirectory()
|
|
646
|
-
|
|
647
|
-
config.branch = args.branch || await getBranch( { branchFilter : args['branch-filter'] } )
|
|
648
|
-
|
|
649
|
-
await checkoutToBranch( config )
|
|
650
|
-
|
|
651
|
-
const argsPackagePath = args['package-path'] && path.join( config.repositoryRoot, args['package-path'] )
|
|
652
|
-
config.packagePath = argsPackagePath || await getPackagePath( config )
|
|
653
|
-
|
|
654
|
-
config.isPackageInRepositoryRoot = await isPackageInRepositoryRoot( config )
|
|
655
|
-
|
|
656
|
-
config.version = args.version || await getVersion( config )
|
|
657
|
-
|
|
658
|
-
config.packageName = await getPackageName( config )
|
|
659
|
-
|
|
660
|
-
config.buildMessage = config.noCommit ? '' : getBuildMessage( config )
|
|
661
|
-
|
|
662
|
-
config.isBetaRelease = config.version.includes( '-beta.' )
|
|
663
|
-
|
|
664
|
-
if ( !config.isBetaRelease && !config.noGitTag ) {
|
|
665
|
-
const tagSuffix = args['tag-suffix'] ?? await getGitTagSuffix()
|
|
666
|
-
const tagPrefix = config.isPackageInRepositoryRoot ? '' : `${config.packageName}/`
|
|
667
|
-
config.tagName = `${tagPrefix}v${config.version}${tagSuffix}`
|
|
668
|
-
|
|
669
|
-
const annotationMessage = args['annotation-message'] ?? await getGitAnnotationMessage( config )
|
|
670
|
-
config.annotationMessage = annotationMessage
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
config.publishable = !!args.publishable
|
|
674
|
-
if ( config.publishable ) {
|
|
675
|
-
validateNpmjsTag( { config, args } )
|
|
676
|
-
config.npmjsTag = args['npmjs-tag'] || await promptForNpmjsTag( config )
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
displayReleaseInfo( config )
|
|
680
|
-
|
|
681
|
-
if ( !config.noConfirm ) {
|
|
682
|
-
const confirmResponse = await confirmTagRelease( config )
|
|
683
|
-
if ( confirmResponse === 'yes' ) {
|
|
684
|
-
config.noConfirm = true
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
if ( !config.noCommit ) { await commitAndPushNewBuild( config ) }
|
|
689
|
-
if ( !config.isBetaRelease && !config.noGitTag ) { await createAndPushGitTag( config ) }
|
|
690
|
-
if ( config.publishable ) { await publishToNpmjs( config ) }
|
|
691
|
-
|
|
692
|
-
process.exit()
|
|
File without changes
|