@pwrdrvr/microapps-publish 0.0.21 → 0.0.25
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/dist/commands/nextjs-docker-auto.d.ts +6 -0
- package/dist/commands/nextjs-docker-auto.d.ts.map +1 -1
- package/dist/commands/nextjs-docker-auto.js +87 -26
- package/dist/commands/nextjs-docker-auto.js.map +1 -1
- package/dist/commands/nextjs-version-restore.d.ts.map +1 -1
- package/dist/commands/nextjs-version-restore.js +4 -10
- package/dist/commands/nextjs-version-restore.js.map +1 -1
- package/dist/commands/nextjs-version.d.ts.map +1 -1
- package/dist/commands/nextjs-version.js +4 -10
- package/dist/commands/nextjs-version.js.map +1 -1
- package/dist/commands/preflight.d.ts +1 -0
- package/dist/commands/preflight.d.ts.map +1 -1
- package/dist/commands/preflight.js +21 -14
- package/dist/commands/preflight.js.map +1 -1
- package/dist/commands/publish-static.d.ts +20 -0
- package/dist/commands/publish-static.d.ts.map +1 -0
- package/dist/commands/publish-static.js +281 -0
- package/dist/commands/publish-static.js.map +1 -0
- package/dist/commands/publish.d.ts +4 -0
- package/dist/commands/publish.d.ts.map +1 -1
- package/dist/commands/publish.js +61 -17
- package/dist/commands/publish.js.map +1 -1
- package/dist/lib/DeployClient.d.ts +10 -2
- package/dist/lib/DeployClient.d.ts.map +1 -1
- package/dist/lib/DeployClient.js +9 -4
- package/dist/lib/DeployClient.js.map +1 -1
- package/package.json +1 -2
- package/src/commands/nextjs-docker-auto.ts +91 -26
- package/src/commands/nextjs-version-restore.ts +5 -9
- package/src/commands/nextjs-version.ts +5 -9
- package/src/commands/preflight.ts +23 -16
- package/src/commands/publish-static.ts +322 -0
- package/src/commands/publish.ts +64 -16
- package/src/lib/DeployClient.ts +15 -7
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import * as s3 from '@aws-sdk/client-s3';
|
|
3
|
+
import * as sts from '@aws-sdk/client-sts';
|
|
4
|
+
import { Command, flags as flagsParser } from '@oclif/command';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import { pathExists, createReadStream } from 'fs-extra';
|
|
7
|
+
import { Listr, ListrTask } from 'listr2';
|
|
8
|
+
import { Config } from '../config/Config';
|
|
9
|
+
import DeployClient, { IDeployVersionPreflightResult } from '../lib/DeployClient';
|
|
10
|
+
import S3Uploader from '../lib/S3Uploader';
|
|
11
|
+
import S3TransferUtility from '../lib/S3TransferUtility';
|
|
12
|
+
import { Upload } from '@aws-sdk/lib-storage';
|
|
13
|
+
import { contentType } from 'mime-types';
|
|
14
|
+
import { createVersions, IVersions } from '../lib/Versions';
|
|
15
|
+
|
|
16
|
+
interface IContext {
|
|
17
|
+
preflightResult: IDeployVersionPreflightResult;
|
|
18
|
+
files: string[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class PublishCommand extends Command {
|
|
22
|
+
static description = 'Publish arbitrary framework static app - deploy static assets to S3 only.';
|
|
23
|
+
|
|
24
|
+
static examples = [
|
|
25
|
+
`$ microapps-publish publish-static -d microapps-deployer-dev -n 0.0.21 -l microapps-app-release-dev -a release
|
|
26
|
+
✔ Get S3 Temp Credentials [1s]
|
|
27
|
+
✔ Confirm Static Assets Folder Exists [0.0s]
|
|
28
|
+
✔ Copy Static Files to Local Upload Dir [0.0s]
|
|
29
|
+
✔ Enumerate Files to Upload to S3 [0.0s]
|
|
30
|
+
✔ Upload Static Files to S3 [1s]
|
|
31
|
+
✔ Creating MicroApp Application: release [0.0s]
|
|
32
|
+
✔ Creating MicroApp Version: 0.0.21 [1s]
|
|
33
|
+
`,
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
static flags = {
|
|
37
|
+
version: flagsParser.version({
|
|
38
|
+
char: 'v',
|
|
39
|
+
}),
|
|
40
|
+
help: flagsParser.help(),
|
|
41
|
+
deployerLambdaName: flagsParser.string({
|
|
42
|
+
char: 'd',
|
|
43
|
+
multiple: false,
|
|
44
|
+
required: true,
|
|
45
|
+
description: 'Name of the deployer lambda function',
|
|
46
|
+
}),
|
|
47
|
+
newVersion: flagsParser.string({
|
|
48
|
+
char: 'n',
|
|
49
|
+
multiple: false,
|
|
50
|
+
required: true,
|
|
51
|
+
description: 'New semantic version to apply',
|
|
52
|
+
}),
|
|
53
|
+
appName: flagsParser.string({
|
|
54
|
+
char: 'a',
|
|
55
|
+
multiple: false,
|
|
56
|
+
required: false,
|
|
57
|
+
description: 'MicroApps app name',
|
|
58
|
+
}),
|
|
59
|
+
staticAssetsPath: flagsParser.string({
|
|
60
|
+
char: 's',
|
|
61
|
+
multiple: false,
|
|
62
|
+
required: false,
|
|
63
|
+
description:
|
|
64
|
+
'Path to files to be uploaded to S3 static bucket at app/version/ path. Do include app/version/ in path if files are already "rooted" under that path locally.',
|
|
65
|
+
}),
|
|
66
|
+
defaultFile: flagsParser.string({
|
|
67
|
+
char: 'i',
|
|
68
|
+
multiple: false,
|
|
69
|
+
required: false,
|
|
70
|
+
description:
|
|
71
|
+
'Default file to return when the app is loaded via the router without a version (e.g. when app/ is requested).',
|
|
72
|
+
}),
|
|
73
|
+
overwrite: flagsParser.boolean({
|
|
74
|
+
char: 'o',
|
|
75
|
+
required: false,
|
|
76
|
+
default: false,
|
|
77
|
+
description:
|
|
78
|
+
'Allow overwrite - Warn but do not fail if version exists. Discouraged outside of test envs if cacheable static files have changed.',
|
|
79
|
+
}),
|
|
80
|
+
noCache: flagsParser.boolean({
|
|
81
|
+
required: false,
|
|
82
|
+
default: false,
|
|
83
|
+
description: 'Force revalidation of CloudFront and browser caching of static assets',
|
|
84
|
+
}),
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
private VersionAndAlias: IVersions;
|
|
88
|
+
|
|
89
|
+
async run(): Promise<void> {
|
|
90
|
+
const config = Config.instance;
|
|
91
|
+
|
|
92
|
+
// const RUNNING_TEXT = ' RUNS ';
|
|
93
|
+
// const RUNNING = chalk.reset.inverse.yellow.bold(RUNNING_TEXT) + ' ';
|
|
94
|
+
const RUNNING = ''; //chalk.reset.inverse.yellow.bold(RUNNING_TEXT) + ' ';
|
|
95
|
+
|
|
96
|
+
const { flags: parsedFlags } = this.parse(PublishCommand);
|
|
97
|
+
const appName = parsedFlags.appName ?? config.app.name;
|
|
98
|
+
const deployerLambdaName = parsedFlags.deployerLambdaName ?? config.deployer.lambdaName;
|
|
99
|
+
const semVer = parsedFlags.newVersion ?? config.app.semVer;
|
|
100
|
+
const staticAssetsPath = parsedFlags.staticAssetsPath ?? config.app.staticAssetsPath;
|
|
101
|
+
const defaultFile = parsedFlags.defaultFile ?? config.app.defaultFile;
|
|
102
|
+
const overwrite = parsedFlags.overwrite;
|
|
103
|
+
const noCache = parsedFlags.noCache;
|
|
104
|
+
|
|
105
|
+
// Override the config value
|
|
106
|
+
config.deployer.lambdaName = deployerLambdaName;
|
|
107
|
+
delete config.app.lambdaName;
|
|
108
|
+
config.app.name = appName;
|
|
109
|
+
config.app.semVer = semVer;
|
|
110
|
+
config.app.staticAssetsPath = staticAssetsPath;
|
|
111
|
+
config.app.defaultFile = defaultFile;
|
|
112
|
+
|
|
113
|
+
// Get the account ID and region from STS
|
|
114
|
+
// TODO: Move this to the right place
|
|
115
|
+
if (config.app.awsAccountID === 0 || config.app.awsRegion === '') {
|
|
116
|
+
const stsClient = new sts.STSClient({
|
|
117
|
+
maxAttempts: 8,
|
|
118
|
+
});
|
|
119
|
+
const stsResponse = await stsClient.send(new sts.GetCallerIdentityCommand({}));
|
|
120
|
+
if (config.app.awsAccountID === 0) {
|
|
121
|
+
config.app.awsAccountID = parseInt(stsResponse.Account, 10);
|
|
122
|
+
}
|
|
123
|
+
if (config.app.awsRegion === '') {
|
|
124
|
+
config.app.awsRegion = stsClient.config.region as string;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
this.VersionAndAlias = createVersions(semVer);
|
|
129
|
+
|
|
130
|
+
if (config.app.staticAssetsPath === undefined) {
|
|
131
|
+
this.error('staticAssetsPath must be specified');
|
|
132
|
+
}
|
|
133
|
+
if (config.app.defaultFile === undefined || config.app.defaultFile === '') {
|
|
134
|
+
this.error('defaultFile must be specified');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
//
|
|
138
|
+
// Setup Tasks
|
|
139
|
+
//
|
|
140
|
+
|
|
141
|
+
const tasks = new Listr<IContext>(
|
|
142
|
+
[
|
|
143
|
+
{
|
|
144
|
+
// TODO: Disable this task if no static assets path
|
|
145
|
+
title: 'Get S3 Temp Credentials',
|
|
146
|
+
task: async (ctx, task) => {
|
|
147
|
+
const origTitle = task.title;
|
|
148
|
+
task.title = RUNNING + origTitle;
|
|
149
|
+
|
|
150
|
+
// Confirm the Version Does Not Exist in Published State
|
|
151
|
+
task.output = `Checking if deployed app/version already exists for ${config.app.name}/${semVer}`;
|
|
152
|
+
ctx.preflightResult = await DeployClient.DeployVersionPreflight({
|
|
153
|
+
config,
|
|
154
|
+
overwrite,
|
|
155
|
+
output: (message: string) => (task.output = message),
|
|
156
|
+
});
|
|
157
|
+
if (ctx.preflightResult.exists) {
|
|
158
|
+
if (!overwrite) {
|
|
159
|
+
throw new Error(
|
|
160
|
+
`App/Version already exists: ${config.app.name}/${config.app.semVer}`,
|
|
161
|
+
);
|
|
162
|
+
} else {
|
|
163
|
+
task.title = `Warning: App/Version already exists: ${config.app.name}/${config.app.semVer}`;
|
|
164
|
+
}
|
|
165
|
+
} else {
|
|
166
|
+
task.title = `App/Version does not exist: ${config.app.name}/${config.app.semVer}`;
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
// TODO: Disable this task if no static assets path
|
|
172
|
+
title: 'Confirm Static Assets Folder Exists',
|
|
173
|
+
task: async (ctx, task) => {
|
|
174
|
+
const origTitle = task.title;
|
|
175
|
+
task.title = RUNNING + origTitle;
|
|
176
|
+
|
|
177
|
+
// Check that Static Assets Folder exists
|
|
178
|
+
if (!(await pathExists(config.app.staticAssetsPath))) {
|
|
179
|
+
this.error(`Static asset path does not exist: ${config.app.staticAssetsPath}`);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
task.title = origTitle;
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
// TODO: Disable this task if no static assets path
|
|
187
|
+
title: 'Copy Static Files to Local Upload Dir',
|
|
188
|
+
task: async (ctx, task) => {
|
|
189
|
+
const origTitle = task.title;
|
|
190
|
+
task.title = RUNNING + origTitle;
|
|
191
|
+
|
|
192
|
+
// Copy files to local dir to be uploaded
|
|
193
|
+
await S3Uploader.CopyToUploadDir(config, ctx.preflightResult.response.s3UploadUrl);
|
|
194
|
+
|
|
195
|
+
task.title = origTitle;
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
// TODO: Disable this task if no static assets path
|
|
200
|
+
title: 'Enumerate Files to Upload to S3',
|
|
201
|
+
task: async (ctx, task) => {
|
|
202
|
+
const origTitle = task.title;
|
|
203
|
+
task.title = RUNNING + origTitle;
|
|
204
|
+
|
|
205
|
+
ctx.files = (await S3TransferUtility.GetFiles(S3Uploader.TempDir)) as string[];
|
|
206
|
+
|
|
207
|
+
task.title = origTitle;
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
// TODO: Disable this task if no static assets path
|
|
212
|
+
title: 'Upload Static Files to S3',
|
|
213
|
+
task: (ctx, task) => {
|
|
214
|
+
const origTitle = task.title;
|
|
215
|
+
task.title = RUNNING + origTitle;
|
|
216
|
+
|
|
217
|
+
const { bucketName, destinationPrefix } = S3Uploader.ParseUploadPath(
|
|
218
|
+
ctx.preflightResult.response.s3UploadUrl,
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
// Use temp credentials for S3
|
|
222
|
+
const s3Client = new s3.S3Client({
|
|
223
|
+
maxAttempts: 16,
|
|
224
|
+
credentials: {
|
|
225
|
+
accessKeyId: ctx.preflightResult.response.awsCredentials.accessKeyId,
|
|
226
|
+
secretAccessKey: ctx.preflightResult.response.awsCredentials.secretAccessKey,
|
|
227
|
+
sessionToken: ctx.preflightResult.response.awsCredentials.sessionToken,
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// Setup caching on static assets
|
|
232
|
+
// NoCache - Only used for test deploys, requires browser and CloudFront to refetch every time
|
|
233
|
+
// Overwrite - Reduces default cache time period from 24 hours to 15 minutes
|
|
234
|
+
// Default - 24 hours
|
|
235
|
+
const CacheControl = noCache
|
|
236
|
+
? 'max-age=0, must-revalidate, public'
|
|
237
|
+
: overwrite
|
|
238
|
+
? `max-age=${15 * 60}, public`
|
|
239
|
+
: `max-age=${24 * 60 * 60}, public`;
|
|
240
|
+
|
|
241
|
+
const pathWithoutAppAndVer = path.join(S3Uploader.TempDir, destinationPrefix);
|
|
242
|
+
|
|
243
|
+
const tasks: ListrTask<IContext>[] = ctx.files.map((filePath) => ({
|
|
244
|
+
task: async (ctx: IContext, subtask) => {
|
|
245
|
+
const relFilePath = path.relative(pathWithoutAppAndVer, filePath);
|
|
246
|
+
|
|
247
|
+
const origTitle = relFilePath;
|
|
248
|
+
subtask.title = RUNNING + origTitle;
|
|
249
|
+
|
|
250
|
+
const upload = new Upload({
|
|
251
|
+
client: s3Client,
|
|
252
|
+
leavePartsOnError: false,
|
|
253
|
+
params: {
|
|
254
|
+
Bucket: bucketName,
|
|
255
|
+
Key: path.relative(S3Uploader.TempDir, filePath),
|
|
256
|
+
Body: createReadStream(filePath),
|
|
257
|
+
ContentType: contentType(path.basename(filePath)) || 'application/octet-stream',
|
|
258
|
+
CacheControl,
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
await upload.done();
|
|
262
|
+
|
|
263
|
+
subtask.title = origTitle;
|
|
264
|
+
},
|
|
265
|
+
}));
|
|
266
|
+
|
|
267
|
+
task.title = origTitle;
|
|
268
|
+
|
|
269
|
+
return task.newListr(tasks, {
|
|
270
|
+
concurrent: 8,
|
|
271
|
+
rendererOptions: {
|
|
272
|
+
clearOutput: false,
|
|
273
|
+
showErrorMessage: true,
|
|
274
|
+
showTimer: true,
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
title: `Creating MicroApp Application: ${config.app.name}`,
|
|
281
|
+
task: async (ctx, task) => {
|
|
282
|
+
const origTitle = task.title;
|
|
283
|
+
task.title = RUNNING + origTitle;
|
|
284
|
+
|
|
285
|
+
// Call Deployer to Create App if Not Exists
|
|
286
|
+
await DeployClient.CreateApp({ config });
|
|
287
|
+
|
|
288
|
+
task.title = origTitle;
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
title: `Creating MicroApp Version: ${config.app.semVer}`,
|
|
293
|
+
task: async (ctx, task) => {
|
|
294
|
+
const origTitle = task.title;
|
|
295
|
+
task.title = RUNNING + origTitle;
|
|
296
|
+
|
|
297
|
+
// Call Deployer to Deploy AppName/Version
|
|
298
|
+
await DeployClient.DeployVersion({
|
|
299
|
+
config,
|
|
300
|
+
appType: 'static',
|
|
301
|
+
overwrite,
|
|
302
|
+
output: (message: string) => (task.output = message),
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
task.title = origTitle;
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
],
|
|
309
|
+
{
|
|
310
|
+
rendererOptions: {
|
|
311
|
+
showTimer: true,
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
try {
|
|
317
|
+
await tasks.run();
|
|
318
|
+
} finally {
|
|
319
|
+
await S3Uploader.removeTempDirIfExists();
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
package/src/commands/publish.ts
CHANGED
|
@@ -4,7 +4,6 @@ import * as lambda from '@aws-sdk/client-lambda';
|
|
|
4
4
|
import * as s3 from '@aws-sdk/client-s3';
|
|
5
5
|
import * as sts from '@aws-sdk/client-sts';
|
|
6
6
|
import { Command, flags as flagsParser } from '@oclif/command';
|
|
7
|
-
import * as chalk from 'chalk';
|
|
8
7
|
import * as path from 'path';
|
|
9
8
|
import { pathExists, createReadStream } from 'fs-extra';
|
|
10
9
|
import { Listr, ListrTask } from 'listr2';
|
|
@@ -74,6 +73,32 @@ export class PublishCommand extends Command {
|
|
|
74
73
|
required: false,
|
|
75
74
|
description: 'MicroApps app name',
|
|
76
75
|
}),
|
|
76
|
+
staticAssetsPath: flagsParser.string({
|
|
77
|
+
char: 's',
|
|
78
|
+
multiple: false,
|
|
79
|
+
required: false,
|
|
80
|
+
description:
|
|
81
|
+
'Path to files to be uploaded to S3 static bucket at app/version/ path. Do include app/version/ in path if files are already "rooted" under that path locally.',
|
|
82
|
+
}),
|
|
83
|
+
defaultFile: flagsParser.string({
|
|
84
|
+
char: 'i',
|
|
85
|
+
multiple: false,
|
|
86
|
+
required: false,
|
|
87
|
+
description:
|
|
88
|
+
'Default file to return when the app is loaded via the router without a version (e.g. when app/ is requested).',
|
|
89
|
+
}),
|
|
90
|
+
overwrite: flagsParser.boolean({
|
|
91
|
+
char: 'o',
|
|
92
|
+
required: false,
|
|
93
|
+
default: false,
|
|
94
|
+
description:
|
|
95
|
+
'Allow overwrite - Warn but do not fail if version exists. Discouraged outside of test envs if cacheable static files have changed.',
|
|
96
|
+
}),
|
|
97
|
+
noCache: flagsParser.boolean({
|
|
98
|
+
required: false,
|
|
99
|
+
default: false,
|
|
100
|
+
description: 'Force revalidation of CloudFront and browser caching of static assets',
|
|
101
|
+
}),
|
|
77
102
|
};
|
|
78
103
|
|
|
79
104
|
private VersionAndAlias: IVersions;
|
|
@@ -81,20 +106,27 @@ export class PublishCommand extends Command {
|
|
|
81
106
|
async run(): Promise<void> {
|
|
82
107
|
const config = Config.instance;
|
|
83
108
|
|
|
84
|
-
const RUNNING_TEXT = ' RUNS ';
|
|
85
|
-
const RUNNING = chalk.reset.inverse.yellow.bold(RUNNING_TEXT) + ' ';
|
|
109
|
+
// const RUNNING_TEXT = ' RUNS ';
|
|
110
|
+
// const RUNNING = chalk.reset.inverse.yellow.bold(RUNNING_TEXT) + ' ';
|
|
111
|
+
const RUNNING = ''; //chalk.reset.inverse.yellow.bold(RUNNING_TEXT) + ' ';
|
|
86
112
|
|
|
87
113
|
const { flags: parsedFlags } = this.parse(PublishCommand);
|
|
88
114
|
const appLambdaName = parsedFlags.appLambdaName ?? config.app.lambdaName;
|
|
89
115
|
const appName = parsedFlags.appName ?? config.app.name;
|
|
90
116
|
const deployerLambdaName = parsedFlags.deployerLambdaName ?? config.deployer.lambdaName;
|
|
91
117
|
const semVer = parsedFlags.newVersion ?? config.app.semVer;
|
|
118
|
+
const staticAssetsPath = parsedFlags.staticAssetsPath ?? config.app.staticAssetsPath;
|
|
119
|
+
const defaultFile = parsedFlags.defaultFile ?? config.app.defaultFile;
|
|
120
|
+
const overwrite = parsedFlags.overwrite;
|
|
121
|
+
const noCache = parsedFlags.noCache;
|
|
92
122
|
|
|
93
123
|
// Override the config value
|
|
94
124
|
config.deployer.lambdaName = deployerLambdaName;
|
|
95
125
|
config.app.lambdaName = appLambdaName;
|
|
96
126
|
config.app.name = appName;
|
|
97
127
|
config.app.semVer = semVer;
|
|
128
|
+
config.app.staticAssetsPath = staticAssetsPath;
|
|
129
|
+
config.app.defaultFile = defaultFile;
|
|
98
130
|
|
|
99
131
|
// Get the account ID and region from STS
|
|
100
132
|
// TODO: Move this to the right place
|
|
@@ -113,11 +145,8 @@ export class PublishCommand extends Command {
|
|
|
113
145
|
|
|
114
146
|
this.VersionAndAlias = createVersions(semVer);
|
|
115
147
|
|
|
116
|
-
if (config === undefined) {
|
|
117
|
-
this.error('Failed to load the config file');
|
|
118
|
-
}
|
|
119
148
|
if (config.app.staticAssetsPath === undefined) {
|
|
120
|
-
this.error('
|
|
149
|
+
this.error('staticAssetsPath must be specified');
|
|
121
150
|
}
|
|
122
151
|
|
|
123
152
|
//
|
|
@@ -137,13 +166,20 @@ export class PublishCommand extends Command {
|
|
|
137
166
|
task.output = `Checking if deployed app/version already exists for ${config.app.name}/${semVer}`;
|
|
138
167
|
ctx.preflightResult = await DeployClient.DeployVersionPreflight({
|
|
139
168
|
config,
|
|
169
|
+
overwrite,
|
|
140
170
|
output: (message: string) => (task.output = message),
|
|
141
171
|
});
|
|
142
172
|
if (ctx.preflightResult.exists) {
|
|
143
|
-
|
|
173
|
+
if (!overwrite) {
|
|
174
|
+
throw new Error(
|
|
175
|
+
`App/Version already exists: ${config.app.name}/${config.app.semVer}`,
|
|
176
|
+
);
|
|
177
|
+
} else {
|
|
178
|
+
task.title = `Warning: App/Version already exists: ${config.app.name}/${config.app.semVer}`;
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
task.title = `App/Version does not exist: ${config.app.name}/${config.app.semVer}`;
|
|
144
182
|
}
|
|
145
|
-
|
|
146
|
-
task.title = origTitle;
|
|
147
183
|
},
|
|
148
184
|
},
|
|
149
185
|
{
|
|
@@ -220,6 +256,16 @@ export class PublishCommand extends Command {
|
|
|
220
256
|
},
|
|
221
257
|
});
|
|
222
258
|
|
|
259
|
+
// Setup caching on static assets
|
|
260
|
+
// NoCache - Only used for test deploys, requires browser and CloudFront to refetch every time
|
|
261
|
+
// Overwrite - Reduces default cache time period from 24 hours to 15 minutes
|
|
262
|
+
// Default - 24 hours
|
|
263
|
+
const CacheControl = noCache
|
|
264
|
+
? 'max-age=0, must-revalidate, public'
|
|
265
|
+
: overwrite
|
|
266
|
+
? `max-age=${15 * 60}, public`
|
|
267
|
+
: `max-age=${24 * 60 * 60}, public`;
|
|
268
|
+
|
|
223
269
|
const pathWithoutAppAndVer = path.join(S3Uploader.TempDir, destinationPrefix);
|
|
224
270
|
|
|
225
271
|
const tasks: ListrTask<IContext>[] = ctx.files.map((filePath) => ({
|
|
@@ -237,7 +283,7 @@ export class PublishCommand extends Command {
|
|
|
237
283
|
Key: path.relative(S3Uploader.TempDir, filePath),
|
|
238
284
|
Body: createReadStream(filePath),
|
|
239
285
|
ContentType: contentType(path.basename(filePath)) || 'application/octet-stream',
|
|
240
|
-
CacheControl
|
|
286
|
+
CacheControl,
|
|
241
287
|
},
|
|
242
288
|
});
|
|
243
289
|
await upload.done();
|
|
@@ -265,7 +311,7 @@ export class PublishCommand extends Command {
|
|
|
265
311
|
task.title = RUNNING + origTitle;
|
|
266
312
|
|
|
267
313
|
// Call Deployer to Create App if Not Exists
|
|
268
|
-
await DeployClient.CreateApp(config);
|
|
314
|
+
await DeployClient.CreateApp({ config });
|
|
269
315
|
|
|
270
316
|
task.title = origTitle;
|
|
271
317
|
},
|
|
@@ -277,7 +323,12 @@ export class PublishCommand extends Command {
|
|
|
277
323
|
task.title = RUNNING + origTitle;
|
|
278
324
|
|
|
279
325
|
// Call Deployer to Deploy AppName/Version
|
|
280
|
-
await DeployClient.DeployVersion(
|
|
326
|
+
await DeployClient.DeployVersion({
|
|
327
|
+
config,
|
|
328
|
+
appType: 'lambda',
|
|
329
|
+
overwrite,
|
|
330
|
+
output: (message: string) => (task.output = message),
|
|
331
|
+
});
|
|
281
332
|
|
|
282
333
|
task.title = origTitle;
|
|
283
334
|
},
|
|
@@ -292,9 +343,6 @@ export class PublishCommand extends Command {
|
|
|
292
343
|
|
|
293
344
|
try {
|
|
294
345
|
await tasks.run();
|
|
295
|
-
// this.log(`Published: ${config.app.name}/${config.app.semVer}`);
|
|
296
|
-
} catch (error) {
|
|
297
|
-
this.log(`Caught exception: ${error.message}`);
|
|
298
346
|
} finally {
|
|
299
347
|
await S3Uploader.removeTempDirIfExists();
|
|
300
348
|
}
|
package/src/lib/DeployClient.ts
CHANGED
|
@@ -19,7 +19,8 @@ export default class DeployClient {
|
|
|
19
19
|
});
|
|
20
20
|
static readonly _decoder = new TextDecoder('utf-8');
|
|
21
21
|
|
|
22
|
-
public static async CreateApp(config: IConfig): Promise<void> {
|
|
22
|
+
public static async CreateApp(opts: { config: IConfig }): Promise<void> {
|
|
23
|
+
const { config } = opts;
|
|
23
24
|
const request = {
|
|
24
25
|
type: 'createApp',
|
|
25
26
|
appName: config.app.name,
|
|
@@ -54,14 +55,16 @@ export default class DeployClient {
|
|
|
54
55
|
public static async DeployVersionPreflight(opts: {
|
|
55
56
|
config: IConfig;
|
|
56
57
|
needS3Creds?: boolean;
|
|
58
|
+
overwrite: boolean;
|
|
57
59
|
output: (message: string) => void;
|
|
58
60
|
}): Promise<IDeployVersionPreflightResult> {
|
|
59
|
-
const { config, needS3Creds = true, output } = opts;
|
|
61
|
+
const { config, needS3Creds = true, overwrite, output } = opts;
|
|
60
62
|
|
|
61
63
|
const request = {
|
|
62
64
|
type: 'deployVersionPreflight',
|
|
63
65
|
appName: config.app.name,
|
|
64
66
|
semVer: config.app.semVer,
|
|
67
|
+
overwrite,
|
|
65
68
|
needS3Creds,
|
|
66
69
|
} as IDeployVersionPreflightRequest;
|
|
67
70
|
const response = await this._client.send(
|
|
@@ -95,16 +98,21 @@ export default class DeployClient {
|
|
|
95
98
|
* @param config
|
|
96
99
|
* @param task
|
|
97
100
|
*/
|
|
98
|
-
public static async DeployVersion(
|
|
99
|
-
config: IConfig
|
|
100
|
-
|
|
101
|
-
|
|
101
|
+
public static async DeployVersion(opts: {
|
|
102
|
+
config: IConfig;
|
|
103
|
+
appType: 'lambda' | 'static';
|
|
104
|
+
overwrite: boolean;
|
|
105
|
+
output: (message: string) => void;
|
|
106
|
+
}): Promise<void> {
|
|
107
|
+
const { config, appType, overwrite, output } = opts;
|
|
102
108
|
const request = {
|
|
103
109
|
type: 'deployVersion',
|
|
110
|
+
appType,
|
|
104
111
|
appName: config.app.name,
|
|
105
112
|
semVer: config.app.semVer,
|
|
106
113
|
defaultFile: config.app.defaultFile,
|
|
107
|
-
lambdaARN: config.app.lambdaARN,
|
|
114
|
+
lambdaARN: appType === 'lambda' ? config.app.lambdaARN : undefined,
|
|
115
|
+
overwrite,
|
|
108
116
|
} as IDeployVersionRequest;
|
|
109
117
|
const response = await this._client.send(
|
|
110
118
|
new lambda.InvokeCommand({
|