@capraconsulting/webapp-deploy-lambda
Version:
CDK construct for deploying a webapp release to S3 and CloudFront
66 lines • 11.2 kB
JavaScript
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