regexper-static/script/s3-upload.js

102 lines
2.9 KiB
JavaScript

/* eslint-disable no-console */
const path = require('path');
const fs = require('fs');
const colors = require('colors/safe');
const readdir = require('recursive-readdir');
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 => {
const { match, ...conf } = config.paths.find(conf => conf.match.test(path)); // eslint-disable-line no-unused-vars
return {
ContentType: mime.lookup(path) || 'application/octet-stream',
...conf
};
};
const bucketContents = s3.listObjectsV2({
Bucket: config.s3Bucket
}).promise()
.then(result => {
return result.Contents.map(item => item.Key);
})
.catch(err => {
console.error(colors.red.bold('Failed to fetch bucket contents:'), err);
process.exit(1);
});
const uploadDetails = readdir(config.deployFrom)
.then(paths => paths.map(p => {
const key = path.relative(config.deployFrom, p);
return {
Key: key,
Body: fs.createReadStream(p),
...configFor(key)
};
}))
.catch(err => {
console.error(colors.red.bold('Error:'), err);
process.exit(1);
});
Promise.all([bucketContents, uploadDetails]).then(([bucket, upload]) => {
const deleteKeys = bucket.filter(key => !upload.find(conf => key === conf.Key));
const uploadPromises = upload.map(params => {
console.log(`Starting upload for ${ params.Key }`);
return s3.upload({
Bucket: config.s3Bucket,
...params
}).promise()
.then(() => console.log(colors.green(`${ params.Key } successful`)))
.catch(err => {
console.error(colors.red.bold(`${ params.Key } failed`));
return Promise.reject(err);
});
});
return Promise.all(uploadPromises)
.then(() => {
if (deleteKeys.length === 0) {
console.log('No files to delete');
return Promise.resolve();
}
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: 1,
Items: [
'/*'
]
}
}
}).promise();
});
})
.catch(err => {
console.error(colors.red.bold('Error:'), err);
process.exit(1);
});