diff --git a/bin/eslint-prerelease.js b/bin/eslint-generate-prerelease.js similarity index 88% rename from bin/eslint-prerelease.js rename to bin/eslint-generate-prerelease.js index fb87ebb..1f6af6f 100644 --- a/bin/eslint-prerelease.js +++ b/bin/eslint-generate-prerelease.js @@ -21,7 +21,7 @@ var ReleaseOps = require("../lib/release-ops"); /* * Usage: - * $ eslint-prerelease beta + * $ eslint-generate-prerelease beta */ var args = process.argv.slice(2), prereleaseId = (args.length ? args[0] : null); @@ -32,5 +32,4 @@ if (!prereleaseId) { process.exit(1); // eslint-disable-line no-process-exit } -var releaseInfo = ReleaseOps.release(prereleaseId); -ReleaseOps.publishReleaseToGitHub(releaseInfo); +ReleaseOps.generateRelease(prereleaseId); diff --git a/bin/eslint-ci-release.js b/bin/eslint-generate-release.js similarity index 75% rename from bin/eslint-ci-release.js rename to bin/eslint-generate-release.js index fefdcb6..0a72490 100644 --- a/bin/eslint-ci-release.js +++ b/bin/eslint-generate-release.js @@ -1,7 +1,7 @@ #!/usr/bin/env node /** - * @fileoverview Main CLI that is run via the eslint-ci-release command. + * @fileoverview Main CLI that is run via the eslint-generate-release command. * @author Nicholas C. Zakas * @copyright jQuery Foundation and other contributors, https://jquery.org/ * MIT License @@ -21,8 +21,7 @@ var ReleaseOps = require("../lib/release-ops"); /* * Usage: - * $ eslint-ci-release + * $ eslint-generate-release */ -var releaseInfo = ReleaseOps.release(null, true); -ReleaseOps.publishReleaseToGitHub(releaseInfo); +ReleaseOps.generateRelease(); diff --git a/bin/eslint-gh-release.js b/bin/eslint-gh-release.js deleted file mode 100644 index 297dd72..0000000 --- a/bin/eslint-gh-release.js +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env node - -/** - * @fileoverview Main CLI that is run via the eslint-gh-release command. - * @author Nicholas C. Zakas - * @copyright jQuery Foundation and other contributors, https://jquery.org/ - * MIT License - */ - -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -var path = require("path"), - ReleaseOps = require("../lib/release-ops"); - -//------------------------------------------------------------------------------ -// Execution -//------------------------------------------------------------------------------ - -/* - * Usage: - * $ eslint-gh-release - */ - -var releaseInfo = require(path.resolve(process.cwd(), "./.releaseInfo.json")); -ReleaseOps.publishReleaseToGitHub(releaseInfo); diff --git a/bin/eslint-release.js b/bin/eslint-publish-release.js similarity index 92% rename from bin/eslint-release.js rename to bin/eslint-publish-release.js index f9cf0ae..6ee615a 100644 --- a/bin/eslint-release.js +++ b/bin/eslint-publish-release.js @@ -21,7 +21,7 @@ var ReleaseOps = require("../lib/release-ops"); /* * Usage: - * $ eslint-release + * $ eslint-publish-release */ -ReleaseOps.release(); +ReleaseOps.publishRelease(); diff --git a/lib/release-ops.js b/lib/release-ops.js index 9740ebf..d9420a2 100644 --- a/lib/release-ops.js +++ b/lib/release-ops.js @@ -16,7 +16,6 @@ var fs = require("fs"), shelljs = require("shelljs"), semver = require("semver"), GitHub = require("github-api"), - // checker = require("npm-license"), dateformat = require("dateformat"), ShellOps = require("./shell-ops"); @@ -40,11 +39,10 @@ function getPackageInfo() { /** * Run before a release to validate that the project is setup correctly. - * @param {boolean} [ciRelease] Set to true to indicate this is a CI release. * @returns {void} * @private */ -function validateSetup(ciRelease) { +function validateSetup() { if (!shelljs.test("-f", "package.json")) { console.error("Missing package.json file"); ShellOps.exit(1); @@ -56,23 +54,24 @@ function validateSetup(ciRelease) { ShellOps.exit(1); } - // special checks for CI release - if (ciRelease) { + // check repository field + if (!pkg.repository) { + console.error("Missing 'repository' in package.json"); + ShellOps.exit(1); + } else if (!/^[\w\-]+\/[\w\-]+$/.test(pkg.repository)) { + console.error("The 'repository' field must be in the format 'foo/bar' in package.json"); + ShellOps.exit(1); + } - // check repository field - if (!pkg.repository) { - console.error("Missing 'repository' in package.json"); - ShellOps.exit(1); - } else if (!/^[\w\-]+\/[\w\-]+$/.test(pkg.repository)) { - console.error("The 'repository' field must be in the format 'foo/bar' in package.json"); - ShellOps.exit(1); - } + // check NPM_TOKEN + if (!process.env.NPM_TOKEN) { + console.error("Missing NPM_TOKEN environment variable"); + ShellOps.exit(1); + } - // check NPM_TOKEN - if (!process.env.NPM_TOKEN) { - console.error("Missing NPM_TOKEN environment variable"); - ShellOps.exit(1); - } + if (!process.env.ESLINT_GITHUB_TOKEN) { + console.error("Missing ESLINT_GITHUB_TOKEN environment variable"); + ShellOps.exit(1); } } @@ -111,63 +110,6 @@ function getVersionTags() { }, []).sort(semver.compare); } -// TODO: Make this async -/** - * Validates the licenses of all dependencies are valid open source licenses. - * @returns {void} - * @private - */ -// function checkLicenses() { - -// /** -// * Check if a dependency is eligible to be used by us -// * @param {object} dependency dependency to check -// * @returns {boolean} true if we have permission -// * @private -// */ -// function isPermissible(dependency) { -// var licenses = dependency.licenses; - -// if (Array.isArray(licenses)) { -// return licenses.some(function(license) { -// return isPermissible({ -// name: dependency.name, -// licenses: license -// }); -// }); -// } - -// return OPEN_SOURCE_LICENSES.some(function(license) { -// return license.test(licenses); -// }); -// } - -// console.log("Validating licenses"); - -// checker.init({ -// start: process.cwd() -// }, function(deps) { -// var impermissible = Object.keys(deps).map(function(dependency) { -// return { -// name: dependency, -// licenses: deps[dependency].licenses -// }; -// }).filter(function(dependency) { -// return !isPermissible(dependency); -// }); - -// if (impermissible.length) { -// impermissible.forEach(function(dependency) { -// console.error("%s license for %s is impermissible.", -// dependency.licenses, -// dependency.name -// ); -// }); -// ShellOps.exit(1); -// } -// }); -// } - /** * Extracts data from a commit log in the format --pretty=format:"* %h %s (%an)\n%b". * @param {string[]} logs Output from git log command. @@ -345,28 +287,11 @@ function writeChangelog(releaseInfo) { * Creates a release version tag and pushes to origin and npm. * @param {string} [prereleaseId] The prerelease ID (alpha, beta, rc, etc.). * Only include when doing a prerelease. - * @param {boolean} [ciRelease] Indicates that the release is being done by the - * CI and so shouldn't push back to Git (this will be handled by CI itself). * @returns {Object} The information about the release. */ -function release(prereleaseId, ciRelease) { +function generateRelease(prereleaseId) { - validateSetup(ciRelease); - - // CI release doesn't need to clear node_modules because it installs clean - if (!ciRelease) { - console.log("Updating dependencies (this may take a while)"); - shelljs.rm("-rf", "node_modules"); - ShellOps.execSilent("npm install --silent"); - } - - // necessary so later "npm install" will install the same versions - // console.log("Shrinkwrapping dependencies"); - // ShellOps.execSilent("npm shrinkwrap"); - - // TODO: Make this work - // console.log("Checking licenses"); - // checkLicenses(); + validateSetup(); console.log("Running tests"); ShellOps.execSilent("npm test"); @@ -379,9 +304,6 @@ function release(prereleaseId, ciRelease) { console.log("Generating changelog"); writeChangelog(releaseInfo); - // console.log("Updating bundled dependencies"); - // ShellOps.exec("bundle-dependencies update"); - console.log("Committing to git"); ShellOps.exec("git add CHANGELOG.md"); ShellOps.exec("git commit -m \"Build: changelog update for " + releaseInfo.version + "\""); @@ -389,10 +311,6 @@ function release(prereleaseId, ciRelease) { console.log("Generating %s", releaseInfo.version); ShellOps.execSilent("npm version " + releaseInfo.version); - // push all the things - console.log("Publishing to git"); - ShellOps.exec("git push origin master --tags"); - console.log("Fixing line endings"); getPackageInfo().files.filter(function(dirPath) { return fs.lstatSync(dirPath).isDirectory(); @@ -402,42 +320,10 @@ function release(prereleaseId, ciRelease) { } }); - // NOTE: eslint-release dependencies are no longer available starting here - - // console.log("Fixing dependencies for bundle"); - // shelljs.rm("-rf", "node_modules"); - // ShellOps.execSilent("npm install --production"); - - if (ciRelease) { - - // CI release needs a .npmrc file to work properly - token is read from environment - console.log("Writing .npmrc file"); - fs.writeFileSync(".npmrc", "//registry.npmjs.org/:_authToken=${NPM_TOKEN}"); - } - - // if there's a prerelease ID, publish under "next" tag - console.log("Publishing to npm"); - if (prereleaseId) { - ShellOps.exec("npm publish --tag next"); - } else { - ShellOps.exec("npm publish"); - } - - // undo any differences - if (!ciRelease) { - ShellOps.exec("git reset"); - ShellOps.exec("git clean -f"); - } - - // restore development environment - // ShellOps.exec("npm install"); - - // NOTE: eslint-release dependencies are once again available after here - - // delete shrinkwrap file - // shelljs.rm("npm-shrinkwrap.json"); - - return releaseInfo; + // Release needs a .npmrc file to work properly - token is read from environment + console.log("Writing .npmrc file"); + fs.writeFileSync(".npmrc", "//registry.npmjs.org/:_authToken=${NPM_TOKEN}"); + fs.writeFileSync(".eslint-release-info.json", JSON.stringify(releaseInfo, null, 4)); } /** @@ -448,11 +334,6 @@ function release(prereleaseId, ciRelease) { */ function publishReleaseToGitHub(releaseInfo) { - if (!process.env.ESLINT_GITHUB_TOKEN) { - console.error("Missing ESLINT_GITHUB_TOKEN environment variable"); - ShellOps.exit(1); - } - var repoParts = releaseInfo.repository.split("/"), gh = new GitHub({ token: process.env.ESLINT_GITHUB_TOKEN }), repo = gh.getRepo(repoParts[0], repoParts[1]), @@ -473,15 +354,45 @@ function publishReleaseToGitHub(releaseInfo) { } +/** + * Push the commit and git tags, publish to npm, and publish a changelog to GitHub release notes. + * @returns {Object} the information about the release. + */ +function publishRelease() { + validateSetup(); + var releaseInfo = JSON.parse(fs.readFileSync(".eslint-release-info.json", "utf8")); + + // if there's a prerelease ID, publish under "next" tag + console.log("Publishing to npm"); + + var command = "npm publish"; + if (semver.prerelease(releaseInfo.version)) { + command += " --tag next"; + } + + if (process.env.NPM_OTP && /^\d+$/.test(process.env.NPM_OTP)) { + command += "--otp=" + process.env.NPM_OTP; + } + + ShellOps.exec(command); + + console.log("Publishing to git"); + ShellOps.exec("git push origin master --tags"); + + publishReleaseToGitHub(releaseInfo); + + return releaseInfo; +} + //------------------------------------------------------------------------------ // Public API //------------------------------------------------------------------------------ module.exports = { getPrereleaseVersion: getPrereleaseVersion, - release: release, + generateRelease: generateRelease, + publishRelease: publishRelease, calculateReleaseInfo: calculateReleaseInfo, calculateReleaseFromGitLogs: calculateReleaseFromGitLogs, - writeChangelog: writeChangelog, - publishReleaseToGitHub: publishReleaseToGitHub + writeChangelog: writeChangelog }; diff --git a/lib/shell-ops.js b/lib/shell-ops.js index 8f9bd4a..132490f 100644 --- a/lib/shell-ops.js +++ b/lib/shell-ops.js @@ -74,6 +74,7 @@ module.exports = { * @private */ exec: function(cmd) { + console.log("+ " + cmd); var result = this.execSilent(cmd); console.log(result); }, diff --git a/package.json b/package.json index f08efff..96fa2e4 100644 --- a/package.json +++ b/package.json @@ -7,19 +7,17 @@ "node": ">=0.12" }, "bin": { - "eslint-release": "./bin/eslint-release.js", - "eslint-ci-release": "./bin/eslint-ci-release.js", - "eslint-gh-release": "./bin/eslint-gh-release.js", - "eslint-prerelease": "./bin/eslint-prerelease.js" + "eslint-generate-release": "./bin/eslint-generate-release.js", + "eslint-generate-prerelease": "./bin/eslint-generate-prerelease.js", + "eslint-publish-release": "./bin/eslint-publish-release.js" }, "scripts": { "test": "npm run lint && mocha tests/lib/*.js", "lint": "eslint .", - "alpharelease": "node ./bin/eslint-prerelease.js alpha", - "betarelease": "node ./bin/eslint-prerelease.js beta", - "release": "node ./bin/eslint-release.js", - "gh-release": "node ./bin/eslint-gh-release.js", - "ci-release": "node ./bin/eslint-ci-release.js" + "generate-alpharelease": "node ./bin/eslint-generate-prerelease.js alpha", + "generate-betarelease": "node ./bin/eslint-generate-prerelease.js beta", + "generate-release": "node ./bin/eslint-generate-release.js", + "publish-release": "node ./bin/eslint-publish-release.js" }, "files": [ "bin", @@ -51,7 +49,6 @@ "dateformat": "^1.0.12", "github-api": "2.3.0", "linefix": "^0.1.1", - "npm-license": "^0.3.1", "semver": "^5.1.0", "shelljs": "^0.5.3" }