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.
- package/dist/index.js +4477 -4
- package/package.json +10 -10
- package/dist/cli.js +0 -246
- package/dist/config.js +0 -11
- package/dist/deploy/addDefaults.cloudformation.js +0 -151
- package/dist/deploy/baseStack/command.js +0 -9
- package/dist/deploy/baseStack/config.js +0 -30
- package/dist/deploy/baseStack/deployBaseStack.js +0 -62
- package/dist/deploy/baseStack/getBaseStackResource.js +0 -27
- package/dist/deploy/baseStack/getBucketTemplate.js +0 -46
- package/dist/deploy/baseStack/getLambdaImageBuilderTemplate.js +0 -188
- package/dist/deploy/baseStack/getLambdaLayerBuilderTemplate.js +0 -142
- package/dist/deploy/baseStack/getVpcTemplate.js +0 -169
- package/dist/deploy/cicd/cicd.template.js +0 -938
- package/dist/deploy/cicd/command.js +0 -31
- package/dist/deploy/cicd/command.options.js +0 -79
- package/dist/deploy/cicd/config.js +0 -8
- package/dist/deploy/cicd/deployCicd.js +0 -121
- package/dist/deploy/cicd/ecsTaskReportCommand.js +0 -55
- package/dist/deploy/cicd/getCicdStackName.js +0 -11
- package/dist/deploy/cicd/getTriggerPipelineObjectKey.js +0 -11
- package/dist/deploy/cicd/lambdas/cicdApiV1.handler.js +0 -124
- package/dist/deploy/cicd/lambdas/ecsTaskReport.handler.js +0 -126
- package/dist/deploy/cicd/lambdas/executeTasks.js +0 -67
- package/dist/deploy/cicd/lambdas/getProcessEnvVariable.js +0 -10
- package/dist/deploy/cicd/lambdas/githubWebhooksApiV1.handler.js +0 -148
- package/dist/deploy/cicd/lambdas/imageUpdaterSchedule.handler.js +0 -44
- package/dist/deploy/cicd/lambdas/index.js +0 -13
- package/dist/deploy/cicd/lambdas/pipelines.handler.js +0 -160
- package/dist/deploy/cicd/lambdas/putApprovalResultManualTask.js +0 -51
- package/dist/deploy/cicd/lambdas/shConditionalCommands.js +0 -30
- package/dist/deploy/cicd/pipelines.js +0 -86
- package/dist/deploy/cicd/readSSHKey.js +0 -34
- package/dist/deploy/cloudformation.core.js +0 -379
- package/dist/deploy/cloudformation.js +0 -189
- package/dist/deploy/command.js +0 -205
- package/dist/deploy/lambda/buildLambdaSingleFile.js +0 -67
- package/dist/deploy/lambda/deployLambdaCode.js +0 -43
- package/dist/deploy/lambda/deployLambdaLayers.js +0 -36
- package/dist/deploy/lambda/uploadCodeToECR.js +0 -53
- package/dist/deploy/lambda/uploadCodeToS3.js +0 -33
- package/dist/deploy/lambdaLayer/command.js +0 -50
- package/dist/deploy/lambdaLayer/deployLambdaLayer.js +0 -139
- package/dist/deploy/lambdaLayer/getPackageLambdaLayerStackName.js +0 -21
- package/dist/deploy/readDockerfile.js +0 -40
- package/dist/deploy/s3.js +0 -210
- package/dist/deploy/stackName.js +0 -85
- package/dist/deploy/staticApp/command.js +0 -86
- package/dist/deploy/staticApp/deployStaticApp.js +0 -65
- package/dist/deploy/staticApp/findDefaultBuildFolder.js +0 -44
- package/dist/deploy/staticApp/getStaticAppBucket.js +0 -19
- package/dist/deploy/staticApp/invalidateCloudFront.js +0 -44
- package/dist/deploy/staticApp/removeOldVersions.js +0 -56
- package/dist/deploy/staticApp/staticApp.template.js +0 -371
- package/dist/deploy/staticApp/uploadBuiltAppToS3.js +0 -28
- package/dist/deploy/utils.js +0 -31
- package/dist/deploy/vercel/command.js +0 -31
- package/dist/deploy/vercel/deployVercel.js +0 -59
- package/dist/generateEnv/generateEnv.js +0 -64
- package/dist/generateEnv/generateEnvCommand.js +0 -29
- package/dist/utils/addGroupToOptions.js +0 -11
- package/dist/utils/cloudFormationTemplate.js +0 -142
- package/dist/utils/codeBuild.js +0 -52
- package/dist/utils/environmentVariables.js +0 -16
- package/dist/utils/exec.js +0 -26
- package/dist/utils/formatCode.js +0 -34
- package/dist/utils/getAwsAccountId.js +0 -10
- package/dist/utils/getCurrentBranch.js +0 -35
- package/dist/utils/getEnvironment.js +0 -8
- package/dist/utils/getIamPath.js +0 -6
- package/dist/utils/getProjectName.js +0 -35
- package/dist/utils/index.js +0 -31
- package/dist/utils/packageJson.js +0 -32
- 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;
|
package/dist/deploy/stackName.js
DELETED
|
@@ -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;
|