@pwrdrvr/microapps-publish 0.0.20 → 0.0.21

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.
Files changed (68) hide show
  1. package/bin/run +5 -0
  2. package/dist/commands/nextjs-docker-auto.d.ts +38 -0
  3. package/dist/commands/nextjs-docker-auto.d.ts.map +1 -0
  4. package/dist/commands/nextjs-docker-auto.js +415 -0
  5. package/dist/commands/nextjs-docker-auto.js.map +1 -0
  6. package/dist/commands/nextjs-version-restore.d.ts +14 -0
  7. package/dist/commands/nextjs-version-restore.d.ts.map +1 -0
  8. package/dist/commands/nextjs-version-restore.js +58 -0
  9. package/dist/commands/nextjs-version-restore.js.map +1 -0
  10. package/dist/commands/nextjs-version.d.ts +16 -0
  11. package/dist/commands/nextjs-version.d.ts.map +1 -0
  12. package/dist/commands/nextjs-version.js +94 -0
  13. package/dist/commands/nextjs-version.js.map +1 -0
  14. package/dist/commands/preflight.d.ts +15 -0
  15. package/dist/commands/preflight.d.ts.map +1 -0
  16. package/dist/commands/preflight.js +111 -0
  17. package/dist/commands/preflight.js.map +1 -0
  18. package/dist/commands/publish.d.ts +23 -0
  19. package/dist/commands/publish.d.ts.map +1 -0
  20. package/dist/commands/publish.js +300 -0
  21. package/dist/commands/publish.js.map +1 -0
  22. package/dist/config/Config.d.ts +0 -2
  23. package/dist/config/Config.d.ts.map +1 -1
  24. package/dist/config/Config.js +0 -5
  25. package/dist/config/Config.js.map +1 -1
  26. package/dist/index.d.ts +1 -64
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +3 -480
  29. package/dist/index.js.map +1 -1
  30. package/dist/{DeployClient.d.ts → lib/DeployClient.d.ts} +14 -6
  31. package/dist/lib/DeployClient.d.ts.map +1 -0
  32. package/dist/{DeployClient.js → lib/DeployClient.js} +15 -5
  33. package/dist/lib/DeployClient.js.map +1 -0
  34. package/dist/{S3TransferUtility.d.ts → lib/S3TransferUtility.d.ts} +0 -0
  35. package/dist/lib/S3TransferUtility.d.ts.map +1 -0
  36. package/dist/{S3TransferUtility.js → lib/S3TransferUtility.js} +0 -0
  37. package/dist/lib/S3TransferUtility.js.map +1 -0
  38. package/dist/{S3Uploader.d.ts → lib/S3Uploader.d.ts} +1 -1
  39. package/dist/lib/S3Uploader.d.ts.map +1 -0
  40. package/dist/{S3Uploader.js → lib/S3Uploader.js} +10 -10
  41. package/dist/lib/S3Uploader.js.map +1 -0
  42. package/dist/lib/Versions.d.ts +27 -0
  43. package/dist/lib/Versions.d.ts.map +1 -0
  44. package/dist/lib/Versions.js +76 -0
  45. package/dist/lib/Versions.js.map +1 -0
  46. package/package.json +11 -2
  47. package/src/commands/nextjs-docker-auto.ts +498 -0
  48. package/src/commands/nextjs-version-restore.ts +73 -0
  49. package/src/commands/nextjs-version.ts +113 -0
  50. package/src/commands/preflight.ts +121 -0
  51. package/src/commands/publish.ts +358 -0
  52. package/src/config/Config.ts +0 -4
  53. package/src/index.ts +1 -596
  54. package/src/{DeployClient.ts → lib/DeployClient.ts} +21 -12
  55. package/src/{S3TransferUtility.ts → lib/S3TransferUtility.ts} +0 -0
  56. package/src/{S3Uploader.ts → lib/S3Uploader.ts} +3 -3
  57. package/src/lib/Versions.ts +95 -0
  58. package/dist/DeployClient.d.ts.map +0 -1
  59. package/dist/DeployClient.js.map +0 -1
  60. package/dist/S3TransferUtility.d.ts.map +0 -1
  61. package/dist/S3TransferUtility.js.map +0 -1
  62. package/dist/S3Uploader.d.ts.map +0 -1
  63. package/dist/S3Uploader.js.map +0 -1
  64. package/dist/config/FileStore.d.ts +0 -7
  65. package/dist/config/FileStore.d.ts.map +0 -1
  66. package/dist/config/FileStore.js +0 -17
  67. package/dist/config/FileStore.js.map +0 -1
  68. package/src/config/FileStore.ts +0 -14
