From 16e900e5df8d4caae00018e8e69243e82980977f Mon Sep 17 00:00:00 2001 From: Jeff Avallone Date: Tue, 29 May 2018 17:08:22 -0400 Subject: [PATCH] Invalidating CloudFront cache when deploying --- README.md | 1 + deploy.config.js | 3 ++- script/s3-upload.js | 46 ++++++++++++++++++++++++++++++--------------- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 9e8571d..9510ef0 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ Several environment variables are used to configure the application at build-tim * `GA_PROPERTY` - Google Analytics property ID. * `SENTRY_KEY` - Sentry.io DSN key for error reporting. * `CIRCLE_BRANCH`, `CIRCLE_BUILD_NUM`, and `CIRCLE_SHA1` - CircleCI values used to generate build ID. Displayed in application footer and used in Sentry.io error reports. +* `CLOUD_FRONT_ID` - AWS CloudFront distribution ID to invalidating when running `yarn deploy` * `DEPLOY_BUCKET` - AWS S3 bucket to deploy application to when running `yarn deploy`. * `DEPLOY_ENV` - Environment the applicatoin will be deployed to. Used to report environment in Sentry.io error reports. Typically set to either "preview" or "production". * `BANNER` - Text to display in header banner. Generally generated from `NODE_ENV` diff --git a/deploy.config.js b/deploy.config.js index d084cf1..a31c223 100644 --- a/deploy.config.js +++ b/deploy.config.js @@ -1,7 +1,8 @@ const path = require('path'); module.exports = { - bucket: process.env.DEPLOY_BUCKET, + s3Bucket: process.env.DEPLOY_BUCKET, + cloudFrontId: process.env.CLOUD_FRONT_ID, deployFrom: path.resolve(__dirname, 'build'), paths: [ { diff --git a/script/s3-upload.js b/script/s3-upload.js index 8682041..8646307 100644 --- a/script/s3-upload.js +++ b/script/s3-upload.js @@ -8,6 +8,7 @@ const AWS = require('aws-sdk'); const mime = require('mime-types'); const s3 = new AWS.S3(); +const cloudFront = new AWS.CloudFront(); const config = require(path.resolve(process.argv[2])); const configFor = path => { @@ -49,7 +50,7 @@ Promise.all([bucketContents, uploadDetails]).then(([bucket, upload]) => { const uploadPromises = upload.map(params => { console.log(`Starting upload for ${ params.Key }`); return s3.upload({ - Bucket: config.bucket, + Bucket: config.s3Bucket, ...params }).promise() .then(() => console.log(colors.green(`${ params.Key } successful`))) @@ -59,20 +60,35 @@ Promise.all([bucketContents, uploadDetails]).then(([bucket, upload]) => { }); }); - return Promise.all(uploadPromises).then(() => { - console.log(`Deleting ${ deleteKeys.length } stale files`); - return s3.deleteObjects({ - Bucket: config.bucket, - Delete: { - Objects: deleteKeys.map(key => ({ Key: key })) - } - }).promise() - .then(() => console.log(colors.green('Delete successful'))) - .catch(err => { - console.error(colors.red.bold('Delete failed')); - return Promise.reject(err); - }); - }); + return Promise.all(uploadPromises) + .then(() => { + console.log(`Deleting ${ deleteKeys.length } stale files`); + return s3.deleteObjects({ + Bucket: config.s3Bucket, + Delete: { + Objects: deleteKeys.map(key => ({ Key: key })) + } + }).promise() + .then(() => console.log(colors.green('Delete successful'))) + .catch(err => { + console.error(colors.red.bold('Delete failed')); + return Promise.reject(err); + }); + }) + .then(() => { + return cloudFront.createInvalidation({ + DistributionId: config.cloudFrontId, + InvalidationBatch: { + CallerReference: `circleci-deploy-${ process.env.CIRCLE_BRANCH }-${ process.env.CIRCLE_BUILD_NUM }-${ process.env.CIRCLE_SHA1 }`, + Paths: { + Quantity: bucket.length, + Items: [ + '/*' + ] + } + } + }).promise(); + }); }) .catch(err => { console.error(colors.red.bold('Error:'), err);