@capraconsulting/webapp-deploy-lambda 1.1.1 → 1.2.3

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/README.md CHANGED
@@ -1,7 +1,5 @@
1
1
  # CDK Construct for deploying a webapp release
2
2
 
3
- [![Build Status](https://jenkins.capra.tv/buildStatus/icon?job=cals-internal/webapp-deploy-lambda/master)](https://jenkins.capra.tv/job/cals-internal/job/webapp-deploy-lambda/job/master)
4
-
5
3
  This project contains a CDK Construct for an AWS Lambda Function to handle
6
4
  deployment of a bundled static web application to a S3 bucket
7
5
  while preserving files from previous deployments within a time
@@ -36,7 +34,7 @@ This project approaches it differently by deleting old files.
36
34
  A user that still uses an application deployed five days ago should not
37
35
  be disrupted. To keep this promise we keep the newest deployment that
38
36
  happened more than five days ago, and delete files from older ones that no
39
- longer have any refrence to them.
37
+ longer have any reference to them.
40
38
 
41
39
  ## Triggering a deployment
42
40
 
@@ -6,6 +6,7 @@ import sys
6
6
  import tarfile
7
7
  import tempfile
8
8
  import time
9
+ import zipfile
9
10
  from contextlib import closing
10
11
 
11
12
  from botocore.exceptions import ClientError
@@ -113,10 +114,55 @@ def upload(bucket, files):
113
114
  s3_client.upload_file(local_path, bucket, s3_key, ExtraArgs=extra_args)
114
115
 
115
116
 
117
+ def extract(artifact_s3_url, source, dest, exclude_pattern):
118
+ pattern_compiled = (
119
+ re.compile(exclude_pattern) if exclude_pattern is not None else None
120
+ )
121
+
122
+ def handle_file(container_path, container_extract):
123
+ name = container_path.lstrip("./")
124
+ if pattern_compiled is not None and pattern_compiled.search(name):
125
+ logger.info("Skipping %s" % name)
126
+ else:
127
+ container_extract(container_path, path=dest + "/")
128
+ logger.info("Extracted %s" % name)
129
+
130
+ logger.info("Extracting archive")
131
+
132
+ if artifact_s3_url.endswith(".zip"):
133
+ logger.info("Found zip file")
134
+ with zipfile.ZipFile(source, "r") as zip:
135
+ for name in zip.namelist():
136
+ handle_file(name, zip.extract)
137
+
138
+ elif artifact_s3_url.endswith(".tgz"):
139
+ logger.info("Found tgz file")
140
+ with tarfile.open(source, "r:gz") as tar:
141
+ for tar_resource in tar:
142
+ if tar_resource.isfile():
143
+ handle_file(tar_resource.name, tar.extract)
144
+
145
+ else:
146
+ raise Exception(f"Unsupported extension: {artifact_s3_url}")
147
+
148
+
149
+ def construct_all_files(temp_dir, s3_upload_key_base):
150
+ all_files = []
151
+ for root, dirs, files in os.walk(temp_dir):
152
+ for filename in files:
153
+ local_path = os.path.join(root, filename)
154
+ relpath = os.path.relpath(local_path, temp_dir)
155
+ s3_key = os.path.join(s3_upload_key_base, relpath)
156
+
157
+ all_files.append([relpath, local_path, s3_key])
158
+
159
+ return all_files
160
+
161
+
116
162
  def deploy(artifact_s3_url, target_s3_url, exclude_pattern):
117
163
  """
118
164
  Deploys items from the S3 artifact, which should point to a .tgz
119
- file, to the target S3 bucket.
165
+ or .zip file, to the target S3 bucket.
120
166
 
121
167
  Returns a list of DeployItem that were uploaded.
122
168
  """
@@ -126,30 +172,11 @@ def deploy(artifact_s3_url, target_s3_url, exclude_pattern):
126
172
 
127
173
  temp_dir = tempfile.mkdtemp()
128
174
 
129
- pattern_compiled = (
130
- re.compile(exclude_pattern) if exclude_pattern is not None else None
131
- )
132
-
133
- logger.info("Extracting archive")
134
- with tarfile.open(temp_file.name, "r:gz") as tar:
135
- for tar_resource in tar:
136
- if tar_resource.isfile():
137
- name = tar_resource.name.lstrip("./")
138
- if pattern_compiled is not None and pattern_compiled.search(name):
139
- logger.info("Skipping %s" % name)
140
- else:
141
- tar.extract(tar_resource.name, path=temp_dir + "/")
142
- logger.info("Extracted %s" % name)
175
+ extract(artifact_s3_url, temp_file.name, temp_dir, exclude_pattern)
143
176
 
144
177
  s3_upload_bucket, s3_upload_key_base = parse_s3_url(target_s3_url)
145
178
 
146
- all_files = []
147
- for root, dirs, files in os.walk(temp_dir):
148
- for filename in files:
149
- local_path = os.path.join(root, filename)
150
- s3_key = os.path.join(s3_upload_key_base, filename)
151
-
152
- all_files.append([filename, local_path, s3_key])
179
+ all_files = construct_all_files(temp_dir, s3_upload_key_base)
153
180
 
154
181
  deploy_time = int(time.time())
155
182
 
@@ -1,9 +1,61 @@
1
+ import os
2
+ import shutil
3
+ import tempfile
1
4
  import unittest
5
+ from pathlib import Path
2
6
 
3
- # TODO: Improve tests
4
- from webapp_deploy.main import handler # noqa: F401
7
+ from webapp_deploy.main import construct_all_files, extract # noqa: F401
5
8
 
6
9
 
7
- class SimpleTest(unittest.TestCase):
8
- def test_loads_ok(self):
9
- pass
10
+ class ExtractTest(unittest.TestCase):
11
+ def test_extract_zip(self):
12
+ temp_dir = tempfile.mkdtemp()
13
+
14
+ extract("s3://example/source.zip", "example-assets/source.zip", temp_dir, None)
15
+
16
+ self.assertListEqual(
17
+ sorted(os.listdir(temp_dir)), ["README.md", "index.js", "index.js.map"]
18
+ )
19
+
20
+ shutil.rmtree(temp_dir)
21
+
22
+ def test_extract_tgz(self):
23
+ temp_dir = tempfile.mkdtemp()
24
+
25
+ extract("s3://example/source.tgz", "example-assets/source.tgz", temp_dir, None)
26
+
27
+ self.assertListEqual(
28
+ sorted(os.listdir(temp_dir)), ["README.md", "index.js", "index.js.map"]
29
+ )
30
+
31
+ shutil.rmtree(temp_dir)
32
+
33
+ def test_extract_tgz_filter_pattern(self):
34
+ temp_dir = tempfile.mkdtemp()
35
+
36
+ extract(
37
+ "s3://example/source.tgz", "example-assets/source.tgz", temp_dir, "\\.map$"
38
+ )
39
+
40
+ self.assertListEqual(sorted(os.listdir(temp_dir)), ["README.md", "index.js"])
41
+
42
+ shutil.rmtree(temp_dir)
43
+
44
+
45
+ class Files(unittest.TestCase):
46
+ def test_construct_all_files(self):
47
+ temp_dir = tempfile.mkdtemp()
48
+
49
+ (Path(temp_dir) / "a.txt").write_text("hello")
50
+ Path.mkdir(Path(temp_dir) / "b")
51
+ (Path(temp_dir) / "b/c.txt").write_text("world")
52
+
53
+ self.assertListEqual(
54
+ construct_all_files(temp_dir, "web/"),
55
+ [
56
+ ["a.txt", str(Path(temp_dir) / "a.txt"), "web/a.txt"],
57
+ ["b/c.txt", str(Path(temp_dir) / "b/c.txt"), "web/b/c.txt"],
58
+ ],
59
+ )
60
+
61
+ shutil.rmtree(temp_dir)
package/lib/index.d.ts CHANGED
@@ -1,50 +1,2 @@
1
- import * as lambda from "@aws-cdk/aws-lambda";
2
- import * as s3 from "@aws-cdk/aws-s3";
3
- import * as cdk from "@aws-cdk/core";
4
- export interface WebappDeployProps {
5
- /**
6
- * S3 bucket where the artifacts to be deployed are stored.
7
- */
8
- buildsBucket: s3.IBucket;
9
- /**
10
- * CloudFront Distribution ID to be invalidated after deploy.
11
- *
12
- * @default - none
13
- */
14
- distributionId?: string;
15
- /**
16
- * Regex for patterns of files to be discarded during deployment.
17
- *
18
- * Example: `\.map$` will exclude `js/myapp-1b22c248f.js.map`.
19
- *
20
- * @default - none
21
- */
22
- excludePattern?: string;
23
- /**
24
- * The time when a deployment is considered old and will be deleted
25
- * unless it is the newest old deployment.
26
- *
27
- * @default - 5 days
28
- */
29
- pruneDeploymentsOlderThan?: cdk.Duration;
30
- /**
31
- * Name of the lambda function to be created.
32
- *
33
- * @default cdk.PhysicalName.GENERATE_IF_NEEDED
34
- */
35
- functionName?: string;
36
- /**
37
- * Name of S3 bucket where the contents of the artifacts will be deployed.
38
- * The files will be deployed under the key "web", which is then expected
39
- * to be the origin for the CloudFront distribution
40
- */
41
- webBucket: s3.IBucket;
42
- }
43
- /**
44
- * Resource to deploy a webapp from a build artifact into an existing
45
- * S3 Bucket and CloudFront Distribution.
46
- */
47
- export declare class WebappDeploy extends cdk.Construct {
48
- readonly deployFn: lambda.Function;
49
- constructor(scope: cdk.Construct, id: string, props: WebappDeployProps);
50
- }
1
+ export { ISource, Source, SourceConfig } from "./source";
2
+ export { WebappDeploy, WebappDeployProps } from "./webapp-deploy";
package/lib/index.js CHANGED
@@ -1,64 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WebappDeploy = void 0;
4
- const iam = require("@aws-cdk/aws-iam");
5
- const lambda = require("@aws-cdk/aws-lambda");
6
- const cdk = require("@aws-cdk/core");
7
- const path = require("path");
8
- /**
9
- * Resource to deploy a webapp from a build artifact into an existing
10
- * S3 Bucket and CloudFront Distribution.
11
- */
12
- class WebappDeploy extends cdk.Construct {
13
- constructor(scope, id, props) {
14
- var _a, _b;
15
- super(scope, id);
16
- const environment = {
17
- DEPLOY_LOG_BUCKET_URL: `s3://${props.webBucket.bucketName}/deployments.log`,
18
- EXPIRE_SECONDS: ((_a = props.pruneDeploymentsOlderThan) !== null && _a !== void 0 ? _a : cdk.Duration.days(5))
19
- .toSeconds()
20
- .toString(),
21
- TARGET_BUCKET_URL: `s3://${props.webBucket.bucketName}/web`,
22
- };
23
- if (props.distributionId != null) {
24
- environment.CF_DISTRIBUTION_ID = props.distributionId;
25
- }
26
- if (props.excludePattern != null) {
27
- environment.EXCLUDE_PATTERN = props.excludePattern;
28
- }
29
- this.deployFn = new lambda.Function(this, "Resource", {
30
- code: lambda.Code.fromAsset(path.join(__dirname, "../dist")),
31
- environment,
32
- functionName: (_b = props.functionName) !== null && _b !== void 0 ? _b : cdk.PhysicalName.GENERATE_IF_NEEDED,
33
- handler: "webapp_deploy.main.handler",
34
- reservedConcurrentExecutions: 1,
35
- runtime: lambda.Runtime.PYTHON_3_7,
36
- timeout: cdk.Duration.minutes(2),
37
- initialPolicy: [
38
- new iam.PolicyStatement({
39
- actions: ["s3:HeadObject", "s3:GetObject"],
40
- resources: [props.buildsBucket.arnForObjects("*")],
41
- }),
42
- new iam.PolicyStatement({
43
- actions: ["s3:PutObject", "s3:DeleteObject"],
44
- resources: [props.webBucket.arnForObjects("web/*")],
45
- }),
46
- new iam.PolicyStatement({
47
- actions: ["s3:GetObject", "s3:PutObject"],
48
- resources: [props.webBucket.arnForObjects("deployments.log")],
49
- }),
50
- new iam.PolicyStatement({
51
- actions: ["s3:List*"],
52
- resources: [props.webBucket.bucketArn],
53
- }),
54
- new iam.PolicyStatement({
55
- actions: ["cloudfront:CreateInvalidation"],
56
- // Cannot be restricted
57
- resources: ["*"],
58
- }),
59
- ],
60
- });
61
- }
62
- }
63
- exports.WebappDeploy = WebappDeploy;
64
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsd0NBQXVDO0FBQ3ZDLDhDQUE2QztBQUU3QyxxQ0FBb0M7QUFDcEMsNkJBQTRCO0FBMEM1Qjs7O0dBR0c7QUFDSCxNQUFhLFlBQWEsU0FBUSxHQUFHLENBQUMsU0FBUztJQUc3QyxZQUFZLEtBQW9CLEVBQUUsRUFBVSxFQUFFLEtBQXdCOztRQUNwRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFBO1FBRWhCLE1BQU0sV0FBVyxHQUEyQjtZQUMxQyxxQkFBcUIsRUFBRSxRQUFRLEtBQUssQ0FBQyxTQUFTLENBQUMsVUFBVSxrQkFBa0I7WUFDM0UsY0FBYyxFQUFFLE9BQUMsS0FBSyxDQUFDLHlCQUF5QixtQ0FBSSxHQUFHLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztpQkFDdEUsU0FBUyxFQUFFO2lCQUNYLFFBQVEsRUFBRTtZQUNiLGlCQUFpQixFQUFFLFFBQVEsS0FBSyxDQUFDLFNBQVMsQ0FBQyxVQUFVLE1BQU07U0FDNUQsQ0FBQTtRQUVELElBQUksS0FBSyxDQUFDLGNBQWMsSUFBSSxJQUFJLEVBQUU7WUFDaEMsV0FBVyxDQUFDLGtCQUFrQixHQUFHLEtBQUssQ0FBQyxjQUFjLENBQUE7U0FDdEQ7UUFFRCxJQUFJLEtBQUssQ0FBQyxjQUFjLElBQUksSUFBSSxFQUFFO1lBQ2hDLFdBQVcsQ0FBQyxlQUFlLEdBQUcsS0FBSyxDQUFDLGNBQWMsQ0FBQTtTQUNuRDtRQUVELElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxVQUFVLEVBQUU7WUFDcEQsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQzVELFdBQVc7WUFDWCxZQUFZLFFBQUUsS0FBSyxDQUFDLFlBQVksbUNBQUksR0FBRyxDQUFDLFlBQVksQ0FBQyxrQkFBa0I7WUFDdkUsT0FBTyxFQUFFLDRCQUE0QjtZQUNyQyw0QkFBNEIsRUFBRSxDQUFDO1lBQy9CLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLFVBQVU7WUFDbEMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUNoQyxhQUFhLEVBQUU7Z0JBQ2IsSUFBSSxHQUFHLENBQUMsZUFBZSxDQUFDO29CQUN0QixPQUFPLEVBQUUsQ0FBQyxlQUFlLEVBQUUsY0FBYyxDQUFDO29CQUMxQyxTQUFTLEVBQUUsQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQztpQkFDbkQsQ0FBQztnQkFDRixJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUM7b0JBQ3RCLE9BQU8sRUFBRSxDQUFDLGNBQWMsRUFBRSxpQkFBaUIsQ0FBQztvQkFDNUMsU0FBUyxFQUFFLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUM7aUJBQ3BELENBQUM7Z0JBQ0YsSUFBSSxHQUFHLENBQUMsZUFBZSxDQUFDO29CQUN0QixPQUFPLEVBQUUsQ0FBQyxjQUFjLEVBQUUsY0FBYyxDQUFDO29CQUN6QyxTQUFTLEVBQUUsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO2lCQUM5RCxDQUFDO2dCQUNGLElBQUksR0FBRyxDQUFDLGVBQWUsQ0FBQztvQkFDdEIsT0FBTyxFQUFFLENBQUMsVUFBVSxDQUFDO29CQUNyQixTQUFTLEVBQUUsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQztpQkFDdkMsQ0FBQztnQkFDRixJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUM7b0JBQ3RCLE9BQU8sRUFBRSxDQUFDLCtCQUErQixDQUFDO29CQUMxQyx1QkFBdUI7b0JBQ3ZCLFNBQVMsRUFBRSxDQUFDLEdBQUcsQ0FBQztpQkFDakIsQ0FBQzthQUNIO1NBQ0YsQ0FBQyxDQUFBO0lBQ0osQ0FBQztDQUNGO0FBdkRELG9DQXVEQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGlhbSBmcm9tIFwiQGF3cy1jZGsvYXdzLWlhbVwiXG5pbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSBcIkBhd3MtY2RrL2F3cy1sYW1iZGFcIlxuaW1wb3J0ICogYXMgczMgZnJvbSBcIkBhd3MtY2RrL2F3cy1zM1wiXG5pbXBvcnQgKiBhcyBjZGsgZnJvbSBcIkBhd3MtY2RrL2NvcmVcIlxuaW1wb3J0ICogYXMgcGF0aCBmcm9tIFwicGF0aFwiXG5cbmV4cG9ydCBpbnRlcmZhY2UgV2ViYXBwRGVwbG95UHJvcHMge1xuICAvKipcbiAgICogUzMgYnVja2V0IHdoZXJlIHRoZSBhcnRpZmFjdHMgdG8gYmUgZGVwbG95ZWQgYXJlIHN0b3JlZC5cbiAgICovXG4gIGJ1aWxkc0J1Y2tldDogczMuSUJ1Y2tldFxuICAvKipcbiAgICogQ2xvdWRGcm9udCBEaXN0cmlidXRpb24gSUQgdG8gYmUgaW52YWxpZGF0ZWQgYWZ0ZXIgZGVwbG95LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vbmVcbiAgICovXG4gIGRpc3RyaWJ1dGlvbklkPzogc3RyaW5nXG4gIC8qKlxuICAgKiBSZWdleCBmb3IgcGF0dGVybnMgb2YgZmlsZXMgdG8gYmUgZGlzY2FyZGVkIGR1cmluZyBkZXBsb3ltZW50LlxuICAgKlxuICAgKiBFeGFtcGxlOiBgXFwubWFwJGAgd2lsbCBleGNsdWRlIGBqcy9teWFwcC0xYjIyYzI0OGYuanMubWFwYC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBub25lXG4gICAqL1xuICBleGNsdWRlUGF0dGVybj86IHN0cmluZ1xuICAvKipcbiAgICogVGhlIHRpbWUgd2hlbiBhIGRlcGxveW1lbnQgaXMgY29uc2lkZXJlZCBvbGQgYW5kIHdpbGwgYmUgZGVsZXRlZFxuICAgKiB1bmxlc3MgaXQgaXMgdGhlIG5ld2VzdCBvbGQgZGVwbG95bWVudC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSA1IGRheXNcbiAgICovXG4gIHBydW5lRGVwbG95bWVudHNPbGRlclRoYW4/OiBjZGsuRHVyYXRpb25cbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIGxhbWJkYSBmdW5jdGlvbiB0byBiZSBjcmVhdGVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCBjZGsuUGh5c2ljYWxOYW1lLkdFTkVSQVRFX0lGX05FRURFRFxuICAgKi9cbiAgZnVuY3Rpb25OYW1lPzogc3RyaW5nXG4gIC8qKlxuICAgKiBOYW1lIG9mIFMzIGJ1Y2tldCB3aGVyZSB0aGUgY29udGVudHMgb2YgdGhlIGFydGlmYWN0cyB3aWxsIGJlIGRlcGxveWVkLlxuICAgKiBUaGUgZmlsZXMgd2lsbCBiZSBkZXBsb3llZCB1bmRlciB0aGUga2V5IFwid2ViXCIsIHdoaWNoIGlzIHRoZW4gZXhwZWN0ZWRcbiAgICogdG8gYmUgdGhlIG9yaWdpbiBmb3IgdGhlIENsb3VkRnJvbnQgZGlzdHJpYnV0aW9uXG4gICAqL1xuICB3ZWJCdWNrZXQ6IHMzLklCdWNrZXRcbn1cblxuLyoqXG4gKiBSZXNvdXJjZSB0byBkZXBsb3kgYSB3ZWJhcHAgZnJvbSBhIGJ1aWxkIGFydGlmYWN0IGludG8gYW4gZXhpc3RpbmdcbiAqIFMzIEJ1Y2tldCBhbmQgQ2xvdWRGcm9udCBEaXN0cmlidXRpb24uXG4gKi9cbmV4cG9ydCBjbGFzcyBXZWJhcHBEZXBsb3kgZXh0ZW5kcyBjZGsuQ29uc3RydWN0IHtcbiAgcmVhZG9ubHkgZGVwbG95Rm46IGxhbWJkYS5GdW5jdGlvblxuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBjZGsuQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogV2ViYXBwRGVwbG95UHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpXG5cbiAgICBjb25zdCBlbnZpcm9ubWVudDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICAgIERFUExPWV9MT0dfQlVDS0VUX1VSTDogYHMzOi8vJHtwcm9wcy53ZWJCdWNrZXQuYnVja2V0TmFtZX0vZGVwbG95bWVudHMubG9nYCxcbiAgICAgIEVYUElSRV9TRUNPTkRTOiAocHJvcHMucHJ1bmVEZXBsb3ltZW50c09sZGVyVGhhbiA/PyBjZGsuRHVyYXRpb24uZGF5cyg1KSlcbiAgICAgICAgLnRvU2Vjb25kcygpXG4gICAgICAgIC50b1N0cmluZygpLFxuICAgICAgVEFSR0VUX0JVQ0tFVF9VUkw6IGBzMzovLyR7cHJvcHMud2ViQnVja2V0LmJ1Y2tldE5hbWV9L3dlYmAsXG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmRpc3RyaWJ1dGlvbklkICE9IG51bGwpIHtcbiAgICAgIGVudmlyb25tZW50LkNGX0RJU1RSSUJVVElPTl9JRCA9IHByb3BzLmRpc3RyaWJ1dGlvbklkXG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmV4Y2x1ZGVQYXR0ZXJuICE9IG51bGwpIHtcbiAgICAgIGVudmlyb25tZW50LkVYQ0xVREVfUEFUVEVSTiA9IHByb3BzLmV4Y2x1ZGVQYXR0ZXJuXG4gICAgfVxuXG4gICAgdGhpcy5kZXBsb3lGbiA9IG5ldyBsYW1iZGEuRnVuY3Rpb24odGhpcywgXCJSZXNvdXJjZVwiLCB7XG4gICAgICBjb2RlOiBsYW1iZGEuQ29kZS5mcm9tQXNzZXQocGF0aC5qb2luKF9fZGlybmFtZSwgXCIuLi9kaXN0XCIpKSxcbiAgICAgIGVudmlyb25tZW50LFxuICAgICAgZnVuY3Rpb25OYW1lOiBwcm9wcy5mdW5jdGlvbk5hbWUgPz8gY2RrLlBoeXNpY2FsTmFtZS5HRU5FUkFURV9JRl9ORUVERUQsXG4gICAgICBoYW5kbGVyOiBcIndlYmFwcF9kZXBsb3kubWFpbi5oYW5kbGVyXCIsXG4gICAgICByZXNlcnZlZENvbmN1cnJlbnRFeGVjdXRpb25zOiAxLFxuICAgICAgcnVudGltZTogbGFtYmRhLlJ1bnRpbWUuUFlUSE9OXzNfNyxcbiAgICAgIHRpbWVvdXQ6IGNkay5EdXJhdGlvbi5taW51dGVzKDIpLFxuICAgICAgaW5pdGlhbFBvbGljeTogW1xuICAgICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgYWN0aW9uczogW1wiczM6SGVhZE9iamVjdFwiLCBcInMzOkdldE9iamVjdFwiXSxcbiAgICAgICAgICByZXNvdXJjZXM6IFtwcm9wcy5idWlsZHNCdWNrZXQuYXJuRm9yT2JqZWN0cyhcIipcIildLFxuICAgICAgICB9KSxcbiAgICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGFjdGlvbnM6IFtcInMzOlB1dE9iamVjdFwiLCBcInMzOkRlbGV0ZU9iamVjdFwiXSxcbiAgICAgICAgICByZXNvdXJjZXM6IFtwcm9wcy53ZWJCdWNrZXQuYXJuRm9yT2JqZWN0cyhcIndlYi8qXCIpXSxcbiAgICAgICAgfSksXG4gICAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICBhY3Rpb25zOiBbXCJzMzpHZXRPYmplY3RcIiwgXCJzMzpQdXRPYmplY3RcIl0sXG4gICAgICAgICAgcmVzb3VyY2VzOiBbcHJvcHMud2ViQnVja2V0LmFybkZvck9iamVjdHMoXCJkZXBsb3ltZW50cy5sb2dcIildLFxuICAgICAgICB9KSxcbiAgICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGFjdGlvbnM6IFtcInMzOkxpc3QqXCJdLFxuICAgICAgICAgIHJlc291cmNlczogW3Byb3BzLndlYkJ1Y2tldC5idWNrZXRBcm5dLFxuICAgICAgICB9KSxcbiAgICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGFjdGlvbnM6IFtcImNsb3VkZnJvbnQ6Q3JlYXRlSW52YWxpZGF0aW9uXCJdLFxuICAgICAgICAgIC8vIENhbm5vdCBiZSByZXN0cmljdGVkXG4gICAgICAgICAgcmVzb3VyY2VzOiBbXCIqXCJdLFxuICAgICAgICB9KSxcbiAgICAgIF0sXG4gICAgfSlcbiAgfVxufVxuIl19
3
+ exports.WebappDeploy = exports.Source = void 0;
4
+ var source_1 = require("./source");
5
+ Object.defineProperty(exports, "Source", { enumerable: true, get: function () { return source_1.Source; } });
6
+ var webapp_deploy_1 = require("./webapp-deploy");
7
+ Object.defineProperty(exports, "WebappDeploy", { enumerable: true, get: function () { return webapp_deploy_1.WebappDeploy; } });
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbUNBQXdEO0FBQXRDLGdHQUFBLE1BQU0sT0FBQTtBQUN4QixpREFBaUU7QUFBeEQsNkdBQUEsWUFBWSxPQUFBIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHsgSVNvdXJjZSwgU291cmNlLCBTb3VyY2VDb25maWcgfSBmcm9tIFwiLi9zb3VyY2VcIlxuZXhwb3J0IHsgV2ViYXBwRGVwbG95LCBXZWJhcHBEZXBsb3lQcm9wcyB9IGZyb20gXCIuL3dlYmFwcC1kZXBsb3lcIlxuIl19
@@ -0,0 +1,58 @@
1
+ import * as iam from "@aws-cdk/aws-iam";
2
+ import * as s3 from "@aws-cdk/aws-s3";
3
+ import * as s3Assets from "@aws-cdk/aws-s3-assets";
4
+ import * as cdk from "@aws-cdk/core";
5
+ export interface SourceConfig {
6
+ /**
7
+ * The source bucket to deploy from.
8
+ */
9
+ readonly bucket: s3.IBucket;
10
+ /**
11
+ * An S3 object key in the source bucket that points to a zip file.
12
+ */
13
+ readonly zipObjectKey: string;
14
+ }
15
+ /**
16
+ * Bind context for ISources
17
+ */
18
+ export interface SourceContext {
19
+ /**
20
+ * The role for the handler
21
+ *
22
+ * @default - no policy is modified
23
+ */
24
+ readonly handlerRole?: iam.IRole;
25
+ }
26
+ /**
27
+ * Represents a source for bucket deployments.
28
+ */
29
+ export interface ISource {
30
+ /**
31
+ * Binds the source to a bucket deployment.
32
+ */
33
+ bind(scope: cdk.Construct, context?: SourceContext): SourceConfig;
34
+ }
35
+ /**
36
+ * Specifies bucket deployment source.
37
+ *
38
+ * Usage:
39
+ *
40
+ * Source.bucket(bucket, key)
41
+ * Source.asset('/local/path/to/directory')
42
+ * Source.asset('/local/path/to/a/file.zip')
43
+ *
44
+ */
45
+ export declare class Source {
46
+ /**
47
+ * Uses a .zip file stored in an S3 bucket as the source for the destination bucket contents.
48
+ * @param bucket The S3 Bucket
49
+ * @param zipObjectKey The S3 object key of the zip file with contents
50
+ */
51
+ static bucket(bucket: s3.IBucket, zipObjectKey: string): ISource;
52
+ /**
53
+ * Uses a local asset as the deployment source.
54
+ * @param path The path to a local .zip file or a directory
55
+ */
56
+ static asset(path: string, options?: s3Assets.AssetOptions): ISource;
57
+ private constructor();
58
+ }
package/lib/source.js ADDED
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Source = void 0;
4
+ const s3Assets = require("@aws-cdk/aws-s3-assets");
5
+ /**
6
+ * Specifies bucket deployment source.
7
+ *
8
+ * Usage:
9
+ *
10
+ * Source.bucket(bucket, key)
11
+ * Source.asset('/local/path/to/directory')
12
+ * Source.asset('/local/path/to/a/file.zip')
13
+ *
14
+ */
15
+ class Source {
16
+ /**
17
+ * Uses a .zip file stored in an S3 bucket as the source for the destination bucket contents.
18
+ * @param bucket The S3 Bucket
19
+ * @param zipObjectKey The S3 object key of the zip file with contents
20
+ */
21
+ static bucket(bucket, zipObjectKey) {
22
+ return {
23
+ bind: (_, context) => {
24
+ if (!context) {
25
+ throw new Error("To use a Source.bucket(), context must be provided");
26
+ }
27
+ if (context.handlerRole) {
28
+ bucket.grantRead(context.handlerRole);
29
+ }
30
+ return { bucket, zipObjectKey };
31
+ },
32
+ };
33
+ }
34
+ /**
35
+ * Uses a local asset as the deployment source.
36
+ * @param path The path to a local .zip file or a directory
37
+ */
38
+ static asset(path, options) {
39
+ return {
40
+ bind(scope, context) {
41
+ if (!context) {
42
+ throw new Error("To use a Source.asset(), context must be provided");
43
+ }
44
+ let id = 1;
45
+ while (scope.node.tryFindChild(`Asset${id}`)) {
46
+ id++;
47
+ }
48
+ const asset = new s3Assets.Asset(scope, `Asset${id}`, {
49
+ path,
50
+ ...options,
51
+ });
52
+ if (!asset.isZipArchive) {
53
+ throw new Error("Asset path must be either a .zip file or a directory");
54
+ }
55
+ if (context.handlerRole) {
56
+ asset.grantRead(context.handlerRole);
57
+ }
58
+ return {
59
+ bucket: asset.bucket,
60
+ zipObjectKey: asset.s3ObjectKey,
61
+ };
62
+ },
63
+ };
64
+ }
65
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
66
+ constructor() { }
67
+ }
68
+ exports.Source = Source;
69
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic291cmNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3NvdXJjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxtREFBa0Q7QUF1Q2xEOzs7Ozs7Ozs7R0FTRztBQUNILE1BQWEsTUFBTTtJQUNqQjs7OztPQUlHO0lBQ0ksTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFrQixFQUFFLFlBQW9CO1FBQzNELE9BQU87WUFDTCxJQUFJLEVBQUUsQ0FBQyxDQUFnQixFQUFFLE9BQXVCLEVBQUUsRUFBRTtnQkFDbEQsSUFBSSxDQUFDLE9BQU8sRUFBRTtvQkFDWixNQUFNLElBQUksS0FBSyxDQUFDLG9EQUFvRCxDQUFDLENBQUE7aUJBQ3RFO2dCQUVELElBQUksT0FBTyxDQUFDLFdBQVcsRUFBRTtvQkFDdkIsTUFBTSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUE7aUJBQ3RDO2dCQUVELE9BQU8sRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLENBQUE7WUFDakMsQ0FBQztTQUNGLENBQUE7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFZLEVBQUUsT0FBK0I7UUFDL0QsT0FBTztZQUNMLElBQUksQ0FBQyxLQUFvQixFQUFFLE9BQXVCO2dCQUNoRCxJQUFJLENBQUMsT0FBTyxFQUFFO29CQUNaLE1BQU0sSUFBSSxLQUFLLENBQUMsbURBQW1ELENBQUMsQ0FBQTtpQkFDckU7Z0JBRUQsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFBO2dCQUNWLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxFQUFFO29CQUM1QyxFQUFFLEVBQUUsQ0FBQTtpQkFDTDtnQkFDRCxNQUFNLEtBQUssR0FBRyxJQUFJLFFBQVEsQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxFQUFFLEVBQUU7b0JBQ3BELElBQUk7b0JBQ0osR0FBRyxPQUFPO2lCQUNYLENBQUMsQ0FBQTtnQkFDRixJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksRUFBRTtvQkFDdkIsTUFBTSxJQUFJLEtBQUssQ0FDYixzREFBc0QsQ0FDdkQsQ0FBQTtpQkFDRjtnQkFFRCxJQUFJLE9BQU8sQ0FBQyxXQUFXLEVBQUU7b0JBQ3ZCLEtBQUssQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFBO2lCQUNyQztnQkFFRCxPQUFPO29CQUNMLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTTtvQkFDcEIsWUFBWSxFQUFFLEtBQUssQ0FBQyxXQUFXO2lCQUNoQyxDQUFBO1lBQ0gsQ0FBQztTQUNGLENBQUE7SUFDSCxDQUFDO0lBRUQsZ0VBQWdFO0lBQ2hFLGdCQUF1QixDQUFDO0NBQ3pCO0FBN0RELHdCQTZEQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGlhbSBmcm9tIFwiQGF3cy1jZGsvYXdzLWlhbVwiXG5pbXBvcnQgKiBhcyBzMyBmcm9tIFwiQGF3cy1jZGsvYXdzLXMzXCJcbmltcG9ydCAqIGFzIHMzQXNzZXRzIGZyb20gXCJAYXdzLWNkay9hd3MtczMtYXNzZXRzXCJcbmltcG9ydCAqIGFzIGNkayBmcm9tIFwiQGF3cy1jZGsvY29yZVwiXG5cbi8vIFRoaXMgaXMgbW9zdGx5IGJhc2VkIG9uIGF3cy1zMy1kZXBsb3ltZW50IGZyb20gYXdzLWNkay5cblxuZXhwb3J0IGludGVyZmFjZSBTb3VyY2VDb25maWcge1xuICAvKipcbiAgICogVGhlIHNvdXJjZSBidWNrZXQgdG8gZGVwbG95IGZyb20uXG4gICAqL1xuICByZWFkb25seSBidWNrZXQ6IHMzLklCdWNrZXRcblxuICAvKipcbiAgICogQW4gUzMgb2JqZWN0IGtleSBpbiB0aGUgc291cmNlIGJ1Y2tldCB0aGF0IHBvaW50cyB0byBhIHppcCBmaWxlLlxuICAgKi9cbiAgcmVhZG9ubHkgemlwT2JqZWN0S2V5OiBzdHJpbmdcbn1cblxuLyoqXG4gKiBCaW5kIGNvbnRleHQgZm9yIElTb3VyY2VzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU291cmNlQ29udGV4dCB7XG4gIC8qKlxuICAgKiBUaGUgcm9sZSBmb3IgdGhlIGhhbmRsZXJcbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBwb2xpY3kgaXMgbW9kaWZpZWRcbiAgICovXG4gIHJlYWRvbmx5IGhhbmRsZXJSb2xlPzogaWFtLklSb2xlXG59XG5cbi8qKlxuICogUmVwcmVzZW50cyBhIHNvdXJjZSBmb3IgYnVja2V0IGRlcGxveW1lbnRzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIElTb3VyY2Uge1xuICAvKipcbiAgICogQmluZHMgdGhlIHNvdXJjZSB0byBhIGJ1Y2tldCBkZXBsb3ltZW50LlxuICAgKi9cbiAgYmluZChzY29wZTogY2RrLkNvbnN0cnVjdCwgY29udGV4dD86IFNvdXJjZUNvbnRleHQpOiBTb3VyY2VDb25maWdcbn1cblxuLyoqXG4gKiBTcGVjaWZpZXMgYnVja2V0IGRlcGxveW1lbnQgc291cmNlLlxuICpcbiAqIFVzYWdlOlxuICpcbiAqICAgICBTb3VyY2UuYnVja2V0KGJ1Y2tldCwga2V5KVxuICogICAgIFNvdXJjZS5hc3NldCgnL2xvY2FsL3BhdGgvdG8vZGlyZWN0b3J5JylcbiAqICAgICBTb3VyY2UuYXNzZXQoJy9sb2NhbC9wYXRoL3RvL2EvZmlsZS56aXAnKVxuICpcbiAqL1xuZXhwb3J0IGNsYXNzIFNvdXJjZSB7XG4gIC8qKlxuICAgKiBVc2VzIGEgLnppcCBmaWxlIHN0b3JlZCBpbiBhbiBTMyBidWNrZXQgYXMgdGhlIHNvdXJjZSBmb3IgdGhlIGRlc3RpbmF0aW9uIGJ1Y2tldCBjb250ZW50cy5cbiAgICogQHBhcmFtIGJ1Y2tldCBUaGUgUzMgQnVja2V0XG4gICAqIEBwYXJhbSB6aXBPYmplY3RLZXkgVGhlIFMzIG9iamVjdCBrZXkgb2YgdGhlIHppcCBmaWxlIHdpdGggY29udGVudHNcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgYnVja2V0KGJ1Y2tldDogczMuSUJ1Y2tldCwgemlwT2JqZWN0S2V5OiBzdHJpbmcpOiBJU291cmNlIHtcbiAgICByZXR1cm4ge1xuICAgICAgYmluZDogKF86IGNkay5Db25zdHJ1Y3QsIGNvbnRleHQ/OiBTb3VyY2VDb250ZXh0KSA9PiB7XG4gICAgICAgIGlmICghY29udGV4dCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRvIHVzZSBhIFNvdXJjZS5idWNrZXQoKSwgY29udGV4dCBtdXN0IGJlIHByb3ZpZGVkXCIpXG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29udGV4dC5oYW5kbGVyUm9sZSkge1xuICAgICAgICAgIGJ1Y2tldC5ncmFudFJlYWQoY29udGV4dC5oYW5kbGVyUm9sZSlcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7IGJ1Y2tldCwgemlwT2JqZWN0S2V5IH1cbiAgICAgIH0sXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFVzZXMgYSBsb2NhbCBhc3NldCBhcyB0aGUgZGVwbG95bWVudCBzb3VyY2UuXG4gICAqIEBwYXJhbSBwYXRoIFRoZSBwYXRoIHRvIGEgbG9jYWwgLnppcCBmaWxlIG9yIGEgZGlyZWN0b3J5XG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGFzc2V0KHBhdGg6IHN0cmluZywgb3B0aW9ucz86IHMzQXNzZXRzLkFzc2V0T3B0aW9ucyk6IElTb3VyY2Uge1xuICAgIHJldHVybiB7XG4gICAgICBiaW5kKHNjb3BlOiBjZGsuQ29uc3RydWN0LCBjb250ZXh0PzogU291cmNlQ29udGV4dCk6IFNvdXJjZUNvbmZpZyB7XG4gICAgICAgIGlmICghY29udGV4dCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRvIHVzZSBhIFNvdXJjZS5hc3NldCgpLCBjb250ZXh0IG11c3QgYmUgcHJvdmlkZWRcIilcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBpZCA9IDFcbiAgICAgICAgd2hpbGUgKHNjb3BlLm5vZGUudHJ5RmluZENoaWxkKGBBc3NldCR7aWR9YCkpIHtcbiAgICAgICAgICBpZCsrXG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYXNzZXQgPSBuZXcgczNBc3NldHMuQXNzZXQoc2NvcGUsIGBBc3NldCR7aWR9YCwge1xuICAgICAgICAgIHBhdGgsXG4gICAgICAgICAgLi4ub3B0aW9ucyxcbiAgICAgICAgfSlcbiAgICAgICAgaWYgKCFhc3NldC5pc1ppcEFyY2hpdmUpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBcIkFzc2V0IHBhdGggbXVzdCBiZSBlaXRoZXIgYSAuemlwIGZpbGUgb3IgYSBkaXJlY3RvcnlcIixcbiAgICAgICAgICApXG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29udGV4dC5oYW5kbGVyUm9sZSkge1xuICAgICAgICAgIGFzc2V0LmdyYW50UmVhZChjb250ZXh0LmhhbmRsZXJSb2xlKVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBidWNrZXQ6IGFzc2V0LmJ1Y2tldCxcbiAgICAgICAgICB6aXBPYmplY3RLZXk6IGFzc2V0LnMzT2JqZWN0S2V5LFxuICAgICAgICB9XG4gICAgICB9LFxuICAgIH1cbiAgfVxuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZW1wdHktZnVuY3Rpb25cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpIHt9XG59XG4iXX0=
@@ -0,0 +1,63 @@
1
+ import * as cloudfront from "@aws-cdk/aws-cloudfront";
2
+ import * as lambda from "@aws-cdk/aws-lambda";
3
+ import * as s3 from "@aws-cdk/aws-s3";
4
+ import * as cdk from "@aws-cdk/core";
5
+ import { ISource } from "./source";
6
+ export interface WebappDeployProps {
7
+ /**
8
+ * Optional S3 bucket that can be used for deployment from outside CDK.
9
+ *
10
+ * If specified a policy is added so the deploy function can read from
11
+ * the bucket.
12
+ *
13
+ * @default - none
14
+ */
15
+ buildsBucket?: s3.IBucket;
16
+ /**
17
+ * CloudFront Distribution to be invalidated after deploy.
18
+ *
19
+ * @default - none
20
+ */
21
+ distribution?: cloudfront.IDistribution;
22
+ /**
23
+ * Regex for patterns of files to be discarded during deployment.
24
+ *
25
+ * Example: `\.map$` will exclude `js/myapp-1b22c248f.js.map`.
26
+ *
27
+ * @default - none
28
+ */
29
+ excludePattern?: string;
30
+ /**
31
+ * The time when a deployment is considered old and will be deleted
32
+ * unless it is the newest old deployment.
33
+ *
34
+ * @default - 5 days
35
+ */
36
+ pruneDeploymentsOlderThan?: cdk.Duration;
37
+ /**
38
+ * Name of the lambda function to be created.
39
+ *
40
+ * @default cdk.PhysicalName.GENERATE_IF_NEEDED
41
+ */
42
+ functionName?: string;
43
+ /**
44
+ * Name of S3 bucket where the contents of the artifacts will be deployed.
45
+ * The files will be deployed under the key "web", which is then expected
46
+ * to be the origin for the CloudFront distribution
47
+ */
48
+ webBucket: s3.IBucket;
49
+ /**
50
+ * Specific artifact to be deployed to the bucket during CDK deployment.
51
+ *
52
+ * @default - none
53
+ */
54
+ source?: ISource;
55
+ }
56
+ /**
57
+ * Resource to deploy a webapp from a build artifact into an existing
58
+ * S3 Bucket and CloudFront Distribution.
59
+ */
60
+ export declare class WebappDeploy extends cdk.Construct {
61
+ readonly deployFn: lambda.Function;
62
+ constructor(scope: cdk.Construct, id: string, props: WebappDeployProps);
63
+ }
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebappDeploy = void 0;
4
+ const iam = require("@aws-cdk/aws-iam");
5
+ const lambda = require("@aws-cdk/aws-lambda");
6
+ const cdk = require("@aws-cdk/core");
7
+ const custom_resources_1 = require("@aws-cdk/custom-resources");
8
+ const path = require("path");
9
+ /**
10
+ * Resource to deploy a webapp from a build artifact into an existing
11
+ * S3 Bucket and CloudFront Distribution.
12
+ */
13
+ class WebappDeploy extends cdk.Construct {
14
+ constructor(scope, id, props) {
15
+ var _a, _b;
16
+ super(scope, id);
17
+ const environment = {
18
+ DEPLOY_LOG_BUCKET_URL: `s3://${props.webBucket.bucketName}/deployments.log`,
19
+ EXPIRE_SECONDS: ((_a = props.pruneDeploymentsOlderThan) !== null && _a !== void 0 ? _a : cdk.Duration.days(5))
20
+ .toSeconds()
21
+ .toString(),
22
+ TARGET_BUCKET_URL: `s3://${props.webBucket.bucketName}/web`,
23
+ };
24
+ if (props.distribution != null) {
25
+ environment.CF_DISTRIBUTION_ID = props.distribution.distributionId;
26
+ }
27
+ if (props.excludePattern != null) {
28
+ environment.EXCLUDE_PATTERN = props.excludePattern;
29
+ }
30
+ this.deployFn = new lambda.Function(this, "Resource", {
31
+ code: lambda.Code.fromAsset(path.join(__dirname, "../dist")),
32
+ environment,
33
+ functionName: (_b = props.functionName) !== null && _b !== void 0 ? _b : cdk.PhysicalName.GENERATE_IF_NEEDED,
34
+ handler: "webapp_deploy.main.handler",
35
+ reservedConcurrentExecutions: 1,
36
+ runtime: lambda.Runtime.PYTHON_3_8,
37
+ timeout: cdk.Duration.minutes(2),
38
+ initialPolicy: [
39
+ new iam.PolicyStatement({
40
+ actions: ["cloudfront:CreateInvalidation"],
41
+ // Cannot be restricted
42
+ resources: ["*"],
43
+ }),
44
+ ],
45
+ });
46
+ props.webBucket.grantReadWrite(this.deployFn);
47
+ if (props.buildsBucket) {
48
+ props.buildsBucket.grantRead(this.deployFn);
49
+ }
50
+ if (props.source) {
51
+ const source = props.source.bind(this, {
52
+ handlerRole: this.deployFn.role,
53
+ });
54
+ new custom_resources_1.AwsCustomResource(this, "CustomResource", {
55
+ onUpdate: {
56
+ service: "Lambda",
57
+ action: "invoke",
58
+ physicalResourceId: custom_resources_1.PhysicalResourceId.of("webapp-deploy"),
59
+ parameters: {
60
+ FunctionName: this.deployFn.functionName,
61
+ Payload: cdk.Stack.of(scope).toJsonString({
62
+ artifactS3Url: `s3://${source.bucket.bucketName}/${source.zipObjectKey}`,
63
+ }),
64
+ },
65
+ },
66
+ policy: custom_resources_1.AwsCustomResourcePolicy.fromStatements([
67
+ new iam.PolicyStatement({
68
+ actions: ["lambda:InvokeFunction"],
69
+ resources: [this.deployFn.functionArn],
70
+ }),
71
+ ]),
72
+ installLatestAwsSdk: false,
73
+ });
74
+ }
75
+ }
76
+ }
77
+ exports.WebappDeploy = WebappDeploy;
78
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViYXBwLWRlcGxveS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy93ZWJhcHAtZGVwbG95LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHdDQUF1QztBQUN2Qyw4Q0FBNkM7QUFFN0MscUNBQW9DO0FBQ3BDLGdFQUlrQztBQUNsQyw2QkFBNEI7QUFzRDVCOzs7R0FHRztBQUNILE1BQWEsWUFBYSxTQUFRLEdBQUcsQ0FBQyxTQUFTO0lBRzdDLFlBQVksS0FBb0IsRUFBRSxFQUFVLEVBQUUsS0FBd0I7O1FBQ3BFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUE7UUFFaEIsTUFBTSxXQUFXLEdBQTJCO1lBQzFDLHFCQUFxQixFQUFFLFFBQVEsS0FBSyxDQUFDLFNBQVMsQ0FBQyxVQUFVLGtCQUFrQjtZQUMzRSxjQUFjLEVBQUUsQ0FBQyxNQUFBLEtBQUssQ0FBQyx5QkFBeUIsbUNBQUksR0FBRyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7aUJBQ3RFLFNBQVMsRUFBRTtpQkFDWCxRQUFRLEVBQUU7WUFDYixpQkFBaUIsRUFBRSxRQUFRLEtBQUssQ0FBQyxTQUFTLENBQUMsVUFBVSxNQUFNO1NBQzVELENBQUE7UUFFRCxJQUFJLEtBQUssQ0FBQyxZQUFZLElBQUksSUFBSSxFQUFFO1lBQzlCLFdBQVcsQ0FBQyxrQkFBa0IsR0FBRyxLQUFLLENBQUMsWUFBWSxDQUFDLGNBQWMsQ0FBQTtTQUNuRTtRQUVELElBQUksS0FBSyxDQUFDLGNBQWMsSUFBSSxJQUFJLEVBQUU7WUFDaEMsV0FBVyxDQUFDLGVBQWUsR0FBRyxLQUFLLENBQUMsY0FBYyxDQUFBO1NBQ25EO1FBRUQsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRTtZQUNwRCxJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQUM7WUFDNUQsV0FBVztZQUNYLFlBQVksRUFBRSxNQUFBLEtBQUssQ0FBQyxZQUFZLG1DQUFJLEdBQUcsQ0FBQyxZQUFZLENBQUMsa0JBQWtCO1lBQ3ZFLE9BQU8sRUFBRSw0QkFBNEI7WUFDckMsNEJBQTRCLEVBQUUsQ0FBQztZQUMvQixPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxVQUFVO1lBQ2xDLE9BQU8sRUFBRSxHQUFHLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFDaEMsYUFBYSxFQUFFO2dCQUNiLElBQUksR0FBRyxDQUFDLGVBQWUsQ0FBQztvQkFDdEIsT0FBTyxFQUFFLENBQUMsK0JBQStCLENBQUM7b0JBQzFDLHVCQUF1QjtvQkFDdkIsU0FBUyxFQUFFLENBQUMsR0FBRyxDQUFDO2lCQUNqQixDQUFDO2FBQ0g7U0FDRixDQUFDLENBQUE7UUFFRixLQUFLLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7UUFFN0MsSUFBSSxLQUFLLENBQUMsWUFBWSxFQUFFO1lBQ3RCLEtBQUssQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQTtTQUM1QztRQUVELElBQUksS0FBSyxDQUFDLE1BQU0sRUFBRTtZQUNoQixNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUU7Z0JBQ3JDLFdBQVcsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUs7YUFDakMsQ0FBQyxDQUFBO1lBRUYsSUFBSSxvQ0FBaUIsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUU7Z0JBQzVDLFFBQVEsRUFBRTtvQkFDUixPQUFPLEVBQUUsUUFBUTtvQkFDakIsTUFBTSxFQUFFLFFBQVE7b0JBQ2hCLGtCQUFrQixFQUFFLHFDQUFrQixDQUFDLEVBQUUsQ0FBQyxlQUFlLENBQUM7b0JBQzFELFVBQVUsRUFBRTt3QkFDVixZQUFZLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZO3dCQUN4QyxPQUFPLEVBQUUsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsWUFBWSxDQUFDOzRCQUN4QyxhQUFhLEVBQUUsUUFBUSxNQUFNLENBQUMsTUFBTSxDQUFDLFVBQVUsSUFBSSxNQUFNLENBQUMsWUFBWSxFQUFFO3lCQUN6RSxDQUFDO3FCQUNIO2lCQUNGO2dCQUNELE1BQU0sRUFBRSwwQ0FBdUIsQ0FBQyxjQUFjLENBQUM7b0JBQzdDLElBQUksR0FBRyxDQUFDLGVBQWUsQ0FBQzt3QkFDdEIsT0FBTyxFQUFFLENBQUMsdUJBQXVCLENBQUM7d0JBQ2xDLFNBQVMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDO3FCQUN2QyxDQUFDO2lCQUNILENBQUM7Z0JBQ0YsbUJBQW1CLEVBQUUsS0FBSzthQUMzQixDQUFDLENBQUE7U0FDSDtJQUNILENBQUM7Q0FDRjtBQXhFRCxvQ0F3RUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjbG91ZGZyb250IGZyb20gXCJAYXdzLWNkay9hd3MtY2xvdWRmcm9udFwiXG5pbXBvcnQgKiBhcyBpYW0gZnJvbSBcIkBhd3MtY2RrL2F3cy1pYW1cIlxuaW1wb3J0ICogYXMgbGFtYmRhIGZyb20gXCJAYXdzLWNkay9hd3MtbGFtYmRhXCJcbmltcG9ydCAqIGFzIHMzIGZyb20gXCJAYXdzLWNkay9hd3MtczNcIlxuaW1wb3J0ICogYXMgY2RrIGZyb20gXCJAYXdzLWNkay9jb3JlXCJcbmltcG9ydCB7XG4gIEF3c0N1c3RvbVJlc291cmNlLFxuICBBd3NDdXN0b21SZXNvdXJjZVBvbGljeSxcbiAgUGh5c2ljYWxSZXNvdXJjZUlkLFxufSBmcm9tIFwiQGF3cy1jZGsvY3VzdG9tLXJlc291cmNlc1wiXG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJwYXRoXCJcbmltcG9ydCB7IElTb3VyY2UgfSBmcm9tIFwiLi9zb3VyY2VcIlxuXG5leHBvcnQgaW50ZXJmYWNlIFdlYmFwcERlcGxveVByb3BzIHtcbiAgLyoqXG4gICAqIE9wdGlvbmFsIFMzIGJ1Y2tldCB0aGF0IGNhbiBiZSB1c2VkIGZvciBkZXBsb3ltZW50IGZyb20gb3V0c2lkZSBDREsuXG4gICAqXG4gICAqIElmIHNwZWNpZmllZCBhIHBvbGljeSBpcyBhZGRlZCBzbyB0aGUgZGVwbG95IGZ1bmN0aW9uIGNhbiByZWFkIGZyb21cbiAgICogdGhlIGJ1Y2tldC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBub25lXG4gICAqL1xuICBidWlsZHNCdWNrZXQ/OiBzMy5JQnVja2V0XG4gIC8qKlxuICAgKiBDbG91ZEZyb250IERpc3RyaWJ1dGlvbiB0byBiZSBpbnZhbGlkYXRlZCBhZnRlciBkZXBsb3kuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm9uZVxuICAgKi9cbiAgZGlzdHJpYnV0aW9uPzogY2xvdWRmcm9udC5JRGlzdHJpYnV0aW9uXG4gIC8qKlxuICAgKiBSZWdleCBmb3IgcGF0dGVybnMgb2YgZmlsZXMgdG8gYmUgZGlzY2FyZGVkIGR1cmluZyBkZXBsb3ltZW50LlxuICAgKlxuICAgKiBFeGFtcGxlOiBgXFwubWFwJGAgd2lsbCBleGNsdWRlIGBqcy9teWFwcC0xYjIyYzI0OGYuanMubWFwYC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBub25lXG4gICAqL1xuICBleGNsdWRlUGF0dGVybj86IHN0cmluZ1xuICAvKipcbiAgICogVGhlIHRpbWUgd2hlbiBhIGRlcGxveW1lbnQgaXMgY29uc2lkZXJlZCBvbGQgYW5kIHdpbGwgYmUgZGVsZXRlZFxuICAgKiB1bmxlc3MgaXQgaXMgdGhlIG5ld2VzdCBvbGQgZGVwbG95bWVudC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSA1IGRheXNcbiAgICovXG4gIHBydW5lRGVwbG95bWVudHNPbGRlclRoYW4/OiBjZGsuRHVyYXRpb25cbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIGxhbWJkYSBmdW5jdGlvbiB0byBiZSBjcmVhdGVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCBjZGsuUGh5c2ljYWxOYW1lLkdFTkVSQVRFX0lGX05FRURFRFxuICAgKi9cbiAgZnVuY3Rpb25OYW1lPzogc3RyaW5nXG4gIC8qKlxuICAgKiBOYW1lIG9mIFMzIGJ1Y2tldCB3aGVyZSB0aGUgY29udGVudHMgb2YgdGhlIGFydGlmYWN0cyB3aWxsIGJlIGRlcGxveWVkLlxuICAgKiBUaGUgZmlsZXMgd2lsbCBiZSBkZXBsb3llZCB1bmRlciB0aGUga2V5IFwid2ViXCIsIHdoaWNoIGlzIHRoZW4gZXhwZWN0ZWRcbiAgICogdG8gYmUgdGhlIG9yaWdpbiBmb3IgdGhlIENsb3VkRnJvbnQgZGlzdHJpYnV0aW9uXG4gICAqL1xuICB3ZWJCdWNrZXQ6IHMzLklCdWNrZXRcbiAgLyoqXG4gICAqIFNwZWNpZmljIGFydGlmYWN0IHRvIGJlIGRlcGxveWVkIHRvIHRoZSBidWNrZXQgZHVyaW5nIENESyBkZXBsb3ltZW50LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vbmVcbiAgICovXG4gIHNvdXJjZT86IElTb3VyY2Vcbn1cblxuLyoqXG4gKiBSZXNvdXJjZSB0byBkZXBsb3kgYSB3ZWJhcHAgZnJvbSBhIGJ1aWxkIGFydGlmYWN0IGludG8gYW4gZXhpc3RpbmdcbiAqIFMzIEJ1Y2tldCBhbmQgQ2xvdWRGcm9udCBEaXN0cmlidXRpb24uXG4gKi9cbmV4cG9ydCBjbGFzcyBXZWJhcHBEZXBsb3kgZXh0ZW5kcyBjZGsuQ29uc3RydWN0IHtcbiAgcmVhZG9ubHkgZGVwbG95Rm46IGxhbWJkYS5GdW5jdGlvblxuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBjZGsuQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogV2ViYXBwRGVwbG95UHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpXG5cbiAgICBjb25zdCBlbnZpcm9ubWVudDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICAgIERFUExPWV9MT0dfQlVDS0VUX1VSTDogYHMzOi8vJHtwcm9wcy53ZWJCdWNrZXQuYnVja2V0TmFtZX0vZGVwbG95bWVudHMubG9nYCxcbiAgICAgIEVYUElSRV9TRUNPTkRTOiAocHJvcHMucHJ1bmVEZXBsb3ltZW50c09sZGVyVGhhbiA/PyBjZGsuRHVyYXRpb24uZGF5cyg1KSlcbiAgICAgICAgLnRvU2Vjb25kcygpXG4gICAgICAgIC50b1N0cmluZygpLFxuICAgICAgVEFSR0VUX0JVQ0tFVF9VUkw6IGBzMzovLyR7cHJvcHMud2ViQnVja2V0LmJ1Y2tldE5hbWV9L3dlYmAsXG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmRpc3RyaWJ1dGlvbiAhPSBudWxsKSB7XG4gICAgICBlbnZpcm9ubWVudC5DRl9ESVNUUklCVVRJT05fSUQgPSBwcm9wcy5kaXN0cmlidXRpb24uZGlzdHJpYnV0aW9uSWRcbiAgICB9XG5cbiAgICBpZiAocHJvcHMuZXhjbHVkZVBhdHRlcm4gIT0gbnVsbCkge1xuICAgICAgZW52aXJvbm1lbnQuRVhDTFVERV9QQVRURVJOID0gcHJvcHMuZXhjbHVkZVBhdHRlcm5cbiAgICB9XG5cbiAgICB0aGlzLmRlcGxveUZuID0gbmV3IGxhbWJkYS5GdW5jdGlvbih0aGlzLCBcIlJlc291cmNlXCIsIHtcbiAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChwYXRoLmpvaW4oX19kaXJuYW1lLCBcIi4uL2Rpc3RcIikpLFxuICAgICAgZW52aXJvbm1lbnQsXG4gICAgICBmdW5jdGlvbk5hbWU6IHByb3BzLmZ1bmN0aW9uTmFtZSA/PyBjZGsuUGh5c2ljYWxOYW1lLkdFTkVSQVRFX0lGX05FRURFRCxcbiAgICAgIGhhbmRsZXI6IFwid2ViYXBwX2RlcGxveS5tYWluLmhhbmRsZXJcIixcbiAgICAgIHJlc2VydmVkQ29uY3VycmVudEV4ZWN1dGlvbnM6IDEsXG4gICAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZS5QWVRIT05fM184LFxuICAgICAgdGltZW91dDogY2RrLkR1cmF0aW9uLm1pbnV0ZXMoMiksXG4gICAgICBpbml0aWFsUG9saWN5OiBbXG4gICAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICBhY3Rpb25zOiBbXCJjbG91ZGZyb250OkNyZWF0ZUludmFsaWRhdGlvblwiXSxcbiAgICAgICAgICAvLyBDYW5ub3QgYmUgcmVzdHJpY3RlZFxuICAgICAgICAgIHJlc291cmNlczogW1wiKlwiXSxcbiAgICAgICAgfSksXG4gICAgICBdLFxuICAgIH0pXG5cbiAgICBwcm9wcy53ZWJCdWNrZXQuZ3JhbnRSZWFkV3JpdGUodGhpcy5kZXBsb3lGbilcblxuICAgIGlmIChwcm9wcy5idWlsZHNCdWNrZXQpIHtcbiAgICAgIHByb3BzLmJ1aWxkc0J1Y2tldC5ncmFudFJlYWQodGhpcy5kZXBsb3lGbilcbiAgICB9XG5cbiAgICBpZiAocHJvcHMuc291cmNlKSB7XG4gICAgICBjb25zdCBzb3VyY2UgPSBwcm9wcy5zb3VyY2UuYmluZCh0aGlzLCB7XG4gICAgICAgIGhhbmRsZXJSb2xlOiB0aGlzLmRlcGxveUZuLnJvbGUhLFxuICAgICAgfSlcblxuICAgICAgbmV3IEF3c0N1c3RvbVJlc291cmNlKHRoaXMsIFwiQ3VzdG9tUmVzb3VyY2VcIiwge1xuICAgICAgICBvblVwZGF0ZToge1xuICAgICAgICAgIHNlcnZpY2U6IFwiTGFtYmRhXCIsXG4gICAgICAgICAgYWN0aW9uOiBcImludm9rZVwiLFxuICAgICAgICAgIHBoeXNpY2FsUmVzb3VyY2VJZDogUGh5c2ljYWxSZXNvdXJjZUlkLm9mKFwid2ViYXBwLWRlcGxveVwiKSxcbiAgICAgICAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICAgICAgICBGdW5jdGlvbk5hbWU6IHRoaXMuZGVwbG95Rm4uZnVuY3Rpb25OYW1lLFxuICAgICAgICAgICAgUGF5bG9hZDogY2RrLlN0YWNrLm9mKHNjb3BlKS50b0pzb25TdHJpbmcoe1xuICAgICAgICAgICAgICBhcnRpZmFjdFMzVXJsOiBgczM6Ly8ke3NvdXJjZS5idWNrZXQuYnVja2V0TmFtZX0vJHtzb3VyY2UuemlwT2JqZWN0S2V5fWAsXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBwb2xpY3k6IEF3c0N1c3RvbVJlc291cmNlUG9saWN5LmZyb21TdGF0ZW1lbnRzKFtcbiAgICAgICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgICBhY3Rpb25zOiBbXCJsYW1iZGE6SW52b2tlRnVuY3Rpb25cIl0sXG4gICAgICAgICAgICByZXNvdXJjZXM6IFt0aGlzLmRlcGxveUZuLmZ1bmN0aW9uQXJuXSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgXSksXG4gICAgICAgIGluc3RhbGxMYXRlc3RBd3NTZGs6IGZhbHNlLFxuICAgICAgfSlcbiAgICB9XG4gIH1cbn1cbiJdfQ==
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capraconsulting/webapp-deploy-lambda",
3
- "version": "1.1.1",
3
+ "version": "1.2.3",
4
4
  "description": "CDK construct for deploying a webapp release to S3 and CloudFront",
5
5
  "repository": {
6
6
  "type": "git",
@@ -12,7 +12,7 @@
12
12
  "test": "jest",
13
13
  "lint": "eslint .",
14
14
  "lint:fix": "eslint --fix .",
15
- "prepare": "npm run build",
15
+ "prepare": "npm run build && husky install",
16
16
  "semantic-release": "semantic-release"
17
17
  },
18
18
  "keywords": [
@@ -33,40 +33,40 @@
33
33
  "access": "public"
34
34
  },
35
35
  "devDependencies": {
36
- "@aws-cdk/assert": "1.46.0",
37
- "@aws-cdk/aws-iam": "1.46.0",
38
- "@aws-cdk/aws-lambda": "1.46.0",
39
- "@aws-cdk/aws-s3": "1.46.0",
40
- "@aws-cdk/core": "1.46.0",
41
- "@commitlint/cli": "9.0.1",
42
- "@commitlint/config-conventional": "9.0.1",
43
- "@liflig/cdk": "1.10.0",
44
- "@types/jest": "26.0.0",
45
- "@types/node": "13.13.12",
46
- "@typescript-eslint/eslint-plugin": "3.3.0",
47
- "@typescript-eslint/parser": "3.3.0",
48
- "eslint": "7.3.0",
49
- "eslint-config-prettier": "6.11.0",
50
- "eslint-plugin-deprecation": "1.1.0",
51
- "eslint-plugin-prettier": "3.1.4",
52
- "husky": "4.2.5",
53
- "jest": "26.0.1",
54
- "jest-cdk-snapshot": "1.3.0",
55
- "prettier": "2.0.5",
56
- "semantic-release": "17.0.8",
57
- "ts-jest": "26.1.0",
58
- "ts-node": "8.10.2",
59
- "typescript": "3.9.5"
60
- },
61
- "husky": {
62
- "hooks": {
63
- "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
64
- }
36
+ "@aws-cdk/assert": "1.135.0",
37
+ "@aws-cdk/aws-cloudfront": "1.135.0",
38
+ "@aws-cdk/aws-iam": "1.135.0",
39
+ "@aws-cdk/aws-lambda": "1.135.0",
40
+ "@aws-cdk/aws-s3": "1.135.0",
41
+ "@aws-cdk/aws-s3-assets": "1.135.0",
42
+ "@aws-cdk/core": "1.135.0",
43
+ "@aws-cdk/custom-resources": "1.135.0",
44
+ "@commitlint/cli": "13.2.1",
45
+ "@commitlint/config-conventional": "13.2.0",
46
+ "@types/jest": "27.0.3",
47
+ "@types/node": "16.11.12",
48
+ "@typescript-eslint/eslint-plugin": "4.33.0",
49
+ "@typescript-eslint/parser": "4.33.0",
50
+ "eslint": "7.32.0",
51
+ "eslint-config-prettier": "8.3.0",
52
+ "eslint-plugin-deprecation": "1.2.1",
53
+ "eslint-plugin-prettier": "4.0.0",
54
+ "husky": "7.0.4",
55
+ "jest": "27.4.3",
56
+ "jest-cdk-snapshot": "1.4.2",
57
+ "prettier": "2.5.1",
58
+ "semantic-release": "18.0.1",
59
+ "ts-jest": "27.0.7",
60
+ "ts-node": "10.4.0",
61
+ "typescript": "4.5.3"
65
62
  },
66
63
  "peerDependencies": {
64
+ "@aws-cdk/aws-cloudfront": "^1.45.0",
67
65
  "@aws-cdk/aws-iam": "^1.45.0",
68
66
  "@aws-cdk/aws-lambda": "^1.45.0",
69
67
  "@aws-cdk/aws-s3": "^1.45.0",
70
- "@aws-cdk/core": "^1.45.0"
68
+ "@aws-cdk/aws-s3-assets": "^1.45.0",
69
+ "@aws-cdk/core": "^1.45.0",
70
+ "@aws-cdk/custom-resources": "^1.45.0"
71
71
  }
72
72
  }