UNPKG

io3fix

Version:

toolkit for interior apps

274 lines (244 loc) • 7.71 kB
const fs = require('fs') const path = require('path') const gulp = require('gulp') const del = require('del') const gzip = require('gulp-gzip') const s3 = require('gulp-s3') const through2 = require('through2') const UglifyJS = require('uglify-js') const build = require('./build.js') const jshint = require('./jshint.js') const packageInfo = require('../package.json') const preamble = require('./preamble.js') const execSync = require('child_process').execSync const git = require('gulp-git') // internals const version = packageInfo.version const branchName = preamble.gitBranchName // configs const srcDir = 'build' const destDir = 'release' const gitCommitMessage = 'Release '+version const awsConfig = { bucket: '3dio-dist', region: 'eu-west-1', key: process.env.AWS_ACCESS_KEY_ID, secret: process.env.AWS_SECRET_ACCESS_KEY } const awsDir = { version: path.join('3dio-js', version), latestMinor: path.join('3dio-js', getLatestMinor(version)), latestPatch: path.join('3dio-js', getLatestPatch(version)) } // set CDN cache time for all specific distribution files (file names i.e. "1.0.3") const cdnCacheMaxAge = 365 * 24 * 60 * 60 // 1 Year // set CDN cache time for "latest" distribution files (file names: "1.x.x" and "1.0.x") const cdnCacheMaxAgeLatest = 5 * 60 // 5 Min // tasks const release = gulp.series( checkLocalEnv, checkWorkingDirectoryClean, checkBranchName, npmCheckVersion, jshint, setBabelEnv, build, unsetBabelEnv, cleanDestDir, copyBuildToDist, uglify, gitTag, gitCommit, gitPush, npmPublish, s3Upload, releaseInfo ) function checkLocalEnv() { if(!awsConfig.key || !awsConfig.secret) throw 'ERROR: You need to set $AWS_ACCESS_KEY_ID and $AWS_SECRET_ACCESS_KEY to be able to upload to S3' try { execSync('npm who') } catch(e) { throw 'ERROR: You need to be logged in with npm to release! Run "npm login" first.' } return Promise.resolve() } function checkWorkingDirectoryClean() { return new Promise(function (resolve, reject) { git.status({ args: '--porcelain' }, function (err, status) { if(status === '') { resolve() } else { throw 'Aborting due to uncommitted changes:\n' + status } }) }) } function checkBranchName () { if (branchName !== 'master') { throw 'ERROR: Releasing is only allowed from master branch.' } else { return Promise.resolve() } } let rememberBabelEnv = {} function setBabelEnv () { rememberBabelEnv.ROLLUP_USE_BABEL = process.env.ROLLUP_USE_BABEL rememberBabelEnv.BABEL_ENV = process.env.BABEL_ENV process.env.ROLLUP_USE_BABEL = true process.env.BABEL_ENV = 'production' return Promise.resolve() } function unsetBabelEnv () { process.env.ROLLUP_USE_BABEL = rememberBabelEnv.ROLLUP_USE_BABEL process.env.BABEL_ENV = rememberBabelEnv.BABEL_ENV return Promise.resolve() } function cleanDestDir () { return del([destDir]).then(function () { fs.mkdirSync(path.join(process.cwd(), destDir), 0o744) fs.mkdirSync(path.join(process.cwd(), destDir, version), 0o744) }) } function copyBuildToDist () { return gulp .src(path.join(srcDir, '/**')) .pipe(gulp.dest(path.join(destDir, version))) } function uglify () { return gulp.src(path.join(srcDir, '/*.js')).pipe(through2.obj((inputFile, enc, cb) => { // process files only if (!inputFile.isBuffer()) return // get filename without extension var cwd = process.cwd() var sourceBasename = inputFile.basename.substr(0, inputFile.basename.length - 3) var targetBasename = sourceBasename //+'-'+version // decode text from vinyl object const ugly = UglifyJS.minify(inputFile.contents.toString(enc), { warnings: true, mangle: true, ie8: false, compress: {dead_code: true, toplevel: true, passes: 3}, output: {preamble: preamble.text, beautify: false}, sourceMap: { content: read(path.join(srcDir, `${targetBasename}.js.map`)), url: `${targetBasename}.min.js.map` } }) if (ugly.warnings) console.log('UGLIFY WARNINGS: ', ugly.warnings) if (ugly.error) return Promise.reject(ugly.error) // write files fs.writeFileSync( path.join(cwd, destDir, version, `${targetBasename}.min.js.map`), ugly.map) fs.writeFileSync( path.join(cwd, destDir, version, `${targetBasename}.min.js`), ugly.code) // gulp callback cb() })) } function gitTag () { return new Promise(function (resolve, reject) { git.tag('v'+version, '', function (err) { if (err) { // graceful error handling because not critical. i.e. tag may already exist when // a previous release failed at a later step and the release has to be repeated. console.warn('Git tag error: ', err) } resolve() }) }) } function gitCommit () { // commit build and package.json with updated version number return gulp.src([ path.join(srcDir, '*'), 'package.json', 'package-lock.json' ]).pipe(git.commit(gitCommitMessage)) } function gitPush () { return new Promise(function (resolve, reject) { git.push('origin', ['master'], {args: " --tags"}, function (err) { if (err) throw err resolve() }) }) } function npmCheckVersion () { const latestNpmVersion = execSync(`npm view ${packageInfo.name} version`).toString('utf8').replace('\n', '') if (latestNpmVersion === version ) { throw new Error('Version '+version+' has been published to NPM already. Did you forget to bump version number?') } return Promise.resolve() } function npmPublish () { console.log('Publishing version '+version+' to NPM') execSync(`npm publish`).toString('utf8').replace('\n', '') return Promise.resolve() } function s3Upload () { return gulp.src(path.join(destDir, version, '*')) .pipe(gzip({ append: false, // do not append .gz extension threshold: false, // no file size treshold because all files will have gzip headers gzipOptions: {level: 9} })) .pipe(s3(awsConfig, { uploadPath: awsDir.version, headers: { 'Content-Encoding': 'gzip', 'Cache-Control': 'max-age=' + cdnCacheMaxAge }, failOnError: true })) .pipe(s3(awsConfig, { uploadPath: awsDir.latestMinor, headers: { 'Content-Encoding': 'gzip', 'Cache-Control': 'max-age=' + cdnCacheMaxAgeLatest }, failOnError: true })) .pipe(s3(awsConfig, { uploadPath: awsDir.latestPatch, headers: { 'Content-Encoding': 'gzip', 'Cache-Control': 'max-age=' + cdnCacheMaxAgeLatest }, failOnError: true })) } // helpers function handleError(error) { console.error(error.stack || error) // return rejected promise to cancel promise chain return Promise.reject(error) } function read (path_) { return fs.readFileSync(path_, `utf8`) } function getLatestMinor (version) { return `${version.split('.')[0]}.x.x${getAppendix(version)}` } function getLatestPatch (version) { const parts = version.split('.') return `${parts[0]}.${parts[1]}.x${getAppendix(version)}` } function getAppendix (version) { let appendix = '' if (version.indexOf('-alpha') > -1) { appendix = '-alpha' } else if (version.indexOf('-beta') > -1) { appendix = '-beta' } else if (version.split('-')[1]) { appendix = version.split('-').slice(1).join('-') } return appendix } function releaseInfo() { console.log(`šŸŽ‰ SUCCESS! šŸŽ‰ āš ļø PLEASE NOTE: "${getLatestMinor(version)}" and "${getLatestPatch(version)}" will become effective after CDN cache expires in ${cdnCacheMaxAgeLatest / 60} minutes.`) return Promise.resolve() } // export module.exports = release