From 78676c8af763c228417e0610c7c3ffc4e4db6221 Mon Sep 17 00:00:00 2001 From: Erik Onarheim Date: Fri, 4 Feb 2022 20:49:39 -0600 Subject: [PATCH] chore: Update release automation (#2230) Preparing for v0.25.3, updating release automation to improve quality of life --- .github/workflows/deploy.yml | 2 +- package-lock.json | 130 +++++++++++++++++++++++++++++++++ package.json | 3 +- scripts/excalibur-version.js | 7 +- scripts/release.js | 6 +- version.js | 130 +++------------------------------ webpack.config.js | 138 ++++++++++++++++++----------------- 7 files changed, 223 insertions(+), 193 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 64de89da3..bd8481166 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -25,7 +25,7 @@ jobs: - run: npm ci - run: npm run build - run: npm run build:esm - - run: echo "alpha_version=$(node -e "console.log(require('./version').getCiVersion(null, false));")" >> $GITHUB_ENV + - run: echo "alpha_version=$(node -e "console.log(require('./version').getAlphaVersion());")" >> $GITHUB_ENV - run: echo $alpha_version - run: npm --no-git-tag-version version $alpha_version - run: npm publish --tag next diff --git a/package-lock.json b/package-lock.json index 127acf3c8..3cc96bcf3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ "copy-webpack-plugin": "10.2.0", "copyfiles": "2.4.1", "coveralls": "3.1.1", + "cross-env": "7.0.3", "css-loader": "6.5.1", "eslint": "8.8.0", "eslint-config-prettier": "8.3.0", @@ -13195,6 +13196,83 @@ "sha.js": "^2.4.8" } }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-env/node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-env/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cross-env/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cross-env/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cross-env/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -37252,6 +37330,58 @@ "sha.js": "^2.4.8" } }, + "cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.1" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", diff --git a/package.json b/package.json index 88171f255..0cfaec906 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "coveralls": "echo 'Temporarily Remove Coveralls Due To Outage'", "apidocs": "node scripts/apidocs.js", "pretty": "prettier --write \"{src,sandbox/src,sandbox/tests}/**/*.{ts,js,json,css,md}\" --config prettier.config.js", - "release": "node scripts/release.js" + "release": "cross-env release=true npm run all" }, "devDependencies": { "@babel/core": "7.16.12", @@ -78,6 +78,7 @@ "copy-webpack-plugin": "10.2.0", "copyfiles": "2.4.1", "coveralls": "3.1.1", + "cross-env": "7.0.3", "css-loader": "6.5.1", "eslint": "8.8.0", "eslint-config-prettier": "8.3.0", diff --git a/scripts/excalibur-version.js b/scripts/excalibur-version.js index f1f545319..503e69e8a 100644 --- a/scripts/excalibur-version.js +++ b/scripts/excalibur-version.js @@ -1,5 +1,10 @@ const replace = require('replace-in-file'); -const version = require('../version').getCiVersion(); +const versioner = require('../version'); +let version = versioner.getAlphaVersion(); +if (process.env.release) { + version = versioner.getReleaseVersion(); +} +console.log('Replacing __EX_VERSION with:', version); const options = { files: 'build/dist/index.js', from: /process\.env\.__EX_VERSION/g, diff --git a/scripts/release.js b/scripts/release.js index 0eeeab382..1b63235a1 100644 --- a/scripts/release.js +++ b/scripts/release.js @@ -1,14 +1,14 @@ const { execSync } = require('child_process'); const readline = require('readline'); const semver = require('semver'); -const { getLatestVersion } = require('./version'); +const { getReleaseVersion } = require('./version'); function generatePatchVersion() { - let version = getLatestVersion(); + let version = getReleaseVersion(); version = semver.inc(version, 'patch'); return version; } -const currentVersion = getLatestVersion(); +const currentVersion = getReleaseVersion(); const version = generatePatchVersion(); const rl = readline.createInterface({ diff --git a/version.js b/version.js index da538fc9c..2510c9508 100644 --- a/version.js +++ b/version.js @@ -1,19 +1,6 @@ const { execSync } = require('child_process'); -const semver = require('semver'); const package = require('./package.json'); -function getCiOptions() { - return { - ghToken: process.env.GH_TOKEN || undefined, - appveyorBuild: process.env.APPVEYOR_BUILD_NUMBER || '', - buildNumber: process.env.GITHUB_RUN_NUMBER || '', - commit: process.env.TRAVIS_COMMIT || '', - isPr: (process.env.GITHUB_HEAD_REF || 'false').replace('/', '-'), - travisTag: process.env.TRAVIS_TAG || '', - fork: process.env.TRAVIS_REPO_SLUG - }; -} - function getCurrentCommit() { const commit = execSync('git rev-parse HEAD').toString().trim(); return commit; @@ -23,118 +10,21 @@ function getNextVersion() { return package.exNextVersion; } -function isTaggedRelease(options) { - return !!options.travisTag; -} - -function isLocal(options) { - return !options.appveyorBuild && !options.buildNumber; -} - -function isPr(options) { - return !options.ghToken && options.isPr !== 'false'; -} - -function isFork(options) { - return !options.ghToken && options.fork !== 'excaliburjs/Excalibur'; -} - -function generateLocalVersion() { - let version = 'local'; - try { - execSync('git fetch'); - const commit = getCurrentCommit(); - version = getNextVersion(); - version = version + '-' + commit.substring(0, 7); - } catch (err) { - console.error(err); - } - return version; -} - -function generateTaggedVersion(options) { - const version = options.travisTag.match(/^v?([0-9\.]+)$/)[1]; - return version; -} - -function generateCommunityVersion(options) { - if (isPr(options)) { - return 'pr-' + options.isPr; - } - if (isFork(options)) { - return 'fork-' + options.fork; - } - throw Error('Invalid community version'); -} - -function generateAlphaVersion(options) { +function getAlphaVersion() { let commit = getCurrentCommit(); let version = getNextVersion(); - - // Nuget doesn't yet support the + suffix in versions - const appveyVersion = version + '.' + options.appveyorBuild + '-alpha'; - const travisVersion = version + '-alpha.' + options.buildNumber + '+' + commit.substring(0, 7); - - if (options.appveyorBuild) { - return appveyVersion; - } else { - return travisVersion; - } -} - -function getCiVersion(ciOptions, log = true) { - if (!ciOptions) { - ciOptions = getCiOptions(); - } - let version = 'unknown'; - if (isLocal(ciOptions)) { - version = generateLocalVersion(ciOptions); - log ? console.log('[local]: ' + version) : null; - } else if (isPr(ciOptions) || isFork(ciOptions)) { - version = generateCommunityVersion(ciOptions); - log ? console.log('[community]: ' + version) : null; - } else if (isTaggedRelease(ciOptions)) { - version = generateTaggedVersion(ciOptions); - log ? console.log('[release]: ' + version) : null; + if (process.env.GITHUB_RUN_NUMBER) { + return version + '-alpha.' + process.env.GITHUB_RUN_NUMBER + '+' + commit.substring(0, 7); } else { - // Else alpha version - version = generateAlphaVersion(ciOptions); - log ? console.log('[alpha]: ' + version) : null; + return version + '-alpha.0' + '+' + commit.substring(0, 7); } - return version; } -exports.getCiOptions = getCiOptions; -exports.getCurrentCommit = getCurrentCommit; -exports.getNextVersion = getNextVersion; -exports.isTaggedRelease = isTaggedRelease; -exports.isLocal = isLocal; -exports.isFork = isFork; -exports.isPr = isPr; -exports.generateLocalVersion = generateLocalVersion; -exports.generateTaggedVersion = generateTaggedVersion; -exports.generateAlphaVersion = generateAlphaVersion; -exports.generateCommunityVersion = generateCommunityVersion; -exports.getCiVersion = getCiVersion; - -// good enough assertions -function assertContains(actual, value, message) { - if (!actual.includes(value)) { - throw Error(`Assertion failed for ${message}`); - } +function getReleaseVersion() { + return package.version; } -const local = getCiVersion({}, false); -assertContains(local, '-', 'local version'); - -const pr = getCiVersion({ isPr: 'somepr', buildNumber: 'somebuild' }, false); -assertContains(pr, 'pr-', 'pr version'); - -const fork = getCiVersion({ fork: 'somefork', isPr: 'false', buildNumber: 'somebuild' }, false); -assertContains(fork, 'fork-', 'fork version'); - -const tagged = getCiVersion({ travisTag: 'v0.0.1', ghToken: 'sometoken', buildNumber: 'somebuild' }, false); -assertContains(tagged, '0.0.1', 'tagged version'); - -const alpha = getCiVersion({ buildNumber: 'somebuild', ghToken: 'sometoken' }, false); -assertContains(alpha, '-alpha.', 'alpha version'); +module.exports = { + getAlphaVersion: getAlphaVersion, + getReleaseVersion: getReleaseVersion +} \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index 82b7fb155..226a8683b 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,6 +1,6 @@ const path = require('path'); const webpack = require('webpack'); -const version = require('./version').getCiVersion(); +const versioner = require('./version'); const pkg = require('./package.json'); const CopyWebpackPlugin = require('copy-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin'); @@ -24,77 +24,81 @@ const esmOutput = { } }; -module.exports = (env, argv) => ({ - mode: env.production ? 'production' : 'development', - devtool: 'source-map', - entry: { - excalibur: './index.ts', - 'excalibur.min': './index.ts' - }, - context: path.resolve(__dirname, 'src/engine'), - optimization: { - minimize: true, - minimizer: [ - new TerserPlugin({ - include: /\.min\.js$/ - }) - ] - }, - output: env.output === 'esm' ? esmOutput : umdOutput, - experiments: - env.output === 'esm' - ? { +module.exports = (env, argv) => { + const version = process.env.release ? versioner.getReleaseVersion() : versioner.getAlphaVersion(); + console.log('[version]:', version); + return { + mode: 'production', + devtool: 'source-map', + entry: { + excalibur: './index.ts', + 'excalibur.min': './index.ts' + }, + context: path.resolve(__dirname, 'src/engine'), + optimization: { + minimize: true, + minimizer: [ + new TerserPlugin({ + include: /\.min\.js$/ + }) + ] + }, + output: env.output === 'esm' ? esmOutput : umdOutput, + experiments: + env.output === 'esm' + ? { outputModule: true } - : {}, - resolve: { - // Add `.ts` and `.tsx` as a resolvable extension. - extensions: ['.ts', '.tsx', '.js'] - }, - module: { - rules: [ - // all files with a `.ts` or `.tsx` extension will be handled by `ts-loader` - { - test: /\.tsx?$/, - loader: 'ts-loader', - options: { - compilerOptions: { - outDir: env.output === 'esm' ? esmOutput.path : umdOutput.path - } - } - }, - { - test: /\.css$/, - use: ['css-loader'] - }, - { - test: /\.(png|jpg|gif|mp3)$/i, - use: [ - { - loader: 'url-loader', - options: { - limit: 8192 + : {}, + resolve: { + // Add `.ts` and `.tsx` as a resolvable extension. + extensions: ['.ts', '.tsx', '.js'] + }, + module: { + rules: [ + // all files with a `.ts` or `.tsx` extension will be handled by `ts-loader` + { + test: /\.tsx?$/, + loader: 'ts-loader', + options: { + compilerOptions: { + outDir: env.output === 'esm' ? esmOutput.path : umdOutput.path } } - ] - }, - { - test: /\.glsl$/, - use: ['raw-loader'] - } - ] - }, - plugins: [ - new CopyWebpackPlugin({ patterns: ['excalibur.d.ts'] }), - new webpack.DefinePlugin({ - 'process.env.__EX_VERSION': JSON.stringify(version) - }), - new webpack.BannerPlugin( - `${pkg.name} - ${version} - ${dt} + }, + { + test: /\.css$/, + use: ['css-loader'] + }, + { + test: /\.(png|jpg|gif|mp3)$/i, + use: [ + { + loader: 'url-loader', + options: { + limit: 8192 + } + } + ] + }, + { + test: /\.glsl$/, + use: ['raw-loader'] + } + ] + }, + plugins: [ + new CopyWebpackPlugin({ patterns: ['excalibur.d.ts'] }), + new webpack.DefinePlugin({ + 'process.env.__EX_VERSION': JSON.stringify(version) + }), + new webpack.BannerPlugin( + `${pkg.name} - ${version} - ${dt} ${pkg.homepage} Copyright (c) ${now.getFullYear()} Excalibur.js <${pkg.author}> Licensed ${pkg.license} @preserve` - ) - ] -}); + ) + ] + } +};