carlin 1.31.11 → 1.31.13

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 (74) hide show
  1. package/dist/index.js +4477 -4
  2. package/package.json +10 -10
  3. package/dist/cli.js +0 -246
  4. package/dist/config.js +0 -11
  5. package/dist/deploy/addDefaults.cloudformation.js +0 -151
  6. package/dist/deploy/baseStack/command.js +0 -9
  7. package/dist/deploy/baseStack/config.js +0 -30
  8. package/dist/deploy/baseStack/deployBaseStack.js +0 -62
  9. package/dist/deploy/baseStack/getBaseStackResource.js +0 -27
  10. package/dist/deploy/baseStack/getBucketTemplate.js +0 -46
  11. package/dist/deploy/baseStack/getLambdaImageBuilderTemplate.js +0 -188
  12. package/dist/deploy/baseStack/getLambdaLayerBuilderTemplate.js +0 -142
  13. package/dist/deploy/baseStack/getVpcTemplate.js +0 -169
  14. package/dist/deploy/cicd/cicd.template.js +0 -938
  15. package/dist/deploy/cicd/command.js +0 -31
  16. package/dist/deploy/cicd/command.options.js +0 -79
  17. package/dist/deploy/cicd/config.js +0 -8
  18. package/dist/deploy/cicd/deployCicd.js +0 -121
  19. package/dist/deploy/cicd/ecsTaskReportCommand.js +0 -55
  20. package/dist/deploy/cicd/getCicdStackName.js +0 -11
  21. package/dist/deploy/cicd/getTriggerPipelineObjectKey.js +0 -11
  22. package/dist/deploy/cicd/lambdas/cicdApiV1.handler.js +0 -124
  23. package/dist/deploy/cicd/lambdas/ecsTaskReport.handler.js +0 -126
  24. package/dist/deploy/cicd/lambdas/executeTasks.js +0 -67
  25. package/dist/deploy/cicd/lambdas/getProcessEnvVariable.js +0 -10
  26. package/dist/deploy/cicd/lambdas/githubWebhooksApiV1.handler.js +0 -148
  27. package/dist/deploy/cicd/lambdas/imageUpdaterSchedule.handler.js +0 -44
  28. package/dist/deploy/cicd/lambdas/index.js +0 -13
  29. package/dist/deploy/cicd/lambdas/pipelines.handler.js +0 -160
  30. package/dist/deploy/cicd/lambdas/putApprovalResultManualTask.js +0 -51
  31. package/dist/deploy/cicd/lambdas/shConditionalCommands.js +0 -30
  32. package/dist/deploy/cicd/pipelines.js +0 -86
  33. package/dist/deploy/cicd/readSSHKey.js +0 -34
  34. package/dist/deploy/cloudformation.core.js +0 -379
  35. package/dist/deploy/cloudformation.js +0 -189
  36. package/dist/deploy/command.js +0 -205
  37. package/dist/deploy/lambda/buildLambdaSingleFile.js +0 -67
  38. package/dist/deploy/lambda/deployLambdaCode.js +0 -43
  39. package/dist/deploy/lambda/deployLambdaLayers.js +0 -36
  40. package/dist/deploy/lambda/uploadCodeToECR.js +0 -53
  41. package/dist/deploy/lambda/uploadCodeToS3.js +0 -33
  42. package/dist/deploy/lambdaLayer/command.js +0 -50
  43. package/dist/deploy/lambdaLayer/deployLambdaLayer.js +0 -139
  44. package/dist/deploy/lambdaLayer/getPackageLambdaLayerStackName.js +0 -21
  45. package/dist/deploy/readDockerfile.js +0 -40
  46. package/dist/deploy/s3.js +0 -210
  47. package/dist/deploy/stackName.js +0 -85
  48. package/dist/deploy/staticApp/command.js +0 -86
  49. package/dist/deploy/staticApp/deployStaticApp.js +0 -65
  50. package/dist/deploy/staticApp/findDefaultBuildFolder.js +0 -44
  51. package/dist/deploy/staticApp/getStaticAppBucket.js +0 -19
  52. package/dist/deploy/staticApp/invalidateCloudFront.js +0 -44
  53. package/dist/deploy/staticApp/removeOldVersions.js +0 -56
  54. package/dist/deploy/staticApp/staticApp.template.js +0 -371
  55. package/dist/deploy/staticApp/uploadBuiltAppToS3.js +0 -28
  56. package/dist/deploy/utils.js +0 -31
  57. package/dist/deploy/vercel/command.js +0 -31
  58. package/dist/deploy/vercel/deployVercel.js +0 -59
  59. package/dist/generateEnv/generateEnv.js +0 -64
  60. package/dist/generateEnv/generateEnvCommand.js +0 -29
  61. package/dist/utils/addGroupToOptions.js +0 -11
  62. package/dist/utils/cloudFormationTemplate.js +0 -142
  63. package/dist/utils/codeBuild.js +0 -52
  64. package/dist/utils/environmentVariables.js +0 -16
  65. package/dist/utils/exec.js +0 -26
  66. package/dist/utils/formatCode.js +0 -34
  67. package/dist/utils/getAwsAccountId.js +0 -10
  68. package/dist/utils/getCurrentBranch.js +0 -35
  69. package/dist/utils/getEnvironment.js +0 -8
  70. package/dist/utils/getIamPath.js +0 -6
  71. package/dist/utils/getProjectName.js +0 -35
  72. package/dist/utils/index.js +0 -31
  73. package/dist/utils/packageJson.js +0 -32
  74. package/dist/utils/spawn.js +0 -34
