UNPKG

@capraconsulting/webapp-deploy-lambda

Version:

CDK construct for deploying a webapp release to S3 and CloudFront

66 lines 11.2 kB
import * as path from "node:path"; import { fileURLToPath } from "node:url"; import * as cdk from "aws-cdk-lib"; import * as iam from "aws-cdk-lib/aws-iam"; import * as lambda from "aws-cdk-lib/aws-lambda"; import { Provider } from "aws-cdk-lib/custom-resources"; import * as constructs from "constructs"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); /** * Resource to deploy a webapp from a build artifact into an existing * S3 Bucket and CloudFront Distribution. */ export class WebappDeploy extends constructs.Construct { deployFn; constructor(scope, id, props) { super(scope, id); const environment = { DEPLOY_LOG_BUCKET_URL: `s3://${props.webBucket.bucketName}/deployments.log`, EXPIRE_SECONDS: (props.pruneDeploymentsOlderThan ?? cdk.Duration.days(5)) .toSeconds() .toString(), TARGET_BUCKET_URL: `s3://${props.webBucket.bucketName}/web`, }; if (props.distribution != null) { environment.CF_DISTRIBUTION_ID = props.distribution.distributionId; } if (props.excludePattern != null) { environment.EXCLUDE_PATTERN = props.excludePattern; } this.deployFn = new lambda.Function(this, "WebappDeployResource", { code: lambda.Code.fromAsset(path.join(__dirname, "../dist")), environment, functionName: props.functionName ?? cdk.PhysicalName.GENERATE_IF_NEEDED, handler: "webapp_deploy.main.handler", reservedConcurrentExecutions: 1, runtime: lambda.Runtime.PYTHON_3_12, timeout: cdk.Duration.minutes(2), initialPolicy: [ new iam.PolicyStatement({ actions: ["cloudfront:CreateInvalidation"], // Cannot be restricted resources: ["*"], }), ], }); const provider = new Provider(this, "Provider", { onEventHandler: this.deployFn, }); props.webBucket.grantReadWrite(this.deployFn); if (props.buildsBucket) { props.buildsBucket.grantRead(this.deployFn); } if (props.source) { const source = props.source.bind(this, { handlerRole: this.deployFn.role, }); new cdk.CustomResource(this, "CustomResource", { serviceToken: provider.serviceToken, properties: { artifactS3Url: `s3://${source.bucket.bucketName}/${source.zipObjectKey}`, }, }); } } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViYXBwLWRlcGxveS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy93ZWJhcHAtZGVwbG95LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFBO0FBQ2pDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxVQUFVLENBQUE7QUFDeEMsT0FBTyxLQUFLLEdBQUcsTUFBTSxhQUFhLENBQUE7QUFFbEMsT0FBTyxLQUFLLEdBQUcsTUFBTSxxQkFBcUIsQ0FBQTtBQUMxQyxPQUFPLEtBQUssTUFBTSxNQUFNLHdCQUF3QixDQUFBO0FBRWhELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQTtBQUN2RCxPQUFPLEtBQUssVUFBVSxNQUFNLFlBQVksQ0FBQTtBQUd4QyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7QUFxRDlEOzs7R0FHRztBQUNILE1BQU0sT0FBTyxZQUFhLFNBQVEsVUFBVSxDQUFDLFNBQVM7SUFDM0MsUUFBUSxDQUFpQjtJQUVsQyxZQUNFLEtBQTJCLEVBQzNCLEVBQVUsRUFDVixLQUF3QjtRQUV4QixLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFBO1FBRWhCLE1BQU0sV0FBVyxHQUEyQjtZQUMxQyxxQkFBcUIsRUFBRSxRQUFRLEtBQUssQ0FBQyxTQUFTLENBQUMsVUFBVSxrQkFBa0I7WUFDM0UsY0FBYyxFQUFFLENBQUMsS0FBSyxDQUFDLHlCQUF5QixJQUFJLEdBQUcsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO2lCQUN0RSxTQUFTLEVBQUU7aUJBQ1gsUUFBUSxFQUFFO1lBQ2IsaUJBQWlCLEVBQUUsUUFBUSxLQUFLLENBQUMsU0FBUyxDQUFDLFVBQVUsTUFBTTtTQUM1RCxDQUFBO1FBRUQsSUFBSSxLQUFLLENBQUMsWUFBWSxJQUFJLElBQUksRUFBRSxDQUFDO1lBQy9CLFdBQVcsQ0FBQyxrQkFBa0IsR0FBRyxLQUFLLENBQUMsWUFBWSxDQUFDLGNBQWMsQ0FBQTtRQUNwRSxDQUFDO1FBRUQsSUFBSSxLQUFLLENBQUMsY0FBYyxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ2pDLFdBQVcsQ0FBQyxlQUFlLEdBQUcsS0FBSyxDQUFDLGNBQWMsQ0FBQTtRQUNwRCxDQUFDO1FBRUQsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLHNCQUFzQixFQUFFO1lBQ2hFLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQztZQUM1RCxXQUFXO1lBQ1gsWUFBWSxFQUFFLEtBQUssQ0FBQyxZQUFZLElBQUksR0FBRyxDQUFDLFlBQVksQ0FBQyxrQkFBa0I7WUFDdkUsT0FBTyxFQUFFLDRCQUE0QjtZQUNyQyw0QkFBNEIsRUFBRSxDQUFDO1lBQy9CLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVc7WUFDbkMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUNoQyxhQUFhLEVBQUU7Z0JBQ2IsSUFBSSxHQUFHLENBQUMsZUFBZSxDQUFDO29CQUN0QixPQUFPLEVBQUUsQ0FBQywrQkFBK0IsQ0FBQztvQkFDMUMsdUJBQXVCO29CQUN2QixTQUFTLEVBQUUsQ0FBQyxHQUFHLENBQUM7aUJBQ2pCLENBQUM7YUFDSDtTQUNGLENBQUMsQ0FBQTtRQUVGLE1BQU0sUUFBUSxHQUFHLElBQUksUUFBUSxDQUFDLElBQUksRUFBRSxVQUFVLEVBQUU7WUFDOUMsY0FBYyxFQUFFLElBQUksQ0FBQyxRQUFRO1NBQzlCLENBQUMsQ0FBQTtRQUVGLEtBQUssQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUU3QyxJQUFJLEtBQUssQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUN2QixLQUFLLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDN0MsQ0FBQztRQUVELElBQUksS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2pCLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRTtnQkFDckMsV0FBVyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSzthQUNqQyxDQUFDLENBQUE7WUFDRixJQUFJLEdBQUcsQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLGdCQUFnQixFQUFFO2dCQUM3QyxZQUFZLEVBQUUsUUFBUSxDQUFDLFlBQVk7Z0JBQ25DLFVBQVUsRUFBRTtvQkFDVixhQUFhLEVBQUUsUUFBUSxNQUFNLENBQUMsTUFBTSxDQUFDLFVBQVUsSUFBSSxNQUFNLENBQUMsWUFBWSxFQUFFO2lCQUN6RTthQUNGLENBQUMsQ0FBQTtRQUNKLENBQUM7SUFDSCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJub2RlOnBhdGhcIlxuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCB9IGZyb20gXCJub2RlOnVybFwiXG5pbXBvcnQgKiBhcyBjZGsgZnJvbSBcImF3cy1jZGstbGliXCJcbmltcG9ydCB0eXBlICogYXMgY2xvdWRmcm9udCBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNsb3VkZnJvbnRcIlxuaW1wb3J0ICogYXMgaWFtIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtaWFtXCJcbmltcG9ydCAqIGFzIGxhbWJkYSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWxhbWJkYVwiXG5pbXBvcnQgdHlwZSAqIGFzIHMzIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtczNcIlxuaW1wb3J0IHsgUHJvdmlkZXIgfSBmcm9tIFwiYXdzLWNkay1saWIvY3VzdG9tLXJlc291cmNlc1wiXG5pbXBvcnQgKiBhcyBjb25zdHJ1Y3RzIGZyb20gXCJjb25zdHJ1Y3RzXCJcbmltcG9ydCB0eXBlIHsgSVNvdXJjZSB9IGZyb20gXCIuL3NvdXJjZVwiXG5cbmNvbnN0IF9fZGlybmFtZSA9IHBhdGguZGlybmFtZShmaWxlVVJMVG9QYXRoKGltcG9ydC5tZXRhLnVybCkpXG5cbmV4cG9ydCBpbnRlcmZhY2UgV2ViYXBwRGVwbG95UHJvcHMge1xuICAvKipcbiAgICogT3B0aW9uYWwgUzMgYnVja2V0IHRoYXQgY2FuIGJlIHVzZWQgZm9yIGRlcGxveW1lbnQgZnJvbSBvdXRzaWRlIENESy5cbiAgICpcbiAgICogSWYgc3BlY2lmaWVkIGEgcG9saWN5IGlzIGFkZGVkIHNvIHRoZSBkZXBsb3kgZnVuY3Rpb24gY2FuIHJlYWQgZnJvbVxuICAgKiB0aGUgYnVja2V0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vbmVcbiAgICovXG4gIGJ1aWxkc0J1Y2tldD86IHMzLklCdWNrZXRcbiAgLyoqXG4gICAqIENsb3VkRnJvbnQgRGlzdHJpYnV0aW9uIHRvIGJlIGludmFsaWRhdGVkIGFmdGVyIGRlcGxveS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBub25lXG4gICAqL1xuICBkaXN0cmlidXRpb24/OiBjbG91ZGZyb250LklEaXN0cmlidXRpb25cbiAgLyoqXG4gICAqIFJlZ2V4IGZvciBwYXR0ZXJucyBvZiBmaWxlcyB0byBiZSBkaXNjYXJkZWQgZHVyaW5nIGRlcGxveW1lbnQuXG4gICAqXG4gICAqIEV4YW1wbGU6IGBcXC5tYXAkYCB3aWxsIGV4Y2x1ZGUgYGpzL215YXBwLTFiMjJjMjQ4Zi5qcy5tYXBgLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vbmVcbiAgICovXG4gIGV4Y2x1ZGVQYXR0ZXJuPzogc3RyaW5nXG4gIC8qKlxuICAgKiBUaGUgdGltZSB3aGVuIGEgZGVwbG95bWVudCBpcyBjb25zaWRlcmVkIG9sZCBhbmQgd2lsbCBiZSBkZWxldGVkXG4gICAqIHVubGVzcyBpdCBpcyB0aGUgbmV3ZXN0IG9sZCBkZXBsb3ltZW50LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIDUgZGF5c1xuICAgKi9cbiAgcHJ1bmVEZXBsb3ltZW50c09sZGVyVGhhbj86IGNkay5EdXJhdGlvblxuICAvKipcbiAgICogTmFtZSBvZiB0aGUgbGFtYmRhIGZ1bmN0aW9uIHRvIGJlIGNyZWF0ZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IGNkay5QaHlzaWNhbE5hbWUuR0VORVJBVEVfSUZfTkVFREVEXG4gICAqL1xuICBmdW5jdGlvbk5hbWU/OiBzdHJpbmdcbiAgLyoqXG4gICAqIE5hbWUgb2YgUzMgYnVja2V0IHdoZXJlIHRoZSBjb250ZW50cyBvZiB0aGUgYXJ0aWZhY3RzIHdpbGwgYmUgZGVwbG95ZWQuXG4gICAqIFRoZSBmaWxlcyB3aWxsIGJlIGRlcGxveWVkIHVuZGVyIHRoZSBrZXkgXCJ3ZWJcIiwgd2hpY2ggaXMgdGhlbiBleHBlY3RlZFxuICAgKiB0byBiZSB0aGUgb3JpZ2luIGZvciB0aGUgQ2xvdWRGcm9udCBkaXN0cmlidXRpb25cbiAgICovXG4gIHdlYkJ1Y2tldDogczMuSUJ1Y2tldFxuICAvKipcbiAgICogU3BlY2lmaWMgYXJ0aWZhY3QgdG8gYmUgZGVwbG95ZWQgdG8gdGhlIGJ1Y2tldCBkdXJpbmcgQ0RLIGRlcGxveW1lbnQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm9uZVxuICAgKi9cbiAgc291cmNlPzogSVNvdXJjZVxufVxuXG4vKipcbiAqIFJlc291cmNlIHRvIGRlcGxveSBhIHdlYmFwcCBmcm9tIGEgYnVpbGQgYXJ0aWZhY3QgaW50byBhbiBleGlzdGluZ1xuICogUzMgQnVja2V0IGFuZCBDbG91ZEZyb250IERpc3RyaWJ1dGlvbi5cbiAqL1xuZXhwb3J0IGNsYXNzIFdlYmFwcERlcGxveSBleHRlbmRzIGNvbnN0cnVjdHMuQ29uc3RydWN0IHtcbiAgcmVhZG9ubHkgZGVwbG95Rm46IGxhbWJkYS5GdW5jdGlvblxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHNjb3BlOiBjb25zdHJ1Y3RzLkNvbnN0cnVjdCxcbiAgICBpZDogc3RyaW5nLFxuICAgIHByb3BzOiBXZWJhcHBEZXBsb3lQcm9wcyxcbiAgKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKVxuXG4gICAgY29uc3QgZW52aXJvbm1lbnQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgICBERVBMT1lfTE9HX0JVQ0tFVF9VUkw6IGBzMzovLyR7cHJvcHMud2ViQnVja2V0LmJ1Y2tldE5hbWV9L2RlcGxveW1lbnRzLmxvZ2AsXG4gICAgICBFWFBJUkVfU0VDT05EUzogKHByb3BzLnBydW5lRGVwbG95bWVudHNPbGRlclRoYW4gPz8gY2RrLkR1cmF0aW9uLmRheXMoNSkpXG4gICAgICAgIC50b1NlY29uZHMoKVxuICAgICAgICAudG9TdHJpbmcoKSxcbiAgICAgIFRBUkdFVF9CVUNLRVRfVVJMOiBgczM6Ly8ke3Byb3BzLndlYkJ1Y2tldC5idWNrZXROYW1lfS93ZWJgLFxuICAgIH1cblxuICAgIGlmIChwcm9wcy5kaXN0cmlidXRpb24gIT0gbnVsbCkge1xuICAgICAgZW52aXJvbm1lbnQuQ0ZfRElTVFJJQlVUSU9OX0lEID0gcHJvcHMuZGlzdHJpYnV0aW9uLmRpc3RyaWJ1dGlvbklkXG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmV4Y2x1ZGVQYXR0ZXJuICE9IG51bGwpIHtcbiAgICAgIGVudmlyb25tZW50LkVYQ0xVREVfUEFUVEVSTiA9IHByb3BzLmV4Y2x1ZGVQYXR0ZXJuXG4gICAgfVxuXG4gICAgdGhpcy5kZXBsb3lGbiA9IG5ldyBsYW1iZGEuRnVuY3Rpb24odGhpcywgXCJXZWJhcHBEZXBsb3lSZXNvdXJjZVwiLCB7XG4gICAgICBjb2RlOiBsYW1iZGEuQ29kZS5mcm9tQXNzZXQocGF0aC5qb2luKF9fZGlybmFtZSwgXCIuLi9kaXN0XCIpKSxcbiAgICAgIGVudmlyb25tZW50LFxuICAgICAgZnVuY3Rpb25OYW1lOiBwcm9wcy5mdW5jdGlvbk5hbWUgPz8gY2RrLlBoeXNpY2FsTmFtZS5HRU5FUkFURV9JRl9ORUVERUQsXG4gICAgICBoYW5kbGVyOiBcIndlYmFwcF9kZXBsb3kubWFpbi5oYW5kbGVyXCIsXG4gICAgICByZXNlcnZlZENvbmN1cnJlbnRFeGVjdXRpb25zOiAxLFxuICAgICAgcnVudGltZTogbGFtYmRhLlJ1bnRpbWUuUFlUSE9OXzNfMTIsXG4gICAgICB0aW1lb3V0OiBjZGsuRHVyYXRpb24ubWludXRlcygyKSxcbiAgICAgIGluaXRpYWxQb2xpY3k6IFtcbiAgICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGFjdGlvbnM6IFtcImNsb3VkZnJvbnQ6Q3JlYXRlSW52YWxpZGF0aW9uXCJdLFxuICAgICAgICAgIC8vIENhbm5vdCBiZSByZXN0cmljdGVkXG4gICAgICAgICAgcmVzb3VyY2VzOiBbXCIqXCJdLFxuICAgICAgICB9KSxcbiAgICAgIF0sXG4gICAgfSlcblxuICAgIGNvbnN0IHByb3ZpZGVyID0gbmV3IFByb3ZpZGVyKHRoaXMsIFwiUHJvdmlkZXJcIiwge1xuICAgICAgb25FdmVudEhhbmRsZXI6IHRoaXMuZGVwbG95Rm4sXG4gICAgfSlcblxuICAgIHByb3BzLndlYkJ1Y2tldC5ncmFudFJlYWRXcml0ZSh0aGlzLmRlcGxveUZuKVxuXG4gICAgaWYgKHByb3BzLmJ1aWxkc0J1Y2tldCkge1xuICAgICAgcHJvcHMuYnVpbGRzQnVja2V0LmdyYW50UmVhZCh0aGlzLmRlcGxveUZuKVxuICAgIH1cblxuICAgIGlmIChwcm9wcy5zb3VyY2UpIHtcbiAgICAgIGNvbnN0IHNvdXJjZSA9IHByb3BzLnNvdXJjZS5iaW5kKHRoaXMsIHtcbiAgICAgICAgaGFuZGxlclJvbGU6IHRoaXMuZGVwbG95Rm4ucm9sZSEsXG4gICAgICB9KVxuICAgICAgbmV3IGNkay5DdXN0b21SZXNvdXJjZSh0aGlzLCBcIkN1c3RvbVJlc291cmNlXCIsIHtcbiAgICAgICAgc2VydmljZVRva2VuOiBwcm92aWRlci5zZXJ2aWNlVG9rZW4sXG4gICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICBhcnRpZmFjdFMzVXJsOiBgczM6Ly8ke3NvdXJjZS5idWNrZXQuYnVja2V0TmFtZX0vJHtzb3VyY2UuemlwT2JqZWN0S2V5fWAsXG4gICAgICAgIH0sXG4gICAgICB9KVxuICAgIH1cbiAgfVxufVxuIl19