package/src/index.ts CHANGED
@@ -1,596 +1 @@
1
- #!/usr/bin/env node
2
- /* eslint-disable no-console */
3
-
4
- import 'source-map-support/register';
5
- // Used by ts-convict
6
- import 'reflect-metadata';
7
- import { exec } from 'child_process';
8
- import * as util from 'util';
9
- import * as lambda from '@aws-sdk/client-lambda';
10
- import * as s3 from '@aws-sdk/client-s3';
11
- import * as sts from '@aws-sdk/client-sts';
12
- import { Command, flags as flagsParser } from '@oclif/command';
13
- import { IConfig as OCLIFIConfig } from '@oclif/config';
14
- import { handle as errorHandler } from '@oclif/errors';
15
- import chalk from 'chalk';
16
- import path from 'path';
17
- import { promises as fs, pathExists, createReadStream } from 'fs-extra';
18
- import { Listr, ListrTask } from 'listr2';
19
- import { Config, IConfig } from './config/Config';
20
- import DeployClient, { IDeployVersionPreflightResult } from './DeployClient';
21
- import S3Uploader from './S3Uploader';
22
- import S3TransferUtility from './S3TransferUtility';
23
- import { Upload } from '@aws-sdk/lib-storage';
24
- import { contentType } from 'mime-types';
25
- import { TaskWrapper } from 'listr2/dist/lib/task-wrapper';
26
- import { DefaultRenderer } from 'listr2/dist/renderer/default.renderer';
27
- const asyncSetTimeout = util.promisify(setTimeout);
28
- const asyncExec = util.promisify(exec);
29
-
30
- const RUNNING_TEXT = ' RUNS ';
31
- const RUNNING = chalk.reset.inverse.yellow.bold(RUNNING_TEXT) + ' ';
32
-
33
- const lambdaClient = new lambda.LambdaClient({
34
- maxAttempts: 8,
35
- });
36
-
37
- interface IVersions {
38
- version: string;
39
- alias?: string;
40
- }
41
-
42
- export interface IContext {
43
- preflightResult: IDeployVersionPreflightResult;
44
- files: string[];
45
- }
46
-
47
- class PublishTool extends Command {
48
- static flags = {
49
- version: flagsParser.version({
50
- char: 'v',
51
- }),
52
- help: flagsParser.help(),
53
- deployerLambdaName: flagsParser.string({
54
- char: 'd',
55
- multiple: false,
56
- required: true,
57
- description: 'Name of the deployer lambda function',
58
- }),
59
- newVersion: flagsParser.string({
60
- char: 'n',
61
- multiple: false,
62
- required: true,
63
- description: 'New semantic version to apply',
64
- }),
65
- repoName: flagsParser.string({
66
- char: 'r',
67
- multiple: false,
68
- required: true,
69
- description: 'Name (not URI) of the Docker repo for the app',
70
- }),
71
- leaveCopy: flagsParser.boolean({
72
- char: 'l',
73
- default: false,
74
- required: false,
75
- description: 'Leave a copy of the modifed files as .modified',
76
- }),
77
- };
78
-
79
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
80
- private static escapeRegExp(value: string): string {
81
- return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
82
- }
83
-
84
- private VersionAndAlias: IVersions;
85
- private IMAGE_TAG = '';
86
- private IMAGE_URI = '';
87
- private FILES_TO_MODIFY: {
88
- path: string;
89
- versions: IVersions;
90
- }[];
91
- private _restoreFilesStarted = false;
92
-
93
- constructor(argv: string[], config: OCLIFIConfig) {
94
- super(argv, config);
95
- this.restoreFiles = this.restoreFiles.bind(this);
96
- }
97
-
98
- async run(): Promise<void> {
99
- const { flags: parsedFlags } = this.parse(PublishTool);
100
- const version = parsedFlags.newVersion;
101
- const leaveFiles = parsedFlags.leaveCopy;
102
- const lambdaName = parsedFlags.deployerLambdaName;
103
- const ecrRepo = parsedFlags.repoName;
104
-
105
- // Override the config value
106
- const config = Config.instance;
107
- config.deployer.lambdaName = lambdaName;
108
- config.app.semVer = version;
109
-
110
- // Get the account ID and region from STS
111
- // TODO: Move this to the right place
112
- if (config.app.awsAccountID === 0 || config.app.awsRegion === '') {
113
- const stsClient = new sts.STSClient({
114
- maxAttempts: 8,
115
- });
116
- const stsResponse = await stsClient.send(new sts.GetCallerIdentityCommand({}));
117
- if (config.app.awsAccountID === 0) {
118
- config.app.awsAccountID = parseInt(stsResponse.Account, 10);
119
- }
120
- if (config.app.awsRegion === '') {
121
- config.app.awsRegion = stsClient.config.region as string;
122
- }
123
- }
124
- if (config.app.ecrHost === '') {
125
- config.app.ecrHost = `${config.app.awsAccountID}.dkr.ecr.${config.app.awsRegion}.amazonaws.com`;
126
- }
127
- if (ecrRepo) {
128
- config.app.ecrRepoName = ecrRepo;
129
- } else if (config.app.ecrRepoName === '') {
130
- config.app.ecrRepoName = `microapps-app-${config.app.name}${Config.envLevel}-repo`;
131
- }
132
-
133
- this.VersionAndAlias = this.createVersions(version);
134
- const versionOnly = { version: this.VersionAndAlias.version };
135
-
136
- this.FILES_TO_MODIFY = [
137
- { path: 'package.json', versions: versionOnly },
138
- // { path: 'deploy.json', versions: this.VersionAndAlias },
139
- { path: 'next.config.js', versions: versionOnly },
140
- ] as { path: string; versions: IVersions }[];
141
-
142
- // Install handler to ensure that we restore files
143
- // eslint-disable-next-line @typescript-eslint/no-misused-promises
144
- process.on('SIGINT', async () => {
145
- if (this._restoreFilesStarted) {
146
- return;
147
- } else {
148
- this._restoreFilesStarted = true;
149
- }
150
- this.log('Caught Ctrl-C, restoring files');
151
- await S3Uploader.removeTempDirIfExists();
152
- await this.restoreFiles();
153
- });
154
-
155
- if (config === undefined) {
156
- this.error('Failed to load the config file');
157
- }
158
- if (config.app.staticAssetsPath === undefined) {
159
- this.error('StaticAssetsPath must be specified in the config file');
160
- }
161
-
162
- //
163
- // Setup Tasks
164
- //
165
-
166
- const tasks = new Listr<IContext>(
167
- [
168
- {
169
- title: 'Logging into ECR',
170
- task: async (ctx, task) => {
171
- const origTitle = task.title;
172
- task.title = RUNNING + origTitle;
173
-
174
- await this.loginToECR(config);
175
-
176
- task.title = origTitle;
177
- },
178
- },
179
- {
180
- title: 'Modifying Config Files',
181
- task: async (ctx, task) => {
182
- const origTitle = task.title;
183
- task.title = RUNNING + origTitle;
184
-
185
- // Modify the existing files with the new version
186
- for (const fileToModify of this.FILES_TO_MODIFY) {
187
- task.output = `Patching version (${this.VersionAndAlias.version}) into ${fileToModify.path}`;
188
- if (
189
- !(await this.writeNewVersions(fileToModify.path, fileToModify.versions, leaveFiles))
190
- ) {
191
- task.output = `Failed modifying file: ${fileToModify.path}`;
192
- }
193
- }
194
-
195
- task.title = origTitle;
196
- },
197
- },
198
- {
199
- title: 'Preflight Version Check',
200
- task: async (ctx, task) => {
201
- const origTitle = task.title;
202
- task.title = RUNNING + origTitle;
203
-
204
- // Confirm the Version Does Not Exist in Published State
205
- task.output = `Checking if deployed app/version already exists for ${config.app.name}/${version}`;
206
- ctx.preflightResult = await DeployClient.DeployVersionPreflight(config, task);
207
- if (ctx.preflightResult.exists) {
208
- task.output = `Warning: App/Version already exists: ${config.app.name}/${config.app.semVer}`;
209
- }
210
-
211
- task.title = origTitle;
212
- },
213
- },
214
- {
215
- title: 'Serverless Next.js Build',
216
- task: async (ctx, task) => {
217
- const origTitle = task.title;
218
- task.title = RUNNING + origTitle;
219
-
220
- task.output = `Invoking serverless next.js build for ${config.app.name}/${version}`;
221
-
222
- // Run the serverless next.js build
223
- await asyncExec('serverless');
224
-
225
- if (config.app.serverlessNextRouterPath !== undefined) {
226
- task.output = 'Copying Serverless Next.js router to build output directory';
227
- await fs.copyFile(
228
- config.app.serverlessNextRouterPath,
229
- './.serverless_nextjs/index.js',
230
- );
231
- }
232
-
233
- task.title = origTitle;
234
- },
235
- },
236
- {
237
- title: 'Publish to ECR',
238
- task: async (ctx: IContext, task: TaskWrapper<IContext, typeof DefaultRenderer>) => {
239
- const origTitle = task.title;
240
- task.title = RUNNING + origTitle;
241
-
242
- // Docker, build, tag, push to ECR
243
- // Note: Need to already have AWS env vars set
244
- await this.publishToECR(config, task);
245
-
246
- task.title = origTitle;
247
- },
248
- },
249
- {
250
- title: 'Deploy to Lambda',
251
- task: async (ctx, task) => {
252
- const origTitle = task.title;
253
- task.title = RUNNING + origTitle;
254
-
255
- // Update the Lambda function
256
- await this.deployToLambda(config, this.VersionAndAlias, task);
257
-
258
- task.title = origTitle;
259
- },
260
- },
261
- {
262
- title: 'Confirm Static Assets Folder Exists',
263
- task: async (ctx, task) => {
264
- const origTitle = task.title;
265
- task.title = RUNNING + origTitle;
266
-
267
- // Check that Static Assets Folder exists
268
- if (!(await pathExists(config.app.staticAssetsPath))) {
269
- this.error(`Static asset path does not exist: ${config.app.staticAssetsPath}`);
270
- }
271
-
272
- task.title = origTitle;
273
- },
274
- },
275
- {
276
- title: 'Copy Static Files to Local Upload Dir',
277
- task: async (ctx, task) => {
278
- const origTitle = task.title;
279
- task.title = RUNNING + origTitle;
280
-
281
- // Copy files to local dir to be uploaded
282
- await S3Uploader.CopyToUploadDir(config, ctx.preflightResult.response.s3UploadUrl);
283
-
284
- task.title = origTitle;
285
- },
286
- },
287
- // {
288
- // title: 'Upload Files to S3 Staging AppName/Version Prefix',
289
- // task: async (ctx, task) => {
290
- // const origTitle = task.title;
291
- // task.title = RUNNING + origTitle;
292
-
293
- // const { destinationPrefix, bucketName } = S3Uploader.ParseUploadPath(
294
- // ctx.preflightResult.response.s3UploadUrl,
295
- // );
296
-
297
- // // Upload Files to S3 Staging AppName/Version Prefix
298
- // await S3TransferUtility.UploadDir(
299
- // S3Uploader.TempDir,
300
- // destinationPrefix,
301
- // bucketName,
302
- // ctx.preflightResult.response,
303
- // );
304
-
305
- // task.title = origTitle;
306
- // },
307
- // },
308
- {
309
- title: 'Enumerate Files to Upload to S3',
310
- task: async (ctx, task) => {
311
- const origTitle = task.title;
312
- task.title = RUNNING + origTitle;
313
-
314
- ctx.files = (await S3TransferUtility.GetFiles(S3Uploader.TempDir)) as string[];
315
-
316
- task.title = origTitle;
317
- },
318
- },
319
- {
320
- title: 'Upload Static Files to S3',
321
- task: (ctx, task) => {
322
- const origTitle = task.title;
323
- task.title = RUNNING + origTitle;
324
-
325
- const { bucketName, destinationPrefix } = S3Uploader.ParseUploadPath(
326
- ctx.preflightResult.response.s3UploadUrl,
327
- );
328
-
329
- // Use temp credentials for S3
330
- const s3Client = new s3.S3Client({
331
- maxAttempts: 16,
332
- credentials: {
333
- accessKeyId: ctx.preflightResult.response.awsCredentials.accessKeyId,
334
- secretAccessKey: ctx.preflightResult.response.awsCredentials.secretAccessKey,
335
- sessionToken: ctx.preflightResult.response.awsCredentials.sessionToken,
336
- },
337
- });
338
-
339
- const pathWithoutAppAndVer = path.join(S3Uploader.TempDir, destinationPrefix);
340
-
341
- const tasks: ListrTask<IContext>[] = ctx.files.map((filePath) => ({
342
- task: async (ctx: IContext, subtask) => {
343
- const relFilePath = path.relative(pathWithoutAppAndVer, filePath);
344
-
345
- const origTitle = relFilePath;
346
- subtask.title = RUNNING + origTitle;
347
-
348
- const upload = new Upload({
349
- client: s3Client,
350
- leavePartsOnError: false,
351
- params: {
352
- Bucket: bucketName,
353
- Key: path.relative(S3Uploader.TempDir, filePath),
354
- Body: createReadStream(filePath),
355
- ContentType: contentType(path.basename(filePath)) || 'application/octet-stream',
356
- CacheControl: 'max-age=86400; public',
357
- },
358
- });
359
- await upload.done();
360
-
361
- subtask.title = origTitle;
362
- },
363
- }));
364
-
365
- task.title = origTitle;
366
-
367
- return task.newListr(tasks, {
368
- concurrent: 8,
369
- rendererOptions: {
370
- clearOutput: false,
371
- showErrorMessage: true,
372
- showTimer: true,
373
- },
374
- });
375
- },
376
- },
377
- {
378
- title: `Creating MicroApp Application: ${config.app.name}`,
379
- task: async (ctx, task) => {
380
- const origTitle = task.title;
381
- task.title = RUNNING + origTitle;
382
-
383
- // Call Deployer to Create App if Not Exists
384
- await DeployClient.CreateApp(config);
385
-
386
- task.title = origTitle;
387
- },
388
- },
389
- {
390
- title: `Creating MicroApp Version: ${config.app.semVer}`,
391
- task: async (ctx, task) => {
392
- const origTitle = task.title;
393
- task.title = RUNNING + origTitle;
394
-
395
- // Call Deployer to Deploy AppName/Version
396
- await DeployClient.DeployVersion(config, task);
397
-
398
- task.title = origTitle;
399
- },
400
- },
401
- ],
402
- {
403
- rendererOptions: {
404
- showTimer: true,
405
- },
406
- },
407
- );
408
-
409
- try {
410
- await tasks.run();
411
- // this.log(`Published: ${config.app.name}/${config.app.semVer}`);
412
- } catch (error) {
413
- this.log(`Caught exception: ${error.message}`);
414
- } finally {
415
- await S3Uploader.removeTempDirIfExists();
416
- await this.restoreFiles();
417
- }
418
- }
419
-
420
- /**
421
- * Restore files that the version was patched into
422
- */
423
- private async restoreFiles(): Promise<void> {
424
- // Put the old files back when succeeded or failed
425
- for (const fileToModify of this.FILES_TO_MODIFY) {
426
- try {
427
- const stats = await fs.stat(`${fileToModify.path}.original`);
428
- if (stats.isFile()) {
429
- // Remove the possibly modified file
430
- await fs.unlink(fileToModify.path);
431
-
432
- // Move the original file back
433
- await fs.rename(`${fileToModify.path}.original`, fileToModify.path);
434
- }
435
- } catch {
436
- // don't care... if the file doesn't exist we can't do anything
437
- }
438
- }
439
- }
440
-
441
- /**
442
- * Setup version and alias strings
443
- * @param version
444
- * @returns
445
- */
446
- private createVersions(version: string): IVersions {
447
- return { version, alias: `v${version.replace(/\./g, '_')}` };
448
- }
449
-
450
- /**
451
- * Write new versions into specified config files
452
- * @param path
453
- * @param requiredVersions
454
- * @param leaveFiles
455
- * @returns
456
- */
457
- private async writeNewVersions(
458
- path: string,
459
- requiredVersions: IVersions,
460
- leaveFiles: boolean,
461
- ): Promise<boolean> {
462
- const stats = await fs.stat(path);
463
- if (!stats.isFile) {
464
- return false;
465
- }
466
-
467
- // Make a backup of the file
468
- await fs.copyFile(path, `${path}.original`);
469
-
470
- // File exists, check that it has the required version strings
471
- let fileText = await fs.readFile(path, 'utf8');
472
-
473
- for (const key of Object.keys(requiredVersions)) {
474
- const placeHolder = key === 'version' ? '0.0.0' : 'v0_0_0';
475
- if (fileText.indexOf(placeHolder) === -1) {
476
- // The required placeholder is missing
477
- return false;
478
- } else {
479
- const regExp = new RegExp(PublishTool.escapeRegExp(placeHolder), 'g');
480
- fileText = fileText.replace(
481
- regExp,
482
- key === 'version' ? requiredVersions.version : (requiredVersions.alias as string),
483
- );
484
- }
485
- }
486
-
487
- // Write the updated file contents
488
- await fs.writeFile(path, fileText, 'utf8');
489
-
490
- // Leave a copy of the modified file if requested
491
- if (leaveFiles) {
492
- // This copy will overwrite an existing file
493
- await fs.copyFile(path, `${path}.modified`);
494
- }
495
-
496
- return true;
497
- }
498
-
499
- /**
500
- * Login to ECR for Lambda Docker functions
501
- * @param config
502
- * @returns
503
- */
504
- private async loginToECR(config: IConfig): Promise<boolean> {
505
- this.IMAGE_TAG = `${config.app.ecrRepoName}:${this.VersionAndAlias.version}`;
506
- this.IMAGE_URI = `${config.app.ecrHost}/${this.IMAGE_TAG}`;
507
-
508
- try {
509
- await asyncExec(
510
- `aws ecr get-login-password --region ${config.app.awsRegion} | docker login --username AWS --password-stdin ${config.app.ecrHost}`,
511
- );
512
- } catch (error) {
513
- throw new Error(`ECR Login Failed: ${error.message}`);
514
- }
515
-
516
- return true;
517
- }
518
-
519
- /**
520
- * Publish to ECR for Lambda Docker function
521
- * @param config
522
- */
523
- private async publishToECR(
524
- config: IConfig,
525
- task: TaskWrapper<IContext, typeof DefaultRenderer>,
526
- ): Promise<void> {
527
- task.output = 'Starting Docker build';
528
- await asyncExec(`docker build -f Dockerfile -t ${this.IMAGE_TAG} .`);
529
- await asyncExec(`docker tag ${this.IMAGE_TAG} ${config.app.ecrHost}/${this.IMAGE_TAG}`);
530
- task.output = 'Starting Docker push to ECR';
531
- await asyncExec(`docker push ${config.app.ecrHost}/${this.IMAGE_TAG}`);
532
- }
533
-
534
- /**
535
- * Publish an app version to Lambda
536
- * @param config
537
- * @param versions
538
- */
539
- private async deployToLambda(
540
- config: IConfig,
541
- versions: IVersions,
542
- task: TaskWrapper<IContext, typeof DefaultRenderer>,
543
- ): Promise<void> {
544
- // Create Lambda version
545
- task.output = 'Updating Lambda code to point to new Docker image';
546
- const resultUpdate = await lambdaClient.send(
547
- new lambda.UpdateFunctionCodeCommand({
548
- FunctionName: config.app.lambdaName,
549
- ImageUri: this.IMAGE_URI,
550
- Publish: true,
551
- }),
552
- );
553
- const lambdaVersion = resultUpdate.Version;
554
- task.output = `Lambda version created: ${resultUpdate.Version}`;
555
-
556
- let lastUpdateStatus = resultUpdate.LastUpdateStatus;
557
- for (let i = 0; i < 5; i++) {
558
- // When the function is created the status will be "Pending"
559
- // and we have to wait until it's done creating
560
- // before we can point an alias to it
561
- if (lastUpdateStatus === 'Successful') {
562
- task.output = `Lambda function updated, version: ${lambdaVersion}`;
563
- break;
564
- }
565
-
566
- // If it didn't work, wait and try again
567
- await asyncSetTimeout(1000 * i);
568
-
569
- const resultGet = await lambdaClient.send(
570
- new lambda.GetFunctionCommand({
571
- FunctionName: config.app.lambdaName,
572
- Qualifier: lambdaVersion,
573
- }),
574
- );
575
-
576
- // Save the last update status so we can check on re-loop
577
- lastUpdateStatus = resultGet?.Configuration?.LastUpdateStatus;
578
- }
579
-
580
- // Create Lambda alias point
581
- task.output = `Creating the lambda alias for the new version: ${lambdaVersion}`;
582
- const resultLambdaAlias = await lambdaClient.send(
583
- new lambda.CreateAliasCommand({
584
- FunctionName: config.app.lambdaName,
585
- Name: versions.alias,
586
- FunctionVersion: lambdaVersion,
587
- }),
588
- );
589
- task.output = `Lambda alias created, name: ${resultLambdaAlias.Name}`;
590
- }
591
- }
592
-
593
- // @ts-expect-error catch is actually defined
594
- PublishTool.run().catch(errorHandler);
595
-
596
- export default PublishTool;
1
+ export { run } from '@oclif/command';
@@ -1,6 +1,4 @@
1
1
  import * as lambda from '@aws-sdk/client-lambda';
