Deployment improvements (auto purge cache etc)

This commit is contained in:
Sam Potts 2018-07-19 09:47:11 +10:00
parent e2fb922d73
commit 13bf80d372
5 changed files with 163 additions and 66 deletions

2
.gitignore vendored
View File

@ -1,6 +1,6 @@
node_modules node_modules
.DS_Store .DS_Store
aws.json credentials.json
*.mp4 *.mp4
!dist/blank.mp4 !dist/blank.mp4
index-*.html index-*.html

View File

@ -2,7 +2,7 @@ demo
.github .github
.vscode .vscode
*.code-workspace *.code-workspace
aws.json credentials.json
bundles.json bundles.json
yarn.lock yarn.lock
package-lock.json package-lock.json

View File

@ -29,18 +29,12 @@ const sourcemaps = require('gulp-sourcemaps');
const uglify = require('gulp-uglify-es').default; const uglify = require('gulp-uglify-es').default;
const commonjs = require('rollup-plugin-commonjs'); const commonjs = require('rollup-plugin-commonjs');
const resolve = require('rollup-plugin-node-resolve'); const resolve = require('rollup-plugin-node-resolve');
const FastlyPurge = require('fastly-purge');
const through = require('through2');
const bundles = require('./bundles.json'); const bundles = require('./bundles.json');
const pkg = require('./package.json'); const pkg = require('./package.json');
// Get AWS config
let aws = {};
try {
aws = require('./aws.json'); //eslint-disable-line
} catch (e) {
// Do nothing
}
const minSuffix = '.min'; const minSuffix = '.min';
// Paths // Paths
@ -95,16 +89,18 @@ const browsers = ['> 1%'];
// Babel config // Babel config
const babelrc = { const babelrc = {
presets: [[ presets: [
'env', [
{ 'env',
targets: { {
browsers, targets: {
browsers,
},
useBuiltIns: true,
modules: false,
}, },
useBuiltIns: true, ],
modules: false, ],
},
]],
plugins: ['external-helpers'], plugins: ['external-helpers'],
babelrc: false, babelrc: false,
exclude: 'node_modules/**', exclude: 'node_modules/**',
@ -112,10 +108,9 @@ const babelrc = {
// Clean out /dist // Clean out /dist
gulp.task('clean', () => { gulp.task('clean', () => {
const dirs = [ const dirs = [paths.plyr.output, paths.demo.output].map(dir =>
paths.plyr.output, path.join(dir, '**/*'),
paths.demo.output, );
].map(dir => path.join(dir, '**/*'));
// Don't delete the mp4 // Don't delete the mp4
dirs.push(`!${path.join(paths.plyr.output, '**/*.mp4')}`); dirs.push(`!${path.join(paths.plyr.output, '**/*.mp4')}`);
@ -187,9 +182,11 @@ const build = {
.src(paths[bundle].src.sprite) .src(paths[bundle].src.sprite)
.pipe( .pipe(
svgmin({ svgmin({
plugins: [{ plugins: [
removeDesc: true, {
}], removeDesc: true,
},
],
}), }),
) )
.pipe(svgstore()) .pipe(svgstore())
@ -238,9 +235,21 @@ gulp.task('default', () => {
// Publish a version to CDN and demo // Publish a version to CDN and demo
// -------------------------------------------- // --------------------------------------------
// If aws is setup // Get deployment config
if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) { let credentials = {};
try {
credentials = require('./credentials.json'); //eslint-disable-line
} catch (e) {
// Do nothing
}
// If deployment is setup
if (
Object.keys(credentials).includes('cdn') &&
Object.keys(credentials).includes('demo')
) {
const { version } = pkg; const { version } = pkg;
const { aws, fastly } = credentials;
// Get branch info // Get branch info
const branch = { const branch = {
@ -248,10 +257,6 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) {
master: 'master', master: 'master',
develop: 'develop', develop: 'develop',
}; };
const allowed = [
branch.master,
branch.develop,
];
const maxAge = 31536000; // 1 year const maxAge = 31536000; // 1 year
const options = { const options = {
@ -264,7 +269,8 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) {
demo: { demo: {
uploadPath: branch.current === branch.develop ? 'beta/' : null, uploadPath: branch.current === branch.develop ? 'beta/' : null,
headers: { headers: {
'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0', 'Cache-Control':
'no-cache, no-store, must-revalidate, max-age=0',
Vary: 'Accept-Encoding', Vary: 'Accept-Encoding',
}, },
}, },
@ -273,27 +279,51 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) {
headers: { headers: {
// http://stackoverflow.com/questions/2272835/amazon-s3-object-redirect // http://stackoverflow.com/questions/2272835/amazon-s3-object-redirect
'x-amz-website-redirect-location': `/${ver}/${filename}`, 'x-amz-website-redirect-location': `/${ver}/${filename}`,
'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0', 'Cache-Control':
'no-cache, no-store, must-revalidate, max-age=0',
}, },
}; };
}, },
}; };
const regex = '(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*).(?:0|[1-9][0-9]*)(?:-[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?(?:\\+[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?'; const regex =
'(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*).(?:0|[1-9][0-9]*)(?:-[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?(?:\\+[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?';
const semver = new RegExp(`v${regex}`, 'gi'); const semver = new RegExp(`v${regex}`, 'gi');
const localPath = new RegExp('(../)?dist', 'gi'); const localPath = new RegExp('(../)?dist', 'gi');
const versionPath = `https://${aws.cdn.domain}/${version}`; const versionPath = `https://${aws.cdn.domain}/${version}`;
const cdnpath = new RegExp(`${aws.cdn.domain}/${regex}/`, 'gi'); const cdnpath = new RegExp(`${aws.cdn.domain}/${regex}/`, 'gi');
const renameFile = rename(p => {
p.basename = p.basename.replace(minSuffix, ''); // eslint-disable-line
p.dirname = p.dirname.replace('.', version); // eslint-disable-line
});
// Check we're on the correct branch to deploy
const canDeploy = () => {
const allowed = [branch.master, branch.develop];
if (!allowed.includes(branch.current)) {
console.error(
`Must be on ${allowed.join(', ')} to publish! (current: ${
branch.current
})`,
);
return false;
}
return true;
};
gulp.task('version', () => { gulp.task('version', () => {
if (!canDeploy()) {
return null;
}
console.log(`Updating versions to '${version}'...`); console.log(`Updating versions to '${version}'...`);
// Replace versioned URLs in source // Replace versioned URLs in source
const files = [ const files = ['plyr.js', 'plyr.polyfilled.js', 'defaults.js'];
'plyr.js',
'plyr.polyfilled.js',
'defaults.js',
];
return gulp return gulp
.src(files.map(file => path.join(root, `src/js/${file}`))) .src(files.map(file => path.join(root, `src/js/${file}`)))
@ -304,8 +334,7 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) {
// Publish version to CDN bucket // Publish version to CDN bucket
gulp.task('cdn', () => { gulp.task('cdn', () => {
if (!allowed.includes(branch.current)) { if (!canDeploy()) {
console.error(`Must be on ${allowed.join(', ')} to publish! (current: ${branch.current})`);
return null; return null;
} }
@ -315,14 +344,15 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) {
return ( return (
gulp gulp
.src(paths.upload) .src(paths.upload)
.pipe( .pipe(renameFile)
rename(p => {
p.basename = p.basename.replace(minSuffix, ''); // eslint-disable-line
p.dirname = p.dirname.replace('.', version); // eslint-disable-line
}),
)
// Remove min suffix from source map URL // Remove min suffix from source map URL
.pipe(replace(/sourceMappingURL=([\w-?.]+)/, (match, p1) => `sourceMappingURL=${p1.replace(minSuffix, '')}`)) .pipe(
replace(
/sourceMappingURL=([\w-?.]+)/,
(match, p1) =>
`sourceMappingURL=${p1.replace(minSuffix, '')}`,
),
)
.pipe( .pipe(
size({ size({
showFiles: true, showFiles: true,
@ -334,10 +364,36 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) {
); );
}); });
// Purge the fastly cache incase any 403/404 are cached
gulp.task('purge', () => {
const list = [];
return gulp.src(paths.upload).pipe(
through.obj((file, enc, cb) => {
const filename = file.path.split('/').pop();
list.push(`${versionPath}/${filename}`);
cb(null);
}),
).on('end', () => {
const purge = new FastlyPurge(fastly.token);
list.forEach(url => {
console.log(`Purging ${url}...`);
purge.url(url, (error, result) => {
if (error) {
console.log(error);
} else if (result) {
console.log(result);
}
});
});
});
});
// Publish to demo bucket // Publish to demo bucket
gulp.task('demo', () => { gulp.task('demo', () => {
if (!allowed.includes(branch.current)) { if (!canDeploy()) {
console.error(`Must be on ${allowed.join(', ')} to publish! (current: ${branch.current})`);
return null; return null;
} }
@ -399,22 +455,29 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) {
})); }));
}); */ }); */
// Open the demo site to check it's sweet // Open the demo site to check it's ok
gulp.task('open', () => { gulp.task('open', callback => {
console.log(`Opening ${aws.demo.domain}...`); gulp.src(__filename).pipe(
open({
// A file must be specified or gulp will skip the task uri: `https://${aws.demo.domain}`,
// Doesn't matter which file since we set the URL above
// Weird, I know...
return gulp.src([`${paths.demo.root}index.html`]).pipe(
open('', {
url: `http://${aws.demo.domain}`,
}), }),
); );
callback();
}); });
// Do everything // Do everything
gulp.task('publish', callback => { gulp.task('deploy', () =>
run('version', tasks.clean, tasks.js, tasks.sass, tasks.sprite, 'cdn', 'demo', callback); run(
}); 'version',
tasks.clean,
tasks.js,
tasks.sass,
tasks.sprite,
'cdn',
'purge',
'demo',
'open',
),
);
} }

View File

@ -32,7 +32,8 @@
"scripts": { "scripts": {
"build": "gulp build", "build": "gulp build",
"lint": "eslint src/js && npm run-script remark", "lint": "eslint src/js && npm run-script remark",
"remark": "remark -f --use 'validate-links=repository:\"sampotts/plyr\"' '{,!(node_modules),.?**/}*.md'", "remark":
"remark -f --use 'validate-links=repository:\"sampotts/plyr\"' '{,!(node_modules),.?**/}*.md'",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"devDependencies": { "devDependencies": {
@ -45,6 +46,7 @@
"eslint-config-airbnb-base": "^13.0.0", "eslint-config-airbnb-base": "^13.0.0",
"eslint-config-prettier": "^2.9.0", "eslint-config-prettier": "^2.9.0",
"eslint-plugin-import": "^2.13.0", "eslint-plugin-import": "^2.13.0",
"fastly-purge": "^1.0.1",
"git-branch": "^2.0.1", "git-branch": "^2.0.1",
"gulp": "^3.9.1", "gulp": "^3.9.1",
"gulp-autoprefixer": "^5.0.0", "gulp-autoprefixer": "^5.0.0",
@ -80,7 +82,8 @@
"stylelint-config-sass-guidelines": "^5.0.0", "stylelint-config-sass-guidelines": "^5.0.0",
"stylelint-order": "^0.8.1", "stylelint-order": "^0.8.1",
"stylelint-scss": "^3.1.3", "stylelint-scss": "^3.1.3",
"stylelint-selector-bem-pattern": "^2.0.0" "stylelint-selector-bem-pattern": "^2.0.0",
"through2": "^2.0.3"
}, },
"dependencies": { "dependencies": {
"babel-polyfill": "^6.26.0", "babel-polyfill": "^6.26.0",

View File

@ -2319,6 +2319,12 @@ fast-levenshtein@~2.0.4:
version "2.0.6" version "2.0.6"
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
fastly-purge@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/fastly-purge/-/fastly-purge-1.0.1.tgz#3bdfe9ea1d0fbf2a65712f2f5fe2eca63fcb5960"
dependencies:
request "^2.55.0"
fault@^1.0.0: fault@^1.0.0:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.2.tgz#c3d0fec202f172a3a4d414042ad2bb5e2a3ffbaa" resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.2.tgz#c3d0fec202f172a3a4d414042ad2bb5e2a3ffbaa"
@ -5801,6 +5807,31 @@ request@2:
tunnel-agent "^0.6.0" tunnel-agent "^0.6.0"
uuid "^3.1.0" uuid "^3.1.0"
request@^2.55.0:
version "2.87.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e"
dependencies:
aws-sign2 "~0.7.0"
aws4 "^1.6.0"
caseless "~0.12.0"
combined-stream "~1.0.5"
extend "~3.0.1"
forever-agent "~0.6.1"
form-data "~2.3.1"
har-validator "~5.0.3"
http-signature "~1.2.0"
is-typedarray "~1.0.0"
isstream "~0.1.2"
json-stringify-safe "~5.0.1"
mime-types "~2.1.17"
oauth-sign "~0.8.2"
performance-now "^2.1.0"
qs "~6.5.1"
safe-buffer "^5.1.1"
tough-cookie "~2.3.3"
tunnel-agent "^0.6.0"
uuid "^3.1.0"
request@~2.79.0: request@~2.79.0:
version "2.79.0" version "2.79.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de"