@@ -1,40 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.readDockerfile = void 0;
27
- const fs = __importStar(require("fs"));
28
- const path = __importStar(require("path"));
29
- /**
30
- * This method was created because fs.readFileSync cannot be mocked.
31
- */
32
- const readDockerfile = (dockerfilePath) => {
33
- try {
34
- return fs.readFileSync(path.join(process.cwd(), dockerfilePath), 'utf8');
35
- }
36
- catch {
37
- return '';
38
- }
39
- };
40
- exports.readDockerfile = readDockerfile;
package/dist/deploy/s3.js DELETED
@@ -1,210 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.deleteS3Directory = exports.emptyS3Directory = exports.uploadDirectoryToS3 = exports.copyRoot404To404Index = exports.getAllFilesInsideADirectory = exports.uploadFileToS3 = exports.getBucketKeyUrl = exports.s3 = void 0;
7
- /* eslint-disable no-restricted-syntax */
8
- /* eslint-disable no-await-in-loop */
9
- const aws_sdk_1 = require("aws-sdk");
10
- const glob_1 = require("glob");
11
- const fs_1 = __importDefault(require("fs"));
12
- const npmlog_1 = __importDefault(require("npmlog"));
13
- const mime_types_1 = __importDefault(require("mime-types"));
14
- const path_1 = __importDefault(require("path"));
15
- const logPrefix = 's3';
16
- exports.s3 = new aws_sdk_1.S3({ apiVersion: '2006-03-01' });
17
- const getBucketKeyUrl = ({ bucket, key, }) => {
18
- return `https://s3.amazonaws.com/${bucket}/${key}`;
19
- };
20
- exports.getBucketKeyUrl = getBucketKeyUrl;
21
- const uploadFileToS3 = async ({ bucket, contentType, file, filePath, key, }) => {
22
- if (!file && !filePath) {
23
- throw new Error('file or filePath must be defined');
24
- }
25
- let params = {
26
- Bucket: bucket,
27
- Key: key.split(path_1.default.sep).join('/'),
28
- };
29
- if (file) {
30
- params.ContentType = contentType;
31
- params.Body = file;
32
- }
33
- else if (filePath) {
34
- const readFile = await fs_1.default.promises.readFile(filePath);
35
- params = {
36
- ...params,
37
- ContentType: contentType || mime_types_1.default.contentType(path_1.default.extname(filePath)) || undefined,
38
- };
39
- params.Body = Buffer.from(readFile);
40
- }
41
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
- const { Bucket, Key, VersionId } = (await exports.s3.upload(params).promise());
43
- return {
44
- bucket: Bucket,
45
- key: Key,
46
- versionId: VersionId,
47
- url: (0, exports.getBucketKeyUrl)({ bucket: Bucket, key: Key }),
48
- };
49
- };
50
- exports.uploadFileToS3 = uploadFileToS3;
51
- /**
52
- * Get all files inside $directory.
53
- */
54
- const getAllFilesInsideADirectory = async ({ directory, }) => {
55
- const allFilesAndDirectories = await (0, glob_1.glob)(`${directory}/**/*`);
56
- const allFiles = allFilesAndDirectories
57
- /**
58
- * Remove directories.
59
- */
60
- .filter((item) => {
61
- return fs_1.default.lstatSync(item).isFile();
62
- });
63
- return allFiles;
64
- };
65
- exports.getAllFilesInsideADirectory = getAllFilesInsideADirectory;
66
- /**
67
- * Docusaurus 2 has a 404.html file in the root of the build folder. This
68
- * function copies it to 404/index.html so that it can be served by S3 and
69
- * CloudFront.
70
- */
71
- const copyRoot404To404Index = async ({ bucket }) => {
72
- try {
73
- const root404Exists = await exports.s3
74
- .headObject({
75
- Bucket: bucket,
76
- Key: '404.html',
77
- })
78
- .promise()
79
- .catch(() => {
80
- /**
81
- * If the file does not exist, return false.
82
- */
83
- return false;
84
- });
85
- if (root404Exists) {
86
- await exports.s3
87
- .copyObject({
88
- Bucket: bucket,
89
- CopySource: `${bucket}/404.html`,
90
- Key: '404/index.html',
91
- })
92
- .promise();
93
- }
94
- }
95
- catch (err) {
96
- npmlog_1.default.error(logPrefix, `Cannot copy 404.html to 404/index.html`);
97
- throw err;
98
- }
99
- };
100
- exports.copyRoot404To404Index = copyRoot404To404Index;
101
- const uploadDirectoryToS3 = async ({ bucket, bucketKey = '', directory, }) => {
102
- npmlog_1.default.info(logPrefix, `Uploading directory ${directory}/ to ${bucket}/${bucketKey}...`);
103
- const allFiles = await (0, exports.getAllFilesInsideADirectory)({ directory });
104
- /**
105
- * If the folder has no files (the folder name may be wrong), thrown an
106
- * error. Discovered at #16 https://github.com/ttoss/carlin/issues/16.
107
- */
108
- if (allFiles.length === 0) {
109
- throw new Error(`Directory ${directory}/ has no files.`);
110
- }
111
- const GROUP_MAX_LENGTH = 63;
112
- const numberOfGroups = Math.ceil(allFiles.length / GROUP_MAX_LENGTH);
113
- /**
114
- * Divide all files and create "numberOfGroups" groups of files whose max
115
- * length is GROUP_MAX_LENGTH.
116
- */
117
- // eslint-disable-next-line max-params
118
- const aoaOfFiles = allFiles.reduce((acc, file, index) => {
119
- const groupIndex = index % numberOfGroups;
120
- if (!acc[groupIndex]) {
121
- acc[groupIndex] = [];
122
- }
123
- acc[index % numberOfGroups].push(file);
124
- return acc;
125
- }, []);
126
- for (const [index, groupOfFiles] of aoaOfFiles.entries()) {
127
- npmlog_1.default.info(logPrefix, `Uploading group ${index + 1}/${aoaOfFiles.length}...`);
128
- await Promise.all(groupOfFiles.map((file) => {
129
- return (0, exports.uploadFileToS3)({
130
- bucket,
131
- key: path_1.default.join(bucketKey, path_1.default.relative(directory, file)),
132
- filePath: file,
133
- });
134
- }));
135
- }
136
- };
137
- exports.uploadDirectoryToS3 = uploadDirectoryToS3;
138
- const emptyS3Directory = async ({ bucket, directory = '', }) => {
139
- npmlog_1.default.info(logPrefix, `${bucket}/${directory} will be empty`);
140
- try {
141
- const { Contents, IsTruncated } = await exports.s3
142
- .listObjectsV2({
143
- Bucket: bucket,
144
- Prefix: directory,
145
- })
146
- .promise();
147
- if (Contents && Contents.length > 0) {
148
- /**
149
- * Get object versions
150
- */
151
- const objectsPromises = Contents.filter(({ Key }) => {
152
- return !!Key;
153
- }).map(async ({ Key }) => {
154
- const { Versions = [] } = await exports.s3
155
- .listObjectVersions({
156
- Bucket: bucket,
157
- Prefix: Key,
158
- })
159
- .promise();
160
- return {
161
- Key: Key,
162
- Versions: Versions.map(({ VersionId }) => {
163
- return VersionId || undefined;
164
- }),
165
- };
166
- });
167
- const objects = await Promise.all(objectsPromises);
168
- const objectsWithVersionsIds = objects.reduce((acc, { Key, Versions }) => {
169
- const objectWithVersionsIds = Versions.map((VersionId) => {
170
- return {
171
- Key,
172
- VersionId,
173
- };
174
- });
175
- return [...acc, ...objectWithVersionsIds];
176
- }, []);
177
- await exports.s3
178
- .deleteObjects({
179
- Bucket: bucket,
180
- Delete: { Objects: objectsWithVersionsIds },
181
- })
182
- .promise();
183
- }
184
- /**
185
- * Truncated is files that exists but weren't listed from S3 API.
186
- */
187
- if (IsTruncated) {
188
- await (0, exports.emptyS3Directory)({ bucket, directory });
189
- }
190
- npmlog_1.default.info(logPrefix, `${bucket}/${directory} is empty.`);
191
- }
192
- catch (err) {
193
- npmlog_1.default.error(logPrefix, `Cannot empty ${bucket}/${directory}.`);
194
- throw err;
195
- }
196
- };
197
- exports.emptyS3Directory = emptyS3Directory;
198
- const deleteS3Directory = async ({ bucket, directory = '', }) => {
199
- try {
200
- npmlog_1.default.info(logPrefix, `${bucket}/${directory} is being deleted...`);
201
- await (0, exports.emptyS3Directory)({ bucket, directory });
202
- await exports.s3.deleteObject({ Bucket: bucket, Key: directory }).promise();
203
- npmlog_1.default.info(logPrefix, `${bucket}/${directory} was deleted.`);
204
- }
205
- catch (error) {
206
- npmlog_1.default.error(logPrefix, `Cannot delete ${bucket}/${directory}.`);
207
- throw error;
208
- }
209
- };
210
- exports.deleteS3Directory = deleteS3Directory;
@@ -1,85 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getStackName = exports.limitStackName = exports.STACK_NAME_MAX_LENGTH = exports.setPreDefinedStackName = void 0;
4
- const utils_1 = require("../utils");
5
- const change_case_1 = require("change-case");
6
- /**
7
- * Used by CLI set stack name when it is defined.
8
- */
9
- const setPreDefinedStackName = (stackName) => {
10
- (0, utils_1.setEnvVar)('STACK_NAME', stackName);
11
- };
12
- exports.setPreDefinedStackName = setPreDefinedStackName;
13
- /**
14
- * We use stackName as the name of appsync api, so we need to limit the length of stackName.
15
- * It is limited to 100 characters, as from "https://github.com/ttoss/ttoss/issues/353".
16
- */
17
- exports.STACK_NAME_MAX_LENGTH = 100;
18
- const limitStackName = (stackName) => {
19
- return `${stackName}`.substring(0, exports.STACK_NAME_MAX_LENGTH);
20
- };
21
- exports.limitStackName = limitStackName;
22
- /**
23
- * If stack name isn't previously defined, the name will be created accordingly
24
- * with the following rules:
25
- *
26
- * 1. The name has to parts.
27
- *
28
- * 1. The first part is defined by the package.json name, if it is defined.
29
- * Else, it'll be a random name starting with the string "Stack-", e.g. **Stack-96830**.
30
- *
31
- * 1. The second part will be defined by, whichever is defined first:
32
- * 1. environment,
33
- * 1. [branch name](https://carlin.ttoss.dev/docs/CLI#branchbranch_name) in param-case,
34
- * 1. `undefined`.
35
- *
36
- * Example:
37
- *
38
- * | Case | Package Name | Environment | Branch Name | `--stack-name` | Stack Name |
39
- * | ---- | ------------ | ----------- | ---------- | -------------- | ---------- |
40
- * | #1 | @package/name | Production | main | MyStackName | **MyStackName** |
41
- * | #2 | @package/name | Production | main | | **PackageName-Production** |
42
- * | #3 | @package/name | | main | | **PackageName-main** |
43
- * | #4 | @package/name | | | | **PackageName** |
44
- * | #5 | | Production | main | | **Stack-96820-Production** |
45
- * | #6 | | | main | | **Stack-96820-main** |
46
- * | #7 | | | | | **Stack-96820** |
47
- *
48
- * CAUTION!!!
49
- *
50
- * This method is a BREAKING CHANGE for **carlin**, I hope we never have to
51
- * change this algorithm, ever. Stack name is how we track the stacks on AWS.
52
- * Suppose we change this algorithm. If we perform an update or destroy
53
- * operation, **carlin** will create another stack or do nothing because the
54
- * old stack won't be found due to stack name changing.
55
- *
56
- */
57
- const getStackName = async () => {
58
- if ((0, utils_1.getEnvVar)('STACK_NAME')) {
59
- return (0, utils_1.getEnvVar)('STACK_NAME');
60
- }
61
- const [currentBranch, environment, packageName] = await Promise.all([
62
- (0, utils_1.getCurrentBranch)(),
63
- (0, utils_1.getEnvironment)(),
64
- (0, utils_1.getPackageName)(),
65
- ]);
66
- const firstName = packageName
67
- ? (0, change_case_1.pascalCase)(packageName)
68
- : `Stack-${Math.round(Math.random() * 100000)}`;
69
- const secondName = (() => {
70
- if (environment) {
71
- return environment;
72
- }
73
- if (currentBranch) {
74
- return (0, change_case_1.paramCase)(currentBranch);
75
- }
76
- return undefined;
77
- })();
78
- const name = [firstName, secondName]
79
- .filter((word) => {
80
- return !!word;
81
- })
82
- .join('-');
83
- return (0, exports.limitStackName)(name);
84
- };
85
- exports.getStackName = getStackName;
@@ -1,86 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.deployStaticAppCommand = exports.options = void 0;
7
- /* eslint-disable no-param-reassign */
8
- const config_1 = require("../../config");
9
- const utils_1 = require("../../utils");
10
- const findDefaultBuildFolder_1 = require("./findDefaultBuildFolder");
11
- const deployStaticApp_1 = require("./deployStaticApp");
12
- const cloudformation_1 = require("../cloudformation");
13
- const aws_sdk_1 = __importDefault(require("aws-sdk"));
14
- exports.options = {
15
- acm: {
16
- describe: 'The ARN of the certificate or the name of the exported variable whose value is the ARN of the certificate that will be associated to CloudFront.',
17
- type: 'string',
18
- },
19
- aliases: {
20
- describe: 'The aliases that will be associated with the CloudFront. See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html',
21
- implies: ['acm'],
22
- type: 'array',
23
- },
24
- 'build-folder': {
25
- describe: `The folder that will be uploaded. If not provided, it'll search for the folders "${findDefaultBuildFolder_1.defaultBuildFolders.join(', ')}."`,
26
- type: 'string',
27
- },
28
- cloudfront: {
29
- default: false,
30
- describe: 'A CloudFront resource is created along with S3 if this option is `true`.',
31
- require: false,
32
- type: 'boolean',
33
- },
34
- 'hosted-zone-name': {
35
- required: false,
36
- describe: `Is the name of a Route 53 hosted zone. If this value is provided, ${config_1.NAME} creates the subdomains defined on \`--aliases\` option. E.g. if you have a hosted zone named "sub.domain.com", the value provided may be "sub.domain.com".`,
37
- type: 'string',
38
- },
39
- /**
40
- * CloudFront triggers can be only in US East (N. Virginia) Region.
41
- * https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html#lambda-requirements-cloudfront-triggers
42
- */
43
- region: {
44
- coerce: () => {
45
- return config_1.CLOUDFRONT_REGION;
46
- },
47
- default: config_1.CLOUDFRONT_REGION,
48
- hidden: true,
49
- type: 'string',
50
- },
51
- 'skip-upload': {
52
- default: false,
53
- describe: 'Skip files upload to S3. Useful when wanting update only CloudFormation.',
54
- type: 'boolean',
55
- },
56
- spa: {
57
- default: false,
58
- describe: 'This option enables CloudFront to serve a single page application (SPA).',
59
- require: false,
60
- type: 'boolean',
61
- },
62
- };
63
- exports.deployStaticAppCommand = {
64
- command: 'static-app',
65
- describe: 'Deploy static app.',
66
- builder: (yargs) => {
67
- return (yargs
68
- .options((0, utils_1.addGroupToOptions)(exports.options, 'Deploy Static App Options'))
69
- /**
70
- * CloudFront triggers can be only in US East (N. Virginia) Region.
71
- * https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html#lambda-requirements-cloudfront-triggers
72
- */
73
- .middleware(() => {
74
- aws_sdk_1.default.config.region = config_1.CLOUDFRONT_REGION;
75
- }));
76
- },
77
- handler: ({ destroy, ...rest }) => {
78
- if (destroy) {
79
- (0, cloudformation_1.destroyCloudFormation)();
80
- }
81
- else {
82
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
83
- (0, deployStaticApp_1.deployStaticApp)(rest);
84
- }
85
- },
86
- };
@@ -1,65 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.deployStaticApp = void 0;
4
- const cloudformation_core_1 = require("../cloudformation.core");
5
- const getStaticAppBucket_1 = require("./getStaticAppBucket");
6
- const staticApp_template_1 = require("./staticApp.template");
7
- const utils_1 = require("../utils");
8
- const invalidateCloudFront_1 = require("./invalidateCloudFront");
9
- const removeOldVersions_1 = require("./removeOldVersions");
10
- const uploadBuiltAppToS3_1 = require("./uploadBuiltAppToS3");
11
- const logPrefix = 'static-app';
12
- /**
13
- * 1. Create the stack name that will be passed to CloudFormation.
14
- * 1. Create a CloudFormation template based on the type of the deployment, and
15
- * the options, for instance, only S3, SPA, with hosted zone...
16
- * 1. Create AWS resources using the templated created.
17
- * 1. Upload static files to the host bucket S3.
18
- * 1. Remove old deployment versions. Keep only the 3 most recent ones.
19
- */
20
- const deployStaticApp = async ({ acm, aliases, buildFolder, cloudfront, spa, hostedZoneName, region, skipUpload, }) => {
21
- try {
22
- const { stackName } = await (0, utils_1.handleDeployInitialization)({ logPrefix });
23
- const params = { StackName: stackName };
24
- const template = (0, staticApp_template_1.getStaticAppTemplate)({
25
- acm,
26
- aliases,
27
- cloudfront,
28
- spa,
29
- hostedZoneName,
30
- region,
31
- });
32
- const bucket = await (0, getStaticAppBucket_1.getStaticAppBucket)({ stackName });
33
- /**
34
- * Stack already exists. Upload files first after changing the files routes
35
- * because of the version changing.
36
- */
37
- if (bucket) {
38
- if (!skipUpload) {
39
- await (0, uploadBuiltAppToS3_1.uploadBuiltAppToS3)({ buildFolder, bucket, cloudfront });
40
- }
41
- const { Outputs } = await (0, cloudformation_core_1.deploy)({ params, template });
42
- await (0, invalidateCloudFront_1.invalidateCloudFront)({ outputs: Outputs });
43
- if (!skipUpload) {
44
- await (0, removeOldVersions_1.removeOldVersions)({ bucket });
45
- }
46
- }
47
- else {
48
- /**
49
- * Stack doesn't exist. Deploy CloudFormation first, get the bucket name,
50
- * and upload files to S3.
51
- */
52
- await (0, cloudformation_core_1.deploy)({ params, template });
53
- const newBucket = await (0, getStaticAppBucket_1.getStaticAppBucket)({ stackName });
54
- if (!newBucket) {
55
- throw new Error(`Cannot find bucket at ${stackName}.`);
56
- }
57
- await (0, uploadBuiltAppToS3_1.uploadBuiltAppToS3)({ buildFolder, bucket: newBucket, cloudfront });
58
- }
59
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
60
- }
61
- catch (error) {
62
- (0, utils_1.handleDeployError)({ error, logPrefix });
63
- }
64
- };
65
- exports.deployStaticApp = deployStaticApp;
@@ -1,44 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.findDefaultBuildFolder = exports.defaultBuildFolders = void 0;
4
- const s3_1 = require("../s3");
5
- /**
6
- * Fixes #20 https://github.com/ttoss/carlin/issues/20
7
- */
8
- exports.defaultBuildFolders = [
9
- /**
10
- * Create React App default build folder
11
- */
12
- 'build',
13
- /**
14
- * Next.js default output folder
15
- */
16
- 'out',
17
- /**
18
- * Storybook default output folder
19
- */
20
- 'storybook-static',
21
- /**
22
- * Vite.js default build folder
23
- */
24
- 'dist',
25
- ];
26
- const findDefaultBuildFolder = async () => {
27
- /**
28
- * Valid folders have at least one file inside.
29
- */
30
- const validFolders = await Promise.all(exports.defaultBuildFolders.map(async (directory) => {
31
- const allFiles = await (0, s3_1.getAllFilesInsideADirectory)({
32
- directory,
33
- });
34
- return { directory, isValid: allFiles.length !== 0 };
35
- }));
36
- const validFolder = validFolders.reduce((acc, cur) => {
37
- if (cur.isValid) {
38
- return cur.directory;
39
- }
40
- return acc;
41
- }, '');
42
- return validFolder;
43
- };
44
- exports.findDefaultBuildFolder = findDefaultBuildFolder;
@@ -1,19 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getStaticAppBucket = void 0;
4
- const cloudformation_core_1 = require("../cloudformation.core");
5
- const STATIC_APP_BUCKET_LOGICAL_ID = 'StaticBucket';
6
- const getStaticAppBucket = async ({ stackName, }) => {
7
- const params = {
8
- LogicalResourceId: STATIC_APP_BUCKET_LOGICAL_ID,
9
- StackName: stackName,
10
- };
11
- try {
12
- const { StackResourceDetail } = await (0, cloudformation_core_1.describeStackResource)(params);
13
- return StackResourceDetail?.PhysicalResourceId;
14
- }
15
- catch (error) {
16
- return undefined;
17
- }
18
- };
19
- exports.getStaticAppBucket = getStaticAppBucket;
@@ -1,44 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.invalidateCloudFront = void 0;
7
- const aws_sdk_1 = require("aws-sdk");
8
- const npmlog_1 = __importDefault(require("npmlog"));
9
- const CLOUDFRONT_DISTRIBUTION_ID = 'CloudFrontDistributionId';
10
- const logPrefix = 'static-app';
11
- const invalidateCloudFront = async ({ outputs, }) => {
12
- npmlog_1.default.info(logPrefix, 'Invalidating CloudFront...');
13
- if (!outputs) {
14
- npmlog_1.default.info(logPrefix, 'Invalidation: outputs do not exist.');
15
- return;
16
- }
17
- const cloudFrontDistributionIDOutput = outputs.find((output) => output.OutputKey === CLOUDFRONT_DISTRIBUTION_ID);
18
- if (cloudFrontDistributionIDOutput?.OutputValue) {
19
- const distributionId = cloudFrontDistributionIDOutput.OutputValue;
20
- const params = {
21
- DistributionId: distributionId,
22
- InvalidationBatch: {
23
- CallerReference: new Date().toISOString(),
24
- Paths: {
25
- Items: ['/*'],
26
- Quantity: 1,
27
- },
28
- },
29
- };
30
- const cloudFront = new aws_sdk_1.CloudFront();
31
- try {
32
- await cloudFront.createInvalidation(params).promise();
33
- npmlog_1.default.info(logPrefix, `CloudFront Distribution ID ${distributionId} invalidated with success.`);
34
- }
35
- catch (err) {
36
- npmlog_1.default.error(logPrefix, `Error while trying to invalidate CloudFront distribution ${distributionId}.`);
37
- npmlog_1.default.error(logPrefix, err);
38
- }
39
- }
40
- else {
41
- npmlog_1.default.info(logPrefix, `Cannot invalidate because distribution does not exist.`);
42
- }
43
- };
44
- exports.invalidateCloudFront = invalidateCloudFront;
@@ -1,56 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.removeOldVersions = void 0;
7
- const s3_1 = require("../s3");
8
- const npmlog_1 = __importDefault(require("npmlog"));
9
- const semver_1 = __importDefault(require("semver"));
10
- const logPrefix = 'static-app';
11
- /**
12
- * When a static-app deployment is executed, the algorithm delete old versions
13
- * if there are three newer versions, and keep these three. For instance, if
14
- * the bucket has the versions/folders below:
15
- *
16
- * - `9.0.1/`
17
- * - `9.0.2/`
18
- * - `9.2.0/`
19
- * - `9.3.0/`
20
- * - `9.3.1/`
21
- * - `10.0.0/` _<- created by the last deploy._
22
- *
23
- * The folders `9.0.1/`, `9.0.2/`, and `9.2.0/` will be delete after the
24
- * deploy.
25
- */
26
- const removeOldVersions = async ({ bucket }) => {
27
- try {
28
- npmlog_1.default.info(logPrefix, 'Removing old versions...');
29
- const { CommonPrefixes = [] } = await s3_1.s3
30
- .listObjectsV2({ Bucket: bucket, Delimiter: '/' })
31
- .promise();
32
- const versions = CommonPrefixes?.map(({ Prefix }) => {
33
- return Prefix?.replace('/', '');
34
- })
35
- .filter((version) => {
36
- return semver_1.default.valid(version);
37
- })
38
- .sort((a, b) => {
39
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
40
- return semver_1.default.gt(a, b) ? -1 : 1;
41
- });
42
- /**
43
- * Keep the 3 most recent versions.
44
- */
45
- versions.shift();
46
- versions.shift();
47
- versions.shift();
48
- await Promise.all(versions.map((version) => {
49
- return (0, s3_1.deleteS3Directory)({ bucket, directory: `${version}` });
50
- }));
51
- }
52
- catch (error) {
53
- npmlog_1.default.info(logPrefix, `Cannot remove older versions from "${bucket}" bucket.`);
54
- }
55
- };
56
- exports.removeOldVersions = removeOldVersions;