2
- import { TaskWrapper } from 'listr2/dist/lib/task-wrapper';
3
- import { DefaultRenderer } from 'listr2/dist/renderer/default.renderer';
4
2
  import {
5
3
  IDeployVersionPreflightRequest,
6
4
  IDeployVersionPreflightResponse,
@@ -8,8 +6,7 @@ import {
8
6
  IDeployerResponse,
9
7
  IDeployVersionRequest,
10
8
  } from '@pwrdrvr/microapps-deployer-lib';
11
- import { IConfig } from './config/Config';
12
- import { IContext } from './index';
9
+ import { IConfig } from '../config/Config';
13
10
 
14
11
  export interface IDeployVersionPreflightResult {
15
12
  exists: boolean;
@@ -47,14 +44,25 @@ export default class DeployClient {
47
44
  }
48
45
  }
49
46
 
50
- public static async DeployVersionPreflight(
51
- config: IConfig,
52
- task: TaskWrapper<IContext, typeof DefaultRenderer>,
53
- ): Promise<IDeployVersionPreflightResult> {
47
+ /**
48
+ * Check if version exists.
49
+ * Optionally get S3 creds for static asset upload.
50
+ * @param config
51
+ * @param output
52
+ * @returns
53
+ */
54
+ public static async DeployVersionPreflight(opts: {
55
+ config: IConfig;
56
+ needS3Creds?: boolean;
57
+ output: (message: string) => void;
58
+ }): Promise<IDeployVersionPreflightResult> {
59
+ const { config, needS3Creds = true, output } = opts;
60
+
54
61
  const request = {
55
62
  type: 'deployVersionPreflight',
56
63
  appName: config.app.name,
57
64
  semVer: config.app.semVer,
65
+ needS3Creds,
58
66
  } as IDeployVersionPreflightRequest;
59
67
  const response = await this._client.send(
60
68
  new lambda.InvokeCommand({
@@ -68,9 +76,10 @@ export default class DeployClient {
68
76
  Buffer.from(response.Payload).toString('utf-8'),
69
77
  ) as IDeployVersionPreflightResponse;
70
78
  if (dResponse.statusCode === 404) {
71
- task.output = `App/Version do not exist: ${config.app.name}/${config.app.semVer}`;
79
+ output(`App/Version does not exist: ${config.app.name}/${config.app.semVer}`);
72
80
  return { exists: false, response: dResponse };
73
81
  } else {
82
+ output(`App/Version exists: ${config.app.name}/${config.app.semVer}`);
74
83
  return { exists: true, response: dResponse };
75
84
  }
76
85
  } else {
@@ -88,7 +97,7 @@ export default class DeployClient {
88
97
  */
89
98
  public static async DeployVersion(
90
99
  config: IConfig,
91
- task: TaskWrapper<IContext, typeof DefaultRenderer>,
100
+ output: (message: string) => void,
92
101
  ): Promise<void> {
93
102
  const request = {
94
103
  type: 'deployVersion',
@@ -109,9 +118,9 @@ export default class DeployClient {
109
118
  Buffer.from(response.Payload).toString('utf-8'),
110
119
  ) as IDeployerResponse;
111
120
  if (dResponse.statusCode === 201) {
112
- task.output = `Deploy succeeded: ${config.app.name}/${config.app.semVer}`;
121
+ output(`Deploy succeeded: ${config.app.name}/${config.app.semVer}`);
113
122
  } else {
114
- task.output = `Deploy failed with: ${dResponse.statusCode}`;
123
+ output(`Deploy failed with: ${dResponse.statusCode}`);
115
124
  throw new Error(`Lambda call to DeployVersionfailed with: ${dResponse.statusCode}`);
116
125
  }
117
126
  } else {
@@ -1,7 +1,7 @@
1
- import path from 'path';
1
+ import * as path from 'path';
2
2
  import { IDeployVersionPreflightResponse } from '@pwrdrvr/microapps-deployer-lib';
3
- import fs from 'fs-extra';
4
- import { IConfig } from './config/Config';
3
+ import * as fs from 'fs-extra';
4
+ import { IConfig } from '../config/Config';
5
5
  import S3TransferUtility from './S3TransferUtility';
6
6
 
7
7
  export default class S3Uploader {