aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Potts <sam@potts.es>2020-03-29 11:36:44 +1100
committerSam Potts <sam@potts.es>2020-03-29 11:36:44 +1100
commit5516db22c3dd38a6bb3ec8674e36bcc8f9bba90c (patch)
tree33a5a1cb92acf65da5e28aeb37905bbd07e27295
parent206e3b57d179504c8e01a6773b8653556ef523da (diff)
downloadplyr-5516db22c3dd38a6bb3ec8674e36bcc8f9bba90c.tar.lz
plyr-5516db22c3dd38a6bb3ec8674e36bcc8f9bba90c.tar.xz
plyr-5516db22c3dd38a6bb3ec8674e36bcc8f9bba90c.zip
Gulp file broken down
-rw-r--r--gulpfile.js518
-rw-r--r--tasks/build.js227
-rw-r--r--tasks/deploy.js272
3 files changed, 501 insertions, 516 deletions
diff --git a/gulpfile.js b/gulpfile.js
index 66966617..e1ebe778 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -1,522 +1,8 @@
// ==========================================================================
// Gulp build script
// ==========================================================================
-/* eslint no-console: "off" */
-const path = require('path');
const gulp = require('gulp');
-// ------------------------------------
-// JavaScript
-// ------------------------------------
-const terser = require('gulp-terser');
-const rollup = require('gulp-better-rollup');
-const babel = require('rollup-plugin-babel');
-const commonjs = require('rollup-plugin-commonjs');
-const resolve = require('rollup-plugin-node-resolve');
-// ------------------------------------
-// CSS
-// ------------------------------------
-const sass = require('gulp-sass');
-const clean = require('gulp-clean-css');
-const prefix = require('gulp-autoprefixer');
-// ------------------------------------
-// Images
-// ------------------------------------
-const svgstore = require('gulp-svgstore');
-const imagemin = require('gulp-imagemin');
-// ------------------------------------
-// Utils
-// ------------------------------------
-const del = require('del');
-const filter = require('gulp-filter');
-const header = require('gulp-header');
-const gitbranch = require('git-branch');
-const rename = require('gulp-rename');
-const replace = require('gulp-replace');
-const ansi = require('ansi-colors');
-const log = require('fancy-log');
-const open = require('gulp-open');
-const plumber = require('gulp-plumber');
-const size = require('gulp-size');
-const sourcemaps = require('gulp-sourcemaps');
-const through = require('through2');
-const browserSync = require('browser-sync').create();
-// ------------------------------------
-// Deployment
-// ------------------------------------
-const aws = require('aws-sdk');
-const publish = require('gulp-awspublish');
-const FastlyPurge = require('fastly-purge');
-// ------------------------------------
-// Configs
-// ------------------------------------
-const pkg = require('./package.json');
-const build = require('./build.json');
-const deploy = require('./deploy.json');
-// ------------------------------------
-// Info from package
-// ------------------------------------
-const { browserslist: browsers, version } = pkg;
-const minSuffix = '.min';
+const HubRegistry = require('gulp-hub');
-// Get AWS config
-Object.values(deploy).forEach(target => {
- Object.assign(target, {
- publisher: publish.create({
- region: target.region,
- params: {
- Bucket: target.bucket,
- },
- credentials: new aws.SharedIniFileCredentials({ profile: 'plyr' }),
- }),
- });
-});
-
-// Paths
-const paths = {
- plyr: {
- // Source paths
- src: {
- sass: path.join(__dirname, 'src/sass/**/*.scss'),
- js: path.join(__dirname, 'src/js/**/*.js'),
- sprite: path.join(__dirname, 'src/sprite/*.svg'),
- },
-
- // Output paths
- output: path.join(__dirname, 'dist/'),
- },
- demo: {
- // Source paths
- src: {
- sass: path.join(__dirname, 'demo/src/sass/**/*.scss'),
- js: path.join(__dirname, 'demo/src/js/**/*.js'),
- },
-
- // Output paths
- output: path.join(__dirname, 'demo/dist/'),
-
- // Demo
- root: path.join(__dirname, 'demo/'),
- },
- upload: [
- path.join(__dirname, `dist/*${minSuffix}.*`),
- path.join(__dirname, 'dist/*.css'),
- path.join(__dirname, 'dist/*.svg'),
- path.join(__dirname, `demo/dist/*${minSuffix}.*`),
- path.join(__dirname, 'demo/dist/*.css'),
- path.join(__dirname, 'demo/dist/*.svg'),
- ],
-};
-
-// Task arrays
-const tasks = {
- css: [],
- js: [],
- sprite: [],
- clean: 'clean',
-};
-
-// Size plugin
-const sizeOptions = { showFiles: true, gzip: true };
-
-// Clean out /dist
-gulp.task(tasks.clean, done => {
- const dirs = [paths.plyr.output, paths.demo.output].map(dir => path.join(dir, '**/*'));
-
- // Don't delete the mp4
- dirs.push(`!${path.join(paths.plyr.output, '**/*.mp4')}`);
-
- del(dirs);
-
- done();
-});
-
-// JavaScript
-Object.entries(build.js).forEach(([filename, entry]) => {
- const { dist, formats, namespace, polyfill, src } = entry;
-
- formats.forEach(format => {
- const name = `js:${filename}:${format}`;
- const extension = format === 'es' ? 'mjs' : 'js';
- tasks.js.push(name);
-
- gulp.task(name, () =>
- gulp
- .src(src)
- .pipe(plumber())
- .pipe(sourcemaps.init())
- .pipe(
- rollup(
- {
- plugins: [
- resolve(),
- commonjs(),
- babel({
- presets: [
- [
- '@babel/env',
- {
- // debug: true,
- useBuiltIns: polyfill ? 'usage' : false,
- corejs: polyfill ? 3 : undefined,
- },
- ],
- ],
- babelrc: false,
- exclude: [/\/core-js\//],
- }),
- ],
- },
- {
- name: namespace,
- format,
- },
- ),
- )
- .pipe(header('typeof navigator === "object" && ')) // "Support" SSR (#935)
- .pipe(
- rename({
- extname: `.${extension}`,
- }),
- )
- .pipe(gulp.dest(dist))
- .pipe(filter(`**/*.${extension}`))
- .pipe(terser())
- .pipe(rename({ suffix: minSuffix }))
- .pipe(size(sizeOptions))
- .pipe(sourcemaps.write(''))
- .pipe(gulp.dest(dist)),
- );
- });
-});
-
-// CSS
-Object.entries(build.css).forEach(([filename, entry]) => {
- const { dist, src } = entry;
- const name = `css:${filename}`;
- tasks.css.push(name);
-
- gulp.task(name, () =>
- gulp
- .src(src)
- .pipe(plumber())
- .pipe(sass())
- .pipe(
- prefix(browsers, {
- cascade: false,
- }),
- )
- .pipe(clean())
- .pipe(size(sizeOptions))
- .pipe(gulp.dest(dist)),
- );
-});
-
-// SVG Sprites
-Object.entries(build.sprite).forEach(([filename, entry]) => {
- const { dist, src } = entry;
- const name = `sprite:${filename}`;
- tasks.sprite.push(name);
-
- gulp.task(name, () =>
- gulp
- .src(src)
- .pipe(plumber())
- .pipe(
- imagemin([
- imagemin.svgo({
- plugins: [{ removeViewBox: false }],
- }),
- ]),
- )
- .pipe(svgstore())
- .pipe(rename({ basename: path.parse(filename).name }))
- .pipe(size(sizeOptions))
- .pipe(gulp.dest(dist)),
- );
-});
-
-// Build all JS
-gulp.task('js', () => gulp.parallel(...tasks.js));
-
-// Watch for file changes
-gulp.task('watch', () => {
- // Plyr core
- gulp.watch(paths.plyr.src.js, gulp.parallel(...tasks.js));
- gulp.watch(paths.plyr.src.sass, gulp.parallel(...tasks.css));
- gulp.watch(paths.plyr.src.sprite, gulp.parallel(...tasks.sprite));
-
- // Demo
- gulp.watch(paths.demo.src.js, gulp.parallel(...tasks.js));
- gulp.watch(paths.demo.src.sass, gulp.parallel(...tasks.css));
-});
-
-// Serve via browser sync
-gulp.task('serve', () =>
- browserSync.init({
- server: {
- baseDir: paths.demo.root,
- },
- notify: false,
- watch: true,
- ghostMode: false,
- }),
-);
-
-// Build distribution
-gulp.task('build', gulp.series(tasks.clean, gulp.parallel(...tasks.js, ...tasks.css, ...tasks.sprite)));
-
-// Default gulp task
-gulp.task('default', gulp.series('build', gulp.parallel('serve', 'watch')));
-
-// Publish a version to CDN and demo
-// --------------------------------------------
-// Get deployment config
-let credentials = {};
-try {
- credentials = require('./credentials.json'); //eslint-disable-line
-} catch (e) {
- // Do nothing
-}
-
-// Get branch info
-const branch = {
- current: gitbranch.sync(),
- master: 'master',
- beta: 'beta',
-};
-
-const maxAge = 31536000; // 1 year
-const options = {
- cdn: {
- headers: {
- 'Cache-Control': `max-age=${maxAge}`,
- },
- },
- demo: {
- uploadPath: branch.current === branch.beta ? '/beta' : null,
- headers: {
- 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0',
- },
- },
- symlinks(ver, filename) {
- return {
- headers: {
- // http://stackoverflow.com/questions/2272835/amazon-s3-object-redirect
- 'x-amz-website-redirect-location': `/${ver}/${filename}`,
- '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 semver = new RegExp(`v${regex}`, 'gi');
-const localPath = new RegExp('(../)?dist', 'gi');
-const versionPath = `https://${deploy.cdn.domain}/${version}`;
-const cdnpath = new RegExp(`${deploy.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.beta];
-
- if (!allowed.includes(branch.current)) {
- console.error(`Must be on ${allowed.join(', ')} to publish! (current: ${branch.current})`);
-
- return false;
- }
-
- return true;
-};
-
-gulp.task('version', done => {
- if (!canDeploy()) {
- done();
- return null;
- }
-
- const { domain } = deploy.cdn;
-
- log(`Uploading ${ansi.green.bold(version)} to ${ansi.cyan(domain)}...`);
-
- // Replace versioned URLs in source
- const files = ['plyr.js', 'plyr.polyfilled.js', 'config/defaults.js'];
-
- return gulp
- .src(
- files.map(file => path.join(__dirname, `src/js/${file}`)),
- { base: '.' },
- )
- .pipe(replace(semver, `v${version}`))
- .pipe(replace(cdnpath, `${domain}/${version}/`))
- .pipe(gulp.dest('./'));
-});
-
-// Publish version to CDN bucket
-gulp.task('cdn', done => {
- if (!canDeploy()) {
- done();
- return null;
- }
-
- const { domain, publisher } = deploy.cdn;
-
- if (!publisher) {
- throw new Error('No publisher instance. Check AWS configuration.');
- }
-
- log(`Uploading ${ansi.green.bold(pkg.version)} to ${ansi.cyan(domain)}...`);
-
- // Upload to CDN
- return (
- gulp
- .src(paths.upload)
- .pipe(renameFile)
- // Remove min suffix from source map URL
- .pipe(
- replace(
- /sourceMappingURL=([\w-?.]+)/,
- (match, filename) => `sourceMappingURL=${filename.replace(minSuffix, '')}`,
- ),
- )
- .pipe(size(sizeOptions))
- .pipe(replace(localPath, versionPath))
- .pipe(publisher.publish(options.cdn.headers))
- .pipe(publish.reporter())
- );
-});
-
-// Purge the fastly cache incase any 403/404 are cached
-gulp.task('purge', () => {
- if (!Object.keys(credentials).includes('fastly')) {
- throw new Error('Fastly credentials required to purge cache.');
- }
-
- const { fastly } = credentials;
- const list = [];
-
- return gulp
- .src(paths.upload)
- .pipe(
- through.obj((file, enc, cb) => {
- const filename = file.path.split('/').pop();
- list.push(`${versionPath}/${filename.replace(minSuffix, '')}`);
- cb(null);
- }),
- )
- .on('end', () => {
- const purge = new FastlyPurge(fastly.token);
-
- list.forEach(url => {
- log(`Purging ${ansi.cyan(url)}...`);
-
- purge.url(url, (error, result) => {
- if (error) {
- log.error(error);
- } else if (result) {
- log(result);
- }
- });
- });
- });
-});
-
-// Publish to demo bucket
-gulp.task('demo', done => {
- if (!canDeploy()) {
- done();
- return null;
- }
-
- const { publisher } = deploy.demo;
- const { domain } = deploy.cdn;
-
- if (!publisher) {
- throw new Error('No publisher instance. Check AWS configuration.');
- }
-
- log(`Uploading ${ansi.green.bold(pkg.version)} to ${ansi.cyan(domain)}...`);
-
- // Replace versioned files in readme.md
- gulp.src([`${__dirname}/readme.md`])
- .pipe(replace(cdnpath, `${domain}/${version}/`))
- .pipe(gulp.dest(__dirname));
-
- // Replace local file paths with remote paths in demo HTML
- // e.g. "../dist/plyr.js" to "https://cdn.plyr.io/x.x.x/plyr.js"
- const index = `${paths.demo.root}index.html`;
- const error = `${paths.demo.root}error.html`;
- const pages = [index];
-
- if (branch.current === branch.master) {
- pages.push(error);
- }
-
- return gulp
- .src(pages)
- .pipe(replace(localPath, versionPath))
- .pipe(
- rename(p => {
- if (options.demo.uploadPath) {
- // eslint-disable-next-line no-param-reassign
- p.dirname += options.demo.uploadPath;
- }
- }),
- )
- .pipe(publisher.publish(options.demo.headers))
- .pipe(publish.reporter());
-});
-
-gulp.task('error', done => {
- // Only update CDN for master (prod)
- if (!canDeploy() || branch.current !== branch.master) {
- done();
- return null;
- }
-
- const { publisher } = deploy.cdn;
-
- if (!publisher) {
- throw new Error('No publisher instance. Check AWS configuration.');
- }
-
- // Replace local file paths with remote paths in demo HTML
- // e.g. "../dist/plyr.js" to "https://cdn.plyr.io/x.x.x/plyr.js"
- // Upload error.html to cdn
- return gulp
- .src(`${paths.demo.root}error.html`)
- .pipe(replace(localPath, versionPath))
- .pipe(publisher.publish(options.demo.headers))
- .pipe(publish.reporter());
-});
-
-// Open the demo site to check it's ok
-gulp.task('open', () => {
- const { domain } = deploy.demo;
-
- return gulp.src(__filename).pipe(
- open({
- uri: `https://${domain}/${branch.current === branch.beta ? 'beta' : ''}`,
- }),
- );
-});
-
-// Do everything
-gulp.task(
- 'deploy',
- gulp.series(
- 'version',
- tasks.clean,
- gulp.parallel(...tasks.js, ...tasks.css, ...tasks.sprite),
- 'cdn',
- 'demo',
- 'purge',
- 'open',
- ),
-);
+gulp.registry(new HubRegistry(['tasks/*.js']));
diff --git a/tasks/build.js b/tasks/build.js
new file mode 100644
index 00000000..797f67a7
--- /dev/null
+++ b/tasks/build.js
@@ -0,0 +1,227 @@
+/* eslint-disable import/no-extraneous-dependencies */
+// ==========================================================================
+// Gulp build script
+// ==========================================================================
+/* eslint no-console: "off" */
+
+const path = require('path');
+const gulp = require('gulp');
+// JavaScript
+const terser = require('gulp-terser');
+const rollup = require('gulp-better-rollup');
+const babel = require('rollup-plugin-babel');
+const commonjs = require('rollup-plugin-commonjs');
+const resolve = require('rollup-plugin-node-resolve');
+// CSS
+const sass = require('gulp-sass');
+const clean = require('gulp-clean-css');
+const prefix = require('gulp-autoprefixer');
+// Images
+const svgstore = require('gulp-svgstore');
+const imagemin = require('gulp-imagemin');
+// Utils
+const del = require('del');
+const filter = require('gulp-filter');
+const header = require('gulp-header');
+const rename = require('gulp-rename');
+const plumber = require('gulp-plumber');
+const size = require('gulp-size');
+const sourcemaps = require('gulp-sourcemaps');
+const browserSync = require('browser-sync').create();
+// Configs
+const pkg = require('../package.json');
+const build = require('../build.json');
+// Info from package
+const { browserslist: browsers } = pkg;
+const minSuffix = '.min';
+// Paths
+const root = path.join(__dirname, '..');
+const paths = {
+ plyr: {
+ // Source paths
+ src: {
+ sass: path.join(root, 'src/sass/**/*.scss'),
+ js: path.join(root, 'src/js/**/*.js'),
+ sprite: path.join(root, 'src/sprite/*.svg'),
+ },
+
+ // Output paths
+ output: path.join(root, 'dist/'),
+ },
+ demo: {
+ // Source paths
+ src: {
+ sass: path.join(root, 'demo/src/sass/**/*.scss'),
+ js: path.join(root, 'demo/src/js/**/*.js'),
+ },
+
+ // Output paths
+ output: path.join(root, 'demo/dist/'),
+
+ // Demo
+ root: path.join(root, 'demo/'),
+ },
+};
+
+// Task lists
+const tasks = {
+ css: [],
+ js: [],
+ sprite: [],
+};
+
+// Size plugin
+const sizeOptions = { showFiles: true, gzip: true };
+
+// Clean out /dist
+gulp.task('clean', done => {
+ const dirs = [paths.plyr.output, paths.demo.output].map(dir => path.join(dir, '**/*'));
+
+ // Don't delete the mp4
+ dirs.push(`!${path.join(paths.plyr.output, '**/*.mp4')}`);
+
+ del(dirs);
+
+ done();
+});
+
+// JavaScript
+Object.entries(build.js).forEach(([filename, entry]) => {
+ const { dist, formats, namespace, polyfill, src } = entry;
+
+ formats.forEach(format => {
+ const name = `js:${filename}:${format}`;
+ const extension = format === 'es' ? 'mjs' : 'js';
+ tasks.js.push(name);
+
+ gulp.task(name, () =>
+ gulp
+ .src(src)
+ .pipe(plumber())
+ .pipe(sourcemaps.init())
+ .pipe(
+ rollup(
+ {
+ plugins: [
+ resolve(),
+ commonjs(),
+ babel({
+ presets: [
+ [
+ '@babel/env',
+ {
+ // debug: true,
+ useBuiltIns: polyfill ? 'usage' : false,
+ corejs: polyfill ? 3 : undefined,
+ bugfixes: true,
+ },
+ ],
+ ],
+ babelrc: false,
+ exclude: [/\/core-js\//],
+ }),
+ ],
+ },
+ {
+ name: namespace,
+ format,
+ },
+ ),
+ )
+ .pipe(header('typeof navigator === "object" && ')) // "Support" SSR (#935)
+ .pipe(
+ rename({
+ extname: `.${extension}`,
+ }),
+ )
+ .pipe(gulp.dest(dist))
+ .pipe(filter(`**/*.${extension}`))
+ .pipe(terser())
+ .pipe(rename({ suffix: minSuffix }))
+ .pipe(size(sizeOptions))
+ .pipe(sourcemaps.write(''))
+ .pipe(gulp.dest(dist)),
+ );
+ });
+});
+
+// CSS
+Object.entries(build.css).forEach(([filename, entry]) => {
+ const { dist, src } = entry;
+ const name = `css:${filename}`;
+ tasks.css.push(name);
+
+ gulp.task(name, () =>
+ gulp
+ .src(src)
+ .pipe(plumber())
+ .pipe(sass())
+ .pipe(
+ prefix(browsers, {
+ cascade: false,
+ }),
+ )
+ .pipe(clean())
+ .pipe(size(sizeOptions))
+ .pipe(gulp.dest(dist)),
+ );
+});
+
+// SVG Sprites
+Object.entries(build.sprite).forEach(([filename, entry]) => {
+ const { dist, src } = entry;
+ const name = `sprite:${filename}`;
+ tasks.sprite.push(name);
+
+ gulp.task(name, () =>
+ gulp
+ .src(src)
+ .pipe(plumber())
+ .pipe(
+ imagemin([
+ imagemin.svgo({
+ plugins: [{ removeViewBox: false }],
+ }),
+ ]),
+ )
+ .pipe(svgstore())
+ .pipe(rename({ basename: path.parse(filename).name }))
+ .pipe(size(sizeOptions))
+ .pipe(gulp.dest(dist)),
+ );
+});
+
+// Build all tasks
+gulp.task('js', gulp.parallel(...tasks.js));
+gulp.task('css', gulp.parallel(...tasks.css));
+gulp.task('sprites', gulp.parallel(...tasks.sprite));
+
+// Watch for file changes
+gulp.task('watch', () => {
+ // Plyr core
+ gulp.watch(paths.plyr.src.js, gulp.parallel('js'));
+ gulp.watch(paths.plyr.src.sass, gulp.parallel('css'));
+ gulp.watch(paths.plyr.src.sprite, gulp.parallel('sprites'));
+
+ // Demo
+ gulp.watch(paths.demo.src.js, gulp.parallel('js'));
+ gulp.watch(paths.demo.src.sass, gulp.parallel('css'));
+});
+
+// Serve via browser sync
+gulp.task('serve', () =>
+ browserSync.init({
+ server: {
+ baseDir: paths.demo.root,
+ },
+ notify: false,
+ watch: true,
+ ghostMode: false,
+ }),
+);
+
+// Build distribution
+gulp.task('build', gulp.series('clean', gulp.parallel('js', 'css', 'sprites')));
+
+// Default gulp task
+gulp.task('default', gulp.series('build', gulp.parallel('serve', 'watch')));
diff --git a/tasks/deploy.js b/tasks/deploy.js
new file mode 100644
index 00000000..4ff94680
--- /dev/null
+++ b/tasks/deploy.js
@@ -0,0 +1,272 @@
+/* eslint-disable import/no-extraneous-dependencies */
+// ==========================================================================
+// Publish a version to CDN and demo
+// ==========================================================================
+/* eslint no-console: "off" */
+
+const path = require('path');
+const gulp = require('gulp');
+// Utils
+const gitbranch = require('git-branch');
+const rename = require('gulp-rename');
+const replace = require('gulp-replace');
+const ansi = require('ansi-colors');
+const log = require('fancy-log');
+const open = require('gulp-open');
+const size = require('gulp-size');
+const through = require('through2');
+// Deployment
+const aws = require('aws-sdk');
+const publish = require('gulp-awspublish');
+const FastlyPurge = require('fastly-purge');
+// Configs
+const pkg = require('../package.json');
+const deploy = require('../deploy.json');
+// Info from package
+const { version } = pkg;
+const minSuffix = '.min';
+
+// Get AWS config
+Object.values(deploy).forEach(target => {
+ Object.assign(target, {
+ publisher: publish.create({
+ region: target.region,
+ params: {
+ Bucket: target.bucket,
+ },
+ credentials: new aws.SharedIniFileCredentials({ profile: 'plyr' }),
+ }),
+ });
+});
+
+// Paths
+const root = path.join(__dirname, '..');
+const paths = {
+ upload: [
+ path.join(root, `dist/*${minSuffix}.*`),
+ path.join(root, 'dist/*.css'),
+ path.join(root, 'dist/*.svg'),
+ path.join(root, `demo/dist/*${minSuffix}.*`),
+ path.join(root, 'demo/dist/*.css'),
+ path.join(root, 'demo/dist/*.svg'),
+ ],
+};
+
+// Get credentials
+let credentials = {};
+try {
+ credentials = require('../credentials.json'); //eslint-disable-line
+} catch (e) {
+ // Do nothing
+}
+
+// Get branch info
+const branch = {
+ current: gitbranch.sync(),
+ master: 'master',
+ beta: 'beta',
+};
+
+const maxAge = 31536000; // 1 year
+const options = {
+ cdn: {
+ headers: {
+ 'Cache-Control': `max-age=${maxAge}, immutable`,
+ },
+ },
+ demo: {
+ uploadPath: branch.current === branch.beta ? '/beta' : null,
+ headers: {
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0',
+ },
+ },
+ symlinks(ver, filename) {
+ return {
+ headers: {
+ // http://stackoverflow.com/questions/2272835/amazon-s3-object-redirect
+ 'x-amz-website-redirect-location': `/${ver}/${filename}`,
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0',
+ },
+ };
+ },
+};
+
+// Size plugin
+const sizeOptions = { showFiles: true, gzip: true };
+
+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 localPath = new RegExp('(../)?dist', 'gi');
+const versionPath = `https://${deploy.cdn.domain}/${version}`;
+const cdnpath = new RegExp(`${deploy.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.beta];
+
+ if (!allowed.includes(branch.current)) {
+ console.error(`Must be on ${allowed.join(', ')} to publish! (current: ${branch.current})`);
+
+ return false;
+ }
+
+ return true;
+};
+
+gulp.task('version', done => {
+ if (!canDeploy()) {
+ done();
+ return null;
+ }
+
+ const { domain } = deploy.cdn;
+
+ log(`Uploading ${ansi.green.bold(version)} to ${ansi.cyan(domain)}...`);
+
+ // Replace versioned URLs in source
+ const files = ['plyr.js', 'plyr.polyfilled.js', 'config/defaults.js'];
+
+ return gulp
+ .src(
+ files.map(file => path.join(__dirname, `src/js/${file}`)),
+ { base: '.' },
+ )
+ .pipe(replace(semver, `v${version}`))
+ .pipe(replace(cdnpath, `${domain}/${version}/`))
+ .pipe(gulp.dest('./'));
+});
+
+// Publish version to CDN bucket
+gulp.task('cdn', done => {
+ if (!canDeploy()) {
+ done();
+ return null;
+ }
+
+ const { domain, publisher } = deploy.cdn;
+
+ if (!publisher) {
+ throw new Error('No publisher instance. Check AWS configuration.');
+ }
+
+ log(`Uploading ${ansi.green.bold(pkg.version)} to ${ansi.cyan(domain)}...`);
+
+ // Upload to CDN
+ return (
+ gulp
+ .src(paths.upload)
+ .pipe(renameFile)
+ // Remove min suffix from source map URL
+ .pipe(
+ replace(
+ /sourceMappingURL=([\w-?.]+)/,
+ (match, filename) => `sourceMappingURL=${filename.replace(minSuffix, '')}`,
+ ),
+ )
+ .pipe(size(sizeOptions))
+ .pipe(replace(localPath, versionPath))
+ .pipe(publisher.publish(options.cdn.headers))
+ .pipe(publish.reporter())
+ );
+});
+
+// Purge the fastly cache incase any 403/404 are cached
+gulp.task('purge', () => {
+ if (!Object.keys(credentials).includes('fastly')) {
+ throw new Error('Fastly credentials required to purge cache.');
+ }
+
+ const { fastly } = credentials;
+ const list = [];
+
+ return gulp
+ .src(paths.upload)
+ .pipe(
+ through.obj((file, enc, cb) => {
+ const filename = file.path.split('/').pop();
+ list.push(`${versionPath}/${filename.replace(minSuffix, '')}`);
+ cb(null);
+ }),
+ )
+ .on('end', () => {
+ const purge = new FastlyPurge(fastly.token);
+
+ list.forEach(url => {
+ log(`Purging ${ansi.cyan(url)}...`);
+
+ purge.url(url, (error, result) => {
+ if (error) {
+ log.error(error);
+ } else if (result) {
+ log(result);
+ }
+ });
+ });
+ });
+});
+
+// Publish to demo bucket
+gulp.task('demo', done => {
+ if (!canDeploy()) {
+ done();
+ return null;
+ }
+
+ const { publisher } = deploy.demo;
+ const { domain } = deploy.cdn;
+
+ if (!publisher) {
+ throw new Error('No publisher instance. Check AWS configuration.');
+ }
+
+ log(`Uploading ${ansi.green.bold(pkg.version)} to ${ansi.cyan(domain)}...`);
+
+ // Replace versioned files in readme.md
+ gulp.src([`${__dirname}/readme.md`])
+ .pipe(replace(cdnpath, `${domain}/${version}/`))
+ .pipe(gulp.dest(__dirname));
+
+ // Replace local file paths with remote paths in demo HTML
+ // e.g. "../dist/plyr.js" to "https://cdn.plyr.io/x.x.x/plyr.js"
+ const index = `${paths.demo.root}index.html`;
+ const error = `${paths.demo.root}error.html`;
+ const pages = [index];
+
+ if (branch.current === branch.master) {
+ pages.push(error);
+ }
+
+ return gulp
+ .src(pages)
+ .pipe(replace(localPath, versionPath))
+ .pipe(
+ rename(p => {
+ if (options.demo.uploadPath) {
+ // eslint-disable-next-line no-param-reassign
+ p.dirname += options.demo.uploadPath;
+ }
+ }),
+ )
+ .pipe(publisher.publish(options.demo.headers))
+ .pipe(publish.reporter());
+});
+
+// Open the demo site to check it's ok
+gulp.task('open', () => {
+ const { domain } = deploy.demo;
+
+ return gulp.src(__filename).pipe(
+ open({
+ uri: `https://${domain}/${branch.current === branch.beta ? 'beta' : ''}`,
+ }),
+ );
+});
+
+// Do everything
+gulp.task('deploy', gulp.series('cdn', 'demo', 'purge', 'open'));