@raisenow/tamaro-cli 1.0.8 → 1.0.9
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/.eslintrc.js +0 -6
- package/.gitignore +1 -2
- package/.prettierignore +1 -0
- package/dist/cli.js +435 -88
- package/dist/webpack.config.js +42 -16
- package/package.json +29 -32
- package/readme.md +99 -73
- package/src/cli.ts +93 -15
- package/src/commands/build.ts +97 -0
- package/src/commands/deploy-email-config.ts +107 -0
- package/src/commands/deploy.ts +151 -0
- package/src/commands/dev.ts +61 -0
- package/src/commands/list-deployed.ts +102 -0
- package/src/commands/serve.ts +29 -0
- package/src/lib/aws.ts +119 -0
- package/src/lib/helpers.ts +100 -23
- package/src/webpack.config.ts +14 -2
- package/src/assets/rnw-logo.png +0 -0
- package/src/commands/build/index.ts +0 -42
- package/src/commands/deploy/index.ts +0 -24
- package/src/commands/dev/index.ts +0 -32
- package/src/commands/serve/index.ts +0 -12
package/src/cli.ts
CHANGED
|
@@ -2,10 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
import {createCommand} from 'commander'
|
|
4
4
|
import pkg from '../package.json'
|
|
5
|
+
import {logError} from 'lib/helpers'
|
|
5
6
|
import {dev, DevOptions} from 'commands/dev'
|
|
6
7
|
import {build, BuildOptions} from 'commands/build'
|
|
7
|
-
import {deploy, DeployOptions} from 'commands/deploy'
|
|
8
|
+
import {DEFAULT_TAG, deploy, DeployOptions} from 'commands/deploy'
|
|
8
9
|
import {serve} from 'commands/serve'
|
|
10
|
+
import {listDeployed, ListDeployedOptions} from 'commands/list-deployed'
|
|
11
|
+
import {
|
|
12
|
+
DEFAULT_AWS_S3_EMAIL_CONFIG_BUCKET,
|
|
13
|
+
deployEmailConfig,
|
|
14
|
+
DeployEmailConfigOptions,
|
|
15
|
+
} from 'commands/deploy-email-config'
|
|
16
|
+
import {DEFAULT_AWS_PROFILE} from 'lib/aws'
|
|
9
17
|
|
|
10
18
|
///////////////////////////////////////////////////////////////////////////////
|
|
11
19
|
|
|
@@ -18,7 +26,7 @@ process.on('unhandledRejection', (error) => {
|
|
|
18
26
|
|
|
19
27
|
// Exit on ctrl+c
|
|
20
28
|
process.on('SIGINT', () => {
|
|
21
|
-
process.exit(
|
|
29
|
+
process.exit(1)
|
|
22
30
|
})
|
|
23
31
|
|
|
24
32
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -29,8 +37,14 @@ const cli = createCommand().name(pkg.name).version(pkg.version, '-v, --version')
|
|
|
29
37
|
|
|
30
38
|
cli
|
|
31
39
|
.command('dev')
|
|
32
|
-
.description(
|
|
33
|
-
|
|
40
|
+
.description(
|
|
41
|
+
'Run the local development server for Tamaro Core or a particular customer configuration',
|
|
42
|
+
)
|
|
43
|
+
.option(
|
|
44
|
+
'--local-core',
|
|
45
|
+
'Load Tamaro Core from localhost instead of the CDN',
|
|
46
|
+
false,
|
|
47
|
+
)
|
|
34
48
|
.action(async (options: DevOptions) => {
|
|
35
49
|
await dev(options)
|
|
36
50
|
})
|
|
@@ -38,17 +52,31 @@ cli
|
|
|
38
52
|
cli
|
|
39
53
|
.command('build')
|
|
40
54
|
.description(
|
|
41
|
-
'Build optimised (minified) bundle of Tamaro Core or customer configuration
|
|
55
|
+
'Build an optimised (minified) bundle of Tamaro Core or a customer configuration',
|
|
42
56
|
)
|
|
43
|
-
.option(
|
|
44
|
-
|
|
57
|
+
.option(
|
|
58
|
+
'--local-core',
|
|
59
|
+
'Load Tamaro Core from localhost instead of the CDN',
|
|
60
|
+
false,
|
|
61
|
+
)
|
|
62
|
+
.option('--analyze', 'Generate bundle statistics to "reports" folder', false)
|
|
45
63
|
.option(
|
|
46
64
|
'--deploy',
|
|
47
|
-
'Deploy Tamaro Core or customer configuration bundle to AWS',
|
|
65
|
+
'Deploy Tamaro Core or a customer configuration bundle to AWS S3',
|
|
66
|
+
false,
|
|
67
|
+
)
|
|
68
|
+
.option('--serve', 'Run the generated bundle with a local web server', false)
|
|
69
|
+
.option(
|
|
70
|
+
'--tag <tag>',
|
|
71
|
+
'Tag which should be used for the deployment of the bundle',
|
|
72
|
+
DEFAULT_TAG,
|
|
48
73
|
)
|
|
49
|
-
.option(
|
|
50
|
-
|
|
51
|
-
|
|
74
|
+
.option(
|
|
75
|
+
'--profile <profile>',
|
|
76
|
+
'AWS profile which should be used for the deployment of the bundle',
|
|
77
|
+
DEFAULT_AWS_PROFILE,
|
|
78
|
+
)
|
|
79
|
+
.action(async (options: BuildOptions & DeployOptions) => {
|
|
52
80
|
await build(options)
|
|
53
81
|
|
|
54
82
|
if (options.deploy) {
|
|
@@ -63,21 +91,71 @@ cli
|
|
|
63
91
|
cli
|
|
64
92
|
.command('deploy')
|
|
65
93
|
.description(
|
|
66
|
-
'Deploy
|
|
94
|
+
'Deploy a pre-built Tamaro Core or customer configuration bundle to AWS S3',
|
|
95
|
+
)
|
|
96
|
+
.option(
|
|
97
|
+
'--tag <tag>',
|
|
98
|
+
'Tag which should be used for the deployment of the bundle',
|
|
99
|
+
DEFAULT_TAG,
|
|
100
|
+
)
|
|
101
|
+
.option(
|
|
102
|
+
'--profile <profile>',
|
|
103
|
+
'AWS profile which should be used for the deployment of the bundle',
|
|
104
|
+
DEFAULT_AWS_PROFILE,
|
|
67
105
|
)
|
|
68
|
-
.option('--tag <tag>', 'Tag which will be used for deployment of the bundle')
|
|
69
106
|
.action(async (options: DeployOptions) => {
|
|
70
107
|
await deploy(options)
|
|
71
108
|
})
|
|
72
109
|
|
|
73
110
|
cli
|
|
74
111
|
.command('serve')
|
|
75
|
-
.description('Run web
|
|
112
|
+
.description('Run a local web server for pre-built bundle')
|
|
76
113
|
.action(async () => {
|
|
77
114
|
await serve()
|
|
78
115
|
})
|
|
79
116
|
|
|
117
|
+
cli
|
|
118
|
+
.command('list-deployed')
|
|
119
|
+
.description(
|
|
120
|
+
'List deployments of Tamaro Core or a particular customer configuration',
|
|
121
|
+
)
|
|
122
|
+
.option(
|
|
123
|
+
'--config <config>',
|
|
124
|
+
'Configuration name (default: current customer configuration)',
|
|
125
|
+
)
|
|
126
|
+
.option(
|
|
127
|
+
'--profile <profile>',
|
|
128
|
+
'AWS profile which should be used for fetching deployments',
|
|
129
|
+
DEFAULT_AWS_PROFILE,
|
|
130
|
+
)
|
|
131
|
+
.action(async (options: ListDeployedOptions) => {
|
|
132
|
+
await listDeployed(options)
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
cli
|
|
136
|
+
.command('deploy-email-config')
|
|
137
|
+
.description('Deploy a widget’s email configuration to AWS S3')
|
|
138
|
+
.option(
|
|
139
|
+
'--bucket <bucket>',
|
|
140
|
+
'AWS S3 bucket where it should be deployed',
|
|
141
|
+
DEFAULT_AWS_S3_EMAIL_CONFIG_BUCKET,
|
|
142
|
+
)
|
|
143
|
+
.option(
|
|
144
|
+
'--profile <profile>',
|
|
145
|
+
'AWS profile which should be used for the deployment of email configuration',
|
|
146
|
+
DEFAULT_AWS_PROFILE,
|
|
147
|
+
)
|
|
148
|
+
.action(async (options: DeployEmailConfigOptions) => {
|
|
149
|
+
await deployEmailConfig(options)
|
|
150
|
+
})
|
|
151
|
+
|
|
80
152
|
///////////////////////////////////////////////////////////////////////////////
|
|
81
153
|
;(async () => {
|
|
82
|
-
|
|
154
|
+
try {
|
|
155
|
+
await cli.parseAsync(process.argv)
|
|
156
|
+
} catch (error: any) {
|
|
157
|
+
if (error.signal === 'SIGINT' && error.signalDescription) {
|
|
158
|
+
logError(`\n${error.signalDescription}`)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
83
161
|
})()
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import resolveBin from 'resolve-bin'
|
|
2
|
+
import {
|
|
3
|
+
fail,
|
|
4
|
+
getIfCoreFns,
|
|
5
|
+
getPaths,
|
|
6
|
+
getWidgetUuid,
|
|
7
|
+
logCommand,
|
|
8
|
+
logDataTable,
|
|
9
|
+
logTitle,
|
|
10
|
+
notify,
|
|
11
|
+
resolveOwn,
|
|
12
|
+
runCommandSync,
|
|
13
|
+
} from 'lib/helpers'
|
|
14
|
+
import {assertProfileValid} from 'lib/aws'
|
|
15
|
+
import {CORE_CONFIG_NAME, DeployOptions} from 'commands/deploy'
|
|
16
|
+
|
|
17
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
18
|
+
|
|
19
|
+
export type BuildOptions = {
|
|
20
|
+
localCore: boolean
|
|
21
|
+
analyze: boolean
|
|
22
|
+
deploy: boolean
|
|
23
|
+
serve: boolean
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
27
|
+
|
|
28
|
+
export const build = async (
|
|
29
|
+
options: BuildOptions & DeployOptions,
|
|
30
|
+
): Promise<void> => {
|
|
31
|
+
assertOptionsValid(options)
|
|
32
|
+
|
|
33
|
+
const flags = prepareFlags(options)
|
|
34
|
+
const {ifCore} = getIfCoreFns()
|
|
35
|
+
const paths = getPaths(ifCore)
|
|
36
|
+
const configName = ifCore(CORE_CONFIG_NAME, getWidgetUuid())
|
|
37
|
+
const title = ifCore(
|
|
38
|
+
'Building optimised (minified) bundle of Tamaro Core …',
|
|
39
|
+
`Building optimised (minified) bundle of “${configName}” customer configuration …`,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
const wpBin = resolveBin.sync('webpack')
|
|
43
|
+
const wpConfig = resolveOwn('dist/webpack.config.js')
|
|
44
|
+
const cmd = `
|
|
45
|
+
${wpBin}
|
|
46
|
+
--config ${wpConfig}
|
|
47
|
+
--env min
|
|
48
|
+
${flags}
|
|
49
|
+
`
|
|
50
|
+
|
|
51
|
+
logTitle(title)
|
|
52
|
+
logCommand(cmd)
|
|
53
|
+
runCommandSync(cmd, {stdio: 'inherit'})
|
|
54
|
+
|
|
55
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
56
|
+
|
|
57
|
+
logDataTable(
|
|
58
|
+
{'Path:': paths.appDist},
|
|
59
|
+
`Bundle for “${configName}” customer configuration is done.`,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
63
|
+
|
|
64
|
+
notify({
|
|
65
|
+
title: 'build',
|
|
66
|
+
message: `Bundle for “${configName}” customer configuration is done.`,
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
71
|
+
|
|
72
|
+
const assertOptionsValid = (options: BuildOptions & DeployOptions) => {
|
|
73
|
+
const {localCore, deploy, profile} = options
|
|
74
|
+
const {ifCore} = getIfCoreFns()
|
|
75
|
+
|
|
76
|
+
if (ifCore() && localCore) {
|
|
77
|
+
fail('Flag "--local-core" is redundant if running in Tamaro Core context.')
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (localCore && deploy) {
|
|
81
|
+
fail('Flags "--local-core" and "--deploy" must not be used together.')
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
assertProfileValid(profile)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
88
|
+
|
|
89
|
+
const prepareFlags = (options: BuildOptions): string => {
|
|
90
|
+
const {localCore, analyze} = options
|
|
91
|
+
let flags: string[] = []
|
|
92
|
+
|
|
93
|
+
flags = localCore ? [...flags, '--env localCore'] : flags
|
|
94
|
+
flags = analyze ? [...flags, '--env analyze'] : flags
|
|
95
|
+
|
|
96
|
+
return flags.join(' ')
|
|
97
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import {existsSync} from 'fs'
|
|
2
|
+
import {
|
|
3
|
+
fail,
|
|
4
|
+
getIfCoreFns,
|
|
5
|
+
getPaths,
|
|
6
|
+
getWidgetUuid,
|
|
7
|
+
logCommand,
|
|
8
|
+
logDataTable,
|
|
9
|
+
logTitle,
|
|
10
|
+
notify,
|
|
11
|
+
} from 'lib/helpers'
|
|
12
|
+
import {assertProfileValid, AwsOptions, runAwsCommandSync} from 'lib/aws'
|
|
13
|
+
|
|
14
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
15
|
+
|
|
16
|
+
export type DeployEmailConfigOptions = AwsOptions & {
|
|
17
|
+
bucket: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
21
|
+
|
|
22
|
+
export const DEFAULT_AWS_S3_EMAIL_CONFIG_BUCKET = 'rnw-email-service'
|
|
23
|
+
|
|
24
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
25
|
+
|
|
26
|
+
export const deployEmailConfig = async (
|
|
27
|
+
options: DeployEmailConfigOptions,
|
|
28
|
+
): Promise<void> => {
|
|
29
|
+
const {ifCore} = getIfCoreFns()
|
|
30
|
+
const paths = getPaths(ifCore)
|
|
31
|
+
const emailConfigPath = `${paths.app}/email-config`
|
|
32
|
+
|
|
33
|
+
assertOptionsValid(options)
|
|
34
|
+
assertEmailConfigPathExists(emailConfigPath)
|
|
35
|
+
assertIsNotCore()
|
|
36
|
+
|
|
37
|
+
const {bucket} = options
|
|
38
|
+
const configName = getWidgetUuid()
|
|
39
|
+
const deployUrl = `s3://${bucket}/${configName}`
|
|
40
|
+
|
|
41
|
+
const cmd = `
|
|
42
|
+
aws s3 sync ${emailConfigPath} ${deployUrl}
|
|
43
|
+
--delete
|
|
44
|
+
--exact-timestamps
|
|
45
|
+
`
|
|
46
|
+
logTitle(
|
|
47
|
+
`Deploying email configuration for “${configName}” customer configuration to AWS S3 …`,
|
|
48
|
+
)
|
|
49
|
+
logCommand(cmd)
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
runAwsCommandSync(cmd, {stdout: 'inherit'})
|
|
53
|
+
} catch (error: any) {
|
|
54
|
+
fail(error.stderr)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
58
|
+
|
|
59
|
+
logDataTable(
|
|
60
|
+
{'Deploy URL:': deployUrl},
|
|
61
|
+
`Email configuration for “${configName}” customer configuration is deployed.`,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
65
|
+
|
|
66
|
+
notify({
|
|
67
|
+
title: `deploy-email-config`,
|
|
68
|
+
message: `Email configuration for “${configName}” customer configuration is deployed.`,
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
73
|
+
|
|
74
|
+
const assertOptionsValid = (options: DeployEmailConfigOptions) => {
|
|
75
|
+
const {bucket, profile} = options
|
|
76
|
+
|
|
77
|
+
assertBucketValid(bucket)
|
|
78
|
+
assertProfileValid(profile)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
82
|
+
|
|
83
|
+
const assertEmailConfigPathExists = (distPath: string) => {
|
|
84
|
+
if (!existsSync(distPath)) {
|
|
85
|
+
fail('Email config folder does not exists. Nothing to deploy.')
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
90
|
+
|
|
91
|
+
const assertBucketValid = (tag: string) => {
|
|
92
|
+
const regex = /^[a-zA-Z0-9-_]+$/
|
|
93
|
+
|
|
94
|
+
if (!regex.test(tag)) {
|
|
95
|
+
fail(`Flag "--bucket" has forbidden format. Allowed format: ${regex}.`)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
100
|
+
|
|
101
|
+
const assertIsNotCore = () => {
|
|
102
|
+
const {ifCore} = getIfCoreFns()
|
|
103
|
+
|
|
104
|
+
if (ifCore()) {
|
|
105
|
+
fail('You cannot deploy widget email configuration for Tamaro Core.')
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import {existsSync} from 'fs'
|
|
2
|
+
import stripIndent from 'strip-indent'
|
|
3
|
+
import {
|
|
4
|
+
fail,
|
|
5
|
+
getIfCoreFns,
|
|
6
|
+
getPaths,
|
|
7
|
+
getWidgetUuid,
|
|
8
|
+
logCommand,
|
|
9
|
+
logDataTable,
|
|
10
|
+
logTitle,
|
|
11
|
+
notify,
|
|
12
|
+
} from 'lib/helpers'
|
|
13
|
+
import {assertProfileValid, AwsOptions, runAwsCommandSync} from 'lib/aws'
|
|
14
|
+
|
|
15
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
16
|
+
|
|
17
|
+
export type DeployOptions = AwsOptions & {
|
|
18
|
+
tag: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
22
|
+
|
|
23
|
+
export const AWS_S3_BUCKET = 'tamaro.raisenow.com'
|
|
24
|
+
export const CORE_CONFIG_NAME = 'tamaro-core'
|
|
25
|
+
const AWS_CLOUDFRONT_DISTRIBUTION_ID = 'EHJ1OM458YQ0I'
|
|
26
|
+
export const DEFAULT_TAG = 'latest'
|
|
27
|
+
|
|
28
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
29
|
+
|
|
30
|
+
export const deploy = async (options: DeployOptions): Promise<void> => {
|
|
31
|
+
const {ifCore} = getIfCoreFns()
|
|
32
|
+
const paths = getPaths(ifCore)
|
|
33
|
+
|
|
34
|
+
assertOptionsValid(options)
|
|
35
|
+
assertDistPathExists(paths.appDist)
|
|
36
|
+
|
|
37
|
+
const {tag} = options
|
|
38
|
+
const configName = ifCore(CORE_CONFIG_NAME, getWidgetUuid())
|
|
39
|
+
const deployUrl = `s3://${AWS_S3_BUCKET}/${configName}/${tag}`
|
|
40
|
+
const entryFilename = ifCore('index.js', 'widget.js')
|
|
41
|
+
|
|
42
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
43
|
+
// Sync all files except entrypoint (without deleting old files)
|
|
44
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
45
|
+
|
|
46
|
+
const cmdSyncAll = `
|
|
47
|
+
aws s3 sync ${paths.appDist} ${deployUrl}
|
|
48
|
+
--acl public-read
|
|
49
|
+
--size-only
|
|
50
|
+
--exclude ${paths.appDist}/${entryFilename}
|
|
51
|
+
--cache-control max-age=31536000
|
|
52
|
+
`
|
|
53
|
+
logTitle('Deploying to AWS S3 …')
|
|
54
|
+
logCommand(cmdSyncAll)
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
runAwsCommandSync(cmdSyncAll, {stdout: 'inherit'})
|
|
58
|
+
} catch (error: any) {
|
|
59
|
+
fail(error.stderr)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
63
|
+
// Copy entrypoint
|
|
64
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
65
|
+
|
|
66
|
+
const cmdCpEntry = `
|
|
67
|
+
aws s3 cp ${paths.appDist}/${entryFilename} ${deployUrl}/${entryFilename}
|
|
68
|
+
--acl public-read
|
|
69
|
+
--cache-control max-age=64800
|
|
70
|
+
`
|
|
71
|
+
logCommand(cmdCpEntry)
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
runAwsCommandSync(cmdCpEntry, {stdout: 'inherit'})
|
|
75
|
+
} catch (error: any) {
|
|
76
|
+
fail(error.stderr)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
80
|
+
// Invalidate cloudfront cache
|
|
81
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
82
|
+
|
|
83
|
+
const cmdInvalidateCache = `
|
|
84
|
+
aws cloudfront create-invalidation
|
|
85
|
+
--distribution-id ${AWS_CLOUDFRONT_DISTRIBUTION_ID}
|
|
86
|
+
--paths /${configName}/${tag}/*
|
|
87
|
+
`
|
|
88
|
+
logTitle('Invalidating edge cache …')
|
|
89
|
+
logCommand(cmdInvalidateCache)
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
// ignore output
|
|
93
|
+
runAwsCommandSync(cmdInvalidateCache)
|
|
94
|
+
} catch (error: any) {
|
|
95
|
+
fail(error.stderr)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
99
|
+
|
|
100
|
+
const demoPage = `https://${AWS_S3_BUCKET}/${configName}/${tag}/index.html`
|
|
101
|
+
const entryPoint = `https://${AWS_S3_BUCKET}/${configName}/${tag}/${entryFilename}`
|
|
102
|
+
|
|
103
|
+
logDataTable(
|
|
104
|
+
{
|
|
105
|
+
'Demo page:': demoPage,
|
|
106
|
+
'Entry point:': entryPoint,
|
|
107
|
+
},
|
|
108
|
+
`Bundle for “${configName}” is deployed with tag “${tag}”`,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
112
|
+
|
|
113
|
+
notify({
|
|
114
|
+
title: 'deploy',
|
|
115
|
+
message: stripIndent(`
|
|
116
|
+
Bundle for “${configName}” is deployed with tag “${tag}”.
|
|
117
|
+
Demo page: ${demoPage}
|
|
118
|
+
`),
|
|
119
|
+
target: demoPage,
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
124
|
+
|
|
125
|
+
const assertOptionsValid = (options: DeployOptions) => {
|
|
126
|
+
const {tag, profile} = options
|
|
127
|
+
|
|
128
|
+
assertTagValid(tag)
|
|
129
|
+
assertProfileValid(profile)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
133
|
+
|
|
134
|
+
const assertDistPathExists = (distPath: string) => {
|
|
135
|
+
if (!existsSync(distPath)) {
|
|
136
|
+
fail(`
|
|
137
|
+
Dist folder does not exists.
|
|
138
|
+
Make sure you have built the bundle before trying to deploy it.
|
|
139
|
+
`)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
144
|
+
|
|
145
|
+
const assertTagValid = (tag: string) => {
|
|
146
|
+
const regex = /^[a-zA-Z0-9-_]+$/
|
|
147
|
+
|
|
148
|
+
if (!regex.test(tag)) {
|
|
149
|
+
fail(`Flag "--tag" has forbidden format. Allowed format: ${regex}.`)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import resolveBin from 'resolve-bin'
|
|
2
|
+
import {
|
|
3
|
+
fail,
|
|
4
|
+
getIfCoreFns,
|
|
5
|
+
logCommand,
|
|
6
|
+
logTitle,
|
|
7
|
+
resolveOwn,
|
|
8
|
+
runCommandSync,
|
|
9
|
+
} from 'lib/helpers'
|
|
10
|
+
|
|
11
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
12
|
+
|
|
13
|
+
export type DevOptions = {
|
|
14
|
+
localCore: boolean
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
18
|
+
|
|
19
|
+
export const dev = async (options: DevOptions): Promise<void> => {
|
|
20
|
+
assertOptionsValid(options)
|
|
21
|
+
|
|
22
|
+
const flags = prepareFlags(options)
|
|
23
|
+
const {ifCore} = getIfCoreFns()
|
|
24
|
+
const title = ifCore(
|
|
25
|
+
'Running dev web-server for Tamaro Core …',
|
|
26
|
+
'Running dev web-server for customer configuration …',
|
|
27
|
+
)
|
|
28
|
+
const wpBin = resolveBin.sync('webpack')
|
|
29
|
+
const wpConfig = resolveOwn('dist/webpack.config.js')
|
|
30
|
+
const cmd = `
|
|
31
|
+
${wpBin} serve
|
|
32
|
+
--config ${wpConfig}
|
|
33
|
+
${flags}
|
|
34
|
+
`
|
|
35
|
+
|
|
36
|
+
logTitle(title)
|
|
37
|
+
logCommand(cmd)
|
|
38
|
+
runCommandSync(cmd, {stdio: 'inherit'})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
42
|
+
|
|
43
|
+
const assertOptionsValid = (options: DevOptions) => {
|
|
44
|
+
const {localCore} = options
|
|
45
|
+
const {ifCore} = getIfCoreFns()
|
|
46
|
+
|
|
47
|
+
if (ifCore() && localCore) {
|
|
48
|
+
fail('Flag "--local-core" is redundant if running in Tamaro Core context.')
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
53
|
+
|
|
54
|
+
const prepareFlags = (options: DevOptions): string => {
|
|
55
|
+
const {localCore} = options
|
|
56
|
+
let flags: string[] = []
|
|
57
|
+
|
|
58
|
+
flags = localCore ? [...flags, '--env localCore'] : flags
|
|
59
|
+
|
|
60
|
+
return flags.join(' ')
|
|
61
|
+
}
|