@capraconsulting/webapp-deploy-lambda
Version:
CDK construct for deploying a webapp release to S3 and CloudFront
66 lines • 11.2 kB
JavaScript
import * as constructs from "constructs";
import * as iam from "aws-cdk-lib/aws-iam";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as cdk from "aws-cdk-lib";
import { Provider } from "aws-cdk-lib/custom-resources";
import * as path from "path";
import { fileURLToPath } from "url";
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViYXBwLWRlcGxveS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy93ZWJhcHAtZGVwbG95LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxVQUFVLE1BQU0sWUFBWSxDQUFBO0FBRXhDLE9BQU8sS0FBSyxHQUFHLE1BQU0scUJBQXFCLENBQUE7QUFDMUMsT0FBTyxLQUFLLE1BQU0sTUFBTSx3QkFBd0IsQ0FBQTtBQUVoRCxPQUFPLEtBQUssR0FBRyxNQUFNLGFBQWEsQ0FBQTtBQUNsQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sOEJBQThCLENBQUE7QUFDdkQsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUE7QUFFNUIsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLEtBQUssQ0FBQTtBQUVuQyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7QUFxRDlEOzs7R0FHRztBQUNILE1BQU0sT0FBTyxZQUFhLFNBQVEsVUFBVSxDQUFDLFNBQVM7SUFDM0MsUUFBUSxDQUFpQjtJQUVsQyxZQUNFLEtBQTJCLEVBQzNCLEVBQVUsRUFDVixLQUF3QjtRQUV4QixLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFBO1FBRWhCLE1BQU0sV0FBVyxHQUEyQjtZQUMxQyxxQkFBcUIsRUFBRSxRQUFRLEtBQUssQ0FBQyxTQUFTLENBQUMsVUFBVSxrQkFBa0I7WUFDM0UsY0FBYyxFQUFFLENBQUMsS0FBSyxDQUFDLHlCQUF5QixJQUFJLEdBQUcsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO2lCQUN0RSxTQUFTLEVBQUU7aUJBQ1gsUUFBUSxFQUFFO1lBQ2IsaUJBQWlCLEVBQUUsUUFBUSxLQUFLLENBQUMsU0FBUyxDQUFDLFVBQVUsTUFBTTtTQUM1RCxDQUFBO1FBRUQsSUFBSSxLQUFLLENBQUMsWUFBWSxJQUFJLElBQUksRUFBRSxDQUFDO1lBQy9CLFdBQVcsQ0FBQyxrQkFBa0IsR0FBRyxLQUFLLENBQUMsWUFBWSxDQUFDLGNBQWMsQ0FBQTtRQUNwRSxDQUFDO1FBRUQsSUFBSSxLQUFLLENBQUMsY0FBYyxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ2pDLFdBQVcsQ0FBQyxlQUFlLEdBQUcsS0FBSyxDQUFDLGNBQWMsQ0FBQTtRQUNwRCxDQUFDO1FBRUQsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLHNCQUFzQixFQUFFO1lBQ2hFLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQztZQUM1RCxXQUFXO1lBQ1gsWUFBWSxFQUFFLEtBQUssQ0FBQyxZQUFZLElBQUksR0FBRyxDQUFDLFlBQVksQ0FBQyxrQkFBa0I7WUFDdkUsT0FBTyxFQUFFLDRCQUE0QjtZQUNyQyw0QkFBNEIsRUFBRSxDQUFDO1lBQy9CLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVc7WUFDbkMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUNoQyxhQUFhLEVBQUU7Z0JBQ2IsSUFBSSxHQUFHLENBQUMsZUFBZSxDQUFDO29CQUN0QixPQUFPLEVBQUUsQ0FBQywrQkFBK0IsQ0FBQztvQkFDMUMsdUJBQXVCO29CQUN2QixTQUFTLEVBQUUsQ0FBQyxHQUFHLENBQUM7aUJBQ2pCLENBQUM7YUFDSDtTQUNGLENBQUMsQ0FBQTtRQUVGLE1BQU0sUUFBUSxHQUFHLElBQUksUUFBUSxDQUFDLElBQUksRUFBRSxVQUFVLEVBQUU7WUFDOUMsY0FBYyxFQUFFLElBQUksQ0FBQyxRQUFRO1NBQzlCLENBQUMsQ0FBQTtRQUVGLEtBQUssQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUU3QyxJQUFJLEtBQUssQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUN2QixLQUFLLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDN0MsQ0FBQztRQUVELElBQUksS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2pCLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRTtnQkFDckMsV0FBVyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSzthQUNqQyxDQUFDLENBQUE7WUFDRixJQUFJLEdBQUcsQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLGdCQUFnQixFQUFFO2dCQUM3QyxZQUFZLEVBQUUsUUFBUSxDQUFDLFlBQVk7Z0JBQ25DLFVBQVUsRUFBRTtvQkFDVixhQUFhLEVBQUUsUUFBUSxNQUFNLENBQUMsTUFBTSxDQUFDLFVBQVUsSUFBSSxNQUFNLENBQUMsWUFBWSxFQUFFO2lCQUN6RTthQUNGLENBQUMsQ0FBQTtRQUNKLENBQUM7SUFDSCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjb25zdHJ1Y3RzIGZyb20gXCJjb25zdHJ1Y3RzXCJcbmltcG9ydCAqIGFzIGNsb3VkZnJvbnQgZnJvbSBcImF3cy1jZGstbGliL2F3cy1jbG91ZGZyb250XCJcbmltcG9ydCAqIGFzIGlhbSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWlhbVwiXG5pbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSBcImF3cy1jZGstbGliL2F3cy1sYW1iZGFcIlxuaW1wb3J0ICogYXMgczMgZnJvbSBcImF3cy1jZGstbGliL2F3cy1zM1wiXG5pbXBvcnQgKiBhcyBjZGsgZnJvbSBcImF3cy1jZGstbGliXCJcbmltcG9ydCB7IFByb3ZpZGVyIH0gZnJvbSBcImF3cy1jZGstbGliL2N1c3RvbS1yZXNvdXJjZXNcIlxuaW1wb3J0ICogYXMgcGF0aCBmcm9tIFwicGF0aFwiXG5pbXBvcnQgeyBJU291cmNlIH0gZnJvbSBcIi4vc291cmNlXCJcbmltcG9ydCB7IGZpbGVVUkxUb1BhdGggfSBmcm9tIFwidXJsXCJcblxuY29uc3QgX19kaXJuYW1lID0gcGF0aC5kaXJuYW1lKGZpbGVVUkxUb1BhdGgoaW1wb3J0Lm1ldGEudXJsKSlcblxuZXhwb3J0IGludGVyZmFjZSBXZWJhcHBEZXBsb3lQcm9wcyB7XG4gIC8qKlxuICAgKiBPcHRpb25hbCBTMyBidWNrZXQgdGhhdCBjYW4gYmUgdXNlZCBmb3IgZGVwbG95bWVudCBmcm9tIG91dHNpZGUgQ0RLLlxuICAgKlxuICAgKiBJZiBzcGVjaWZpZWQgYSBwb2xpY3kgaXMgYWRkZWQgc28gdGhlIGRlcGxveSBmdW5jdGlvbiBjYW4gcmVhZCBmcm9tXG4gICAqIHRoZSBidWNrZXQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm9uZVxuICAgKi9cbiAgYnVpbGRzQnVja2V0PzogczMuSUJ1Y2tldFxuICAvKipcbiAgICogQ2xvdWRGcm9udCBEaXN0cmlidXRpb24gdG8gYmUgaW52YWxpZGF0ZWQgYWZ0ZXIgZGVwbG95LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vbmVcbiAgICovXG4gIGRpc3RyaWJ1dGlvbj86IGNsb3VkZnJvbnQuSURpc3RyaWJ1dGlvblxuICAvKipcbiAgICogUmVnZXggZm9yIHBhdHRlcm5zIG9mIGZpbGVzIHRvIGJlIGRpc2NhcmRlZCBkdXJpbmcgZGVwbG95bWVudC5cbiAgICpcbiAgICogRXhhbXBsZTogYFxcLm1hcCRgIHdpbGwgZXhjbHVkZSBganMvbXlhcHAtMWIyMmMyNDhmLmpzLm1hcGAuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm9uZVxuICAgKi9cbiAgZXhjbHVkZVBhdHRlcm4/OiBzdHJpbmdcbiAgLyoqXG4gICAqIFRoZSB0aW1lIHdoZW4gYSBkZXBsb3ltZW50IGlzIGNvbnNpZGVyZWQgb2xkIGFuZCB3aWxsIGJlIGRlbGV0ZWRcbiAgICogdW5sZXNzIGl0IGlzIHRoZSBuZXdlc3Qgb2xkIGRlcGxveW1lbnQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gNSBkYXlzXG4gICAqL1xuICBwcnVuZURlcGxveW1lbnRzT2xkZXJUaGFuPzogY2RrLkR1cmF0aW9uXG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoZSBsYW1iZGEgZnVuY3Rpb24gdG8gYmUgY3JlYXRlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgY2RrLlBoeXNpY2FsTmFtZS5HRU5FUkFURV9JRl9ORUVERURcbiAgICovXG4gIGZ1bmN0aW9uTmFtZT86IHN0cmluZ1xuICAvKipcbiAgICogTmFtZSBvZiBTMyBidWNrZXQgd2hlcmUgdGhlIGNvbnRlbnRzIG9mIHRoZSBhcnRpZmFjdHMgd2lsbCBiZSBkZXBsb3llZC5cbiAgICogVGhlIGZpbGVzIHdpbGwgYmUgZGVwbG95ZWQgdW5kZXIgdGhlIGtleSBcIndlYlwiLCB3aGljaCBpcyB0aGVuIGV4cGVjdGVkXG4gICAqIHRvIGJlIHRoZSBvcmlnaW4gZm9yIHRoZSBDbG91ZEZyb250IGRpc3RyaWJ1dGlvblxuICAgKi9cbiAgd2ViQnVja2V0OiBzMy5JQnVja2V0XG4gIC8qKlxuICAgKiBTcGVjaWZpYyBhcnRpZmFjdCB0byBiZSBkZXBsb3llZCB0byB0aGUgYnVja2V0IGR1cmluZyBDREsgZGVwbG95bWVudC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBub25lXG4gICAqL1xuICBzb3VyY2U/OiBJU291cmNlXG59XG5cbi8qKlxuICogUmVzb3VyY2UgdG8gZGVwbG95IGEgd2ViYXBwIGZyb20gYSBidWlsZCBhcnRpZmFjdCBpbnRvIGFuIGV4aXN0aW5nXG4gKiBTMyBCdWNrZXQgYW5kIENsb3VkRnJvbnQgRGlzdHJpYnV0aW9uLlxuICovXG5leHBvcnQgY2xhc3MgV2ViYXBwRGVwbG95IGV4dGVuZHMgY29uc3RydWN0cy5Db25zdHJ1Y3Qge1xuICByZWFkb25seSBkZXBsb3lGbjogbGFtYmRhLkZ1bmN0aW9uXG5cbiAgY29uc3RydWN0b3IoXG4gICAgc2NvcGU6IGNvbnN0cnVjdHMuQ29uc3RydWN0LFxuICAgIGlkOiBzdHJpbmcsXG4gICAgcHJvcHM6IFdlYmFwcERlcGxveVByb3BzLFxuICApIHtcbiAgICBzdXBlcihzY29wZSwgaWQpXG5cbiAgICBjb25zdCBlbnZpcm9ubWVudDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICAgIERFUExPWV9MT0dfQlVDS0VUX1VSTDogYHMzOi8vJHtwcm9wcy53ZWJCdWNrZXQuYnVja2V0TmFtZX0vZGVwbG95bWVudHMubG9nYCxcbiAgICAgIEVYUElSRV9TRUNPTkRTOiAocHJvcHMucHJ1bmVEZXBsb3ltZW50c09sZGVyVGhhbiA/PyBjZGsuRHVyYXRpb24uZGF5cyg1KSlcbiAgICAgICAgLnRvU2Vjb25kcygpXG4gICAgICAgIC50b1N0cmluZygpLFxuICAgICAgVEFSR0VUX0JVQ0tFVF9VUkw6IGBzMzovLyR7cHJvcHMud2ViQnVja2V0LmJ1Y2tldE5hbWV9L3dlYmAsXG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmRpc3RyaWJ1dGlvbiAhPSBudWxsKSB7XG4gICAgICBlbnZpcm9ubWVudC5DRl9ESVNUUklCVVRJT05fSUQgPSBwcm9wcy5kaXN0cmlidXRpb24uZGlzdHJpYnV0aW9uSWRcbiAgICB9XG5cbiAgICBpZiAocHJvcHMuZXhjbHVkZVBhdHRlcm4gIT0gbnVsbCkge1xuICAgICAgZW52aXJvbm1lbnQuRVhDTFVERV9QQVRURVJOID0gcHJvcHMuZXhjbHVkZVBhdHRlcm5cbiAgICB9XG5cbiAgICB0aGlzLmRlcGxveUZuID0gbmV3IGxhbWJkYS5GdW5jdGlvbih0aGlzLCBcIldlYmFwcERlcGxveVJlc291cmNlXCIsIHtcbiAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChwYXRoLmpvaW4oX19kaXJuYW1lLCBcIi4uL2Rpc3RcIikpLFxuICAgICAgZW52aXJvbm1lbnQsXG4gICAgICBmdW5jdGlvbk5hbWU6IHByb3BzLmZ1bmN0aW9uTmFtZSA/PyBjZGsuUGh5c2ljYWxOYW1lLkdFTkVSQVRFX0lGX05FRURFRCxcbiAgICAgIGhhbmRsZXI6IFwid2ViYXBwX2RlcGxveS5tYWluLmhhbmRsZXJcIixcbiAgICAgIHJlc2VydmVkQ29uY3VycmVudEV4ZWN1dGlvbnM6IDEsXG4gICAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZS5QWVRIT05fM18xMixcbiAgICAgIHRpbWVvdXQ6IGNkay5EdXJhdGlvbi5taW51dGVzKDIpLFxuICAgICAgaW5pdGlhbFBvbGljeTogW1xuICAgICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgYWN0aW9uczogW1wiY2xvdWRmcm9udDpDcmVhdGVJbnZhbGlkYXRpb25cIl0sXG4gICAgICAgICAgLy8gQ2Fubm90IGJlIHJlc3RyaWN0ZWRcbiAgICAgICAgICByZXNvdXJjZXM6IFtcIipcIl0sXG4gICAgICAgIH0pLFxuICAgICAgXSxcbiAgICB9KVxuXG4gICAgY29uc3QgcHJvdmlkZXIgPSBuZXcgUHJvdmlkZXIodGhpcywgXCJQcm92aWRlclwiLCB7XG4gICAgICBvbkV2ZW50SGFuZGxlcjogdGhpcy5kZXBsb3lGbixcbiAgICB9KVxuXG4gICAgcHJvcHMud2ViQnVja2V0LmdyYW50UmVhZFdyaXRlKHRoaXMuZGVwbG95Rm4pXG5cbiAgICBpZiAocHJvcHMuYnVpbGRzQnVja2V0KSB7XG4gICAgICBwcm9wcy5idWlsZHNCdWNrZXQuZ3JhbnRSZWFkKHRoaXMuZGVwbG95Rm4pXG4gICAgfVxuXG4gICAgaWYgKHByb3BzLnNvdXJjZSkge1xuICAgICAgY29uc3Qgc291cmNlID0gcHJvcHMuc291cmNlLmJpbmQodGhpcywge1xuICAgICAgICBoYW5kbGVyUm9sZTogdGhpcy5kZXBsb3lGbi5yb2xlISxcbiAgICAgIH0pXG4gICAgICBuZXcgY2RrLkN1c3RvbVJlc291cmNlKHRoaXMsIFwiQ3VzdG9tUmVzb3VyY2VcIiwge1xuICAgICAgICBzZXJ2aWNlVG9rZW46IHByb3ZpZGVyLnNlcnZpY2VUb2tlbixcbiAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgIGFydGlmYWN0UzNVcmw6IGBzMzovLyR7c291cmNlLmJ1Y2tldC5idWNrZXROYW1lfS8ke3NvdXJjZS56aXBPYmplY3RLZXl9YCxcbiAgICAgICAgfSxcbiAgICAgIH0pXG4gICAgfVxuICB9XG59XG4iXX0=