diff --git a/.gitignore b/.gitignore index b1eb16ce..1ce7a4c0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,9 @@ -# common coverage node_modules test/registry/couch test/registry/data +test/tmp *.log *.dump .DS_Store .nyc_output -.test -.tmp - -# build-artifacts -dist diff --git a/.npmignore b/.npmignore deleted file mode 100644 index e3f24950..00000000 --- a/.npmignore +++ /dev/null @@ -1,18 +0,0 @@ -# common -coverage -node_modules -test/registry/couch -test/registry/data -*.log -*.dump -.DS_Store -.nyc_output -.test -.tmp - -# source/config -src -*.yml -.gitignore -.editorconfig -.npmrc diff --git a/.travis.yml b/.travis.yml index bdb8bf04..074a0118 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,10 +6,9 @@ cache: notifications: email: false node_js: -- v5 -- v4 -- iojs-v2 -- iojs-v1 +- 5 +- 4 +- iojs - '0.12' - '0.10' before_install: @@ -19,3 +18,5 @@ before_script: after_success: - npm run coverage:upload - npm run semantic-release +services: +- couchdb diff --git a/README.md b/README.md index 7bf749f6..778c89b7 100644 --- a/README.md +++ b/README.md @@ -257,9 +257,7 @@ It is indeed a great idea because it _forces_ you to follow best practices. If y ### Why should I trust `semantic-release` with my releases? -`semantic-release` has a full unit- and integration-test-suite that tests _actual_ `npm` publishes against the [npm-registry-couchapp](https://github.com/npm/npm-registry-couchapp/) on node.js `^0.10`, `^0.12` and io.js `^1`, `^2`. A new version won’t get published if it doesn’t pass on all these engines. - -Note: Currently integration-tests don’t run on Travis CI. If you know stuff about npm/Travis/Couch: Please help! +`semantic-release` has a full unit- and integration-test-suite that tests _actual_ `npm` publishes against the [npm-registry-couchapp](https://github.com/npm/npm-registry-couchapp/) on all major node.js versions from `^0.10` on. A new version won’t get published if it doesn’t pass on all these engines. ## Badge diff --git a/bin/semantic-release.js b/bin/semantic-release.js index edcd96a3..ac37c2f6 100755 --- a/bin/semantic-release.js +++ b/bin/semantic-release.js @@ -1,13 +1,163 @@ #!/usr/bin/env node -/* istanbul ignore next */ -try { - require('../dist') -} catch (err) { - if (err.code === 'MODULE_NOT_FOUND') { - require('babel/register') - require('../src') - } else { - console.log(err) - } +var fs = require('fs') +var path = require('path') +var url = require('url') + +var _ = require('lodash') +var log = require('npmlog') +var nopt = require('nopt') +var npmconf = require('npmconf') +var normalizeData = require('normalize-package-data') + +log.heading = 'semantic-release' +var env = process.env +var pkg = JSON.parse(fs.readFileSync('./package.json')) +normalizeData(pkg) +var knownOptions = { + branch: String, + debug: Boolean, + 'github-token': String, + 'github-url': String, + 'analyze-commits': [path, String], + 'generate-notes': [path, String], + 'verify-conditions': [path, String], + 'verify-release': [path, String] } +var options = _.defaults( + _.mapKeys(nopt(knownOptions), function (value, key) { + return _.camelCase(key) + }), + pkg.release, + { + branch: 'master', + fallbackTags: { + next: 'latest' + }, + debug: !env.CI, + githubToken: env.GH_TOKEN || env.GITHUB_TOKEN, + githubUrl: env.GH_URL + } +) +var plugins = require('../src/lib/plugins')(options) + +npmconf.load({}, function (err, conf) { + if (err) { + log.error('init', 'Failed to load npm config.', err) + process.exit(1) + } + + var npm = { + auth: { + token: env.NPM_TOKEN + }, + loglevel: conf.get('loglevel'), + registry: require('../src/lib/get-registry')(pkg, conf), + tag: (pkg.publishConfig || {}).tag || conf.get('tag') || 'latest' + } + + // normalize trailing slash + npm.registry = url.format(url.parse(npm.registry)) + + log.level = npm.loglevel + + var config = { + env: env, + pkg: pkg, + options: options, + plugins: plugins, + npm: npm + } + + var hide = {} + if (options.githubToken) hide.githubToken = '***' + + log.verbose('init', 'options:', _.assign({}, options, hide)) + log.verbose('init', 'Verifying config.') + + var errors = require('../src/lib/verify')(config) + errors.forEach(function (err) { + log.error('init', err.message + ' ' + err.code) + }) + if (errors.length) process.exit(1) + + if (options.argv.remain[0] === 'pre') { + log.verbose('pre', 'Running pre-script.') + log.verbose('pre', 'Veriying conditions.') + + plugins.verifyConditions(config, function (err) { + if (err) { + log[options.debug ? 'warn' : 'error']('pre', err.message) + if (!options.debug) process.exit(1) + } + + var nerfDart = require('nerf-dart')(npm.registry) + var wroteNpmRc = false + + if (env.NPM_OLD_TOKEN && env.NPM_EMAIL) { + // Using the old auth token format is not considered part of the public API + // This might go away anytime (i.e. once we have a better testing strategy) + conf.set('_auth', '${NPM_OLD_TOKEN}', 'project') + conf.set('email', '${NPM_EMAIL}', 'project') + wroteNpmRc = true + } else if (env.NPM_TOKEN) { + conf.set(nerfDart + ':_authToken', '${NPM_TOKEN}', 'project') + wroteNpmRc = true + } + + conf.save('project', function (err) { + if (err) return log.error('pre', 'Failed to save npm config.', err) + + if (wroteNpmRc) log.verbose('pre', 'Wrote authToken to .npmrc.') + + require('../src/pre')(config, function (err, release) { + if (err) { + log.error('pre', 'Failed to determine new version.') + + var args = ['pre', (err.code ? err.code + ' ' : '') + err.message] + if (err.stack) args.push(err.stack) + log.error.apply(log, args) + process.exit(1) + } + + var message = 'Determined version ' + release.version + ' as "' + npm.tag + '".' + + log.verbose('pre', message) + + if (options.debug) { + log.error('pre', message + ' Not publishing in debug mode.', release) + process.exit(1) + } + + try { + var shrinkwrap = JSON.parse(fs.readFileSync('./npm-shrinkwrap.json')) + shrinkwrap.version = release.version + fs.writeFileSync('./npm-shrinkwrap.json', JSON.stringify(shrinkwrap, null, 2)) + log.verbose('pre', 'Wrote version ' + release.version + 'to npm-shrinkwrap.json.') + } catch (e) { + log.silly('pre', 'Couldn\'t find npm-shrinkwrap.json.') + } + + fs.writeFileSync('./package.json', JSON.stringify(_.assign(pkg, { + version: release.version + }), null, 2)) + + log.verbose('pre', 'Wrote version ' + release.version + ' to package.json.') + }) + }) + }) + } else if (options.argv.remain[0] === 'post') { + log.verbose('post', 'Running post-script.') + + require('../src/post')(config, function (err, published, release) { + if (err) { + log.error('post', 'Failed to publish release notes.', err) + process.exit(1) + } + + log.verbose('post', (published ? 'Published' : 'Generated') + ' release notes.', release) + }) + } else { + log.error('post', 'Command "' + options.argv.remain[0] + '" not recognized. User either "pre" or "post"') + } +}) diff --git a/package.json b/package.json index 2f74f7f4..db3bede3 100644 --- a/package.json +++ b/package.json @@ -1,21 +1,14 @@ { "name": "semantic-release", "description": "automated semver compliant package publishing", + "version": "0.0.0-placeholder", "author": "Stephan Bönnemann (http://boennemann.me)", "bin": { - "semantic-release": "./bin/semantic-release.js" + "semantic-release": "bin/semantic-release.js" }, "bugs": { "url": "https://github.com/semantic-release/semantic-release/issues" }, - "config": { - "nyc": { - "exclude": [ - ".test", - "node_modules" - ] - } - }, "czConfig": { "path": "node_modules/cz-conventional-changelog/" }, @@ -40,7 +33,6 @@ "semver": "^5.0.3" }, "devDependencies": { - "babel": "^5.8.21", "coveralls": "^2.11.4", "cz-conventional-changelog": "^1.1.4", "mkdirp": "^0.5.1", @@ -49,7 +41,7 @@ "npm-registry-couchapp": "^2.6.11", "nyc": "^5.0.0", "proxyquire": "^1.7.3", - "rimraf": "^2.4.3", + "rimraf": "^2.5.0", "standard": "^5.3.0", "tap": "^4.0.0" }, @@ -70,7 +62,11 @@ "version" ], "license": "MIT", - "main": "dist/index.js", + "main": "bin/semantic-release.js", + "files": [ + "bin", + "src" + ], "publishConfig": { "tag": "next" }, @@ -82,17 +78,12 @@ "url": "git+https://github.com/semantic-release/semantic-release.git" }, "scripts": { - "build": "rimraf dist && mkdirp dist && babel src --out-dir dist", "coverage": "nyc report", - "coverage:upload": "npm run coverage -- --reporter=lcovonly && coveralls < coverage/lcov.info", - "prepublish": "npm run build", - "pretest:integration": "npm run build && npm run test:build", - "pretest:unit": "npm run build && npm run test:build", - "semantic-release": "./bin/semantic-release.js pre && npm dedupe && npm publish && ./bin/semantic-release.js post", - "test": "npm run test:style && npm run test:unit", - "test:build": "rimraf .test && mkdirp .test && babel test --out-dir .test", - "test:integration": "tap --no-cov .test/scenarios/*.js", - "test:style": "standard", - "test:unit": "nyc tap --no-cov .test/specs/*.js" + "coverage:upload": "npm run coverage -s -- --reporter=text-lcov | coveralls", + "pretest": "standard", + "semantic-release": "./bin/semantic-release.js pre && npm publish && ./bin/semantic-release.js post", + "test": "npm run test:unit && npm run test:integration", + "test:integration": "tap --no-cov test/scenarios/*.js", + "test:unit": "nyc tap --no-cov test/specs/*.js" } } diff --git a/src/index.js b/src/index.js deleted file mode 100644 index 9f44e819..00000000 --- a/src/index.js +++ /dev/null @@ -1,150 +0,0 @@ -const { readFileSync, writeFileSync } = require('fs') -const path = require('path') -const url = require('url') - -const _ = require('lodash') -const log = require('npmlog') -const nopt = require('nopt') -const npmconf = require('npmconf') -const normalizeData = require('normalize-package-data') - -log.heading = 'semantic-release' -const env = process.env -const pkg = normalizeData(readFileSync('./package.json')) -const knownOptions = { - branch: String, - debug: Boolean, - 'github-token': String, - 'github-url': String, - 'analyze-commits': [path, String], - 'generate-notes': [path, String], - 'verify-conditions': [path, String], - 'verify-release': [path, String] -} -const options = _.defaults( - _.mapKeys(nopt(knownOptions), (value, key) => _.camelCase(key)), - pkg.release, - { - branch: 'master', - fallbackTags: { - next: 'latest' - }, - debug: !env.CI, - githubToken: env.GH_TOKEN || env.GITHUB_TOKEN, - githubUrl: env.GH_URL - } -) -const plugins = require('./lib/plugins')(options) - -npmconf.load({}, (err, conf) => { - if (err) { - log.error('init', 'Failed to load npm config.', err) - process.exit(1) - } - - let npm = { - auth: { - token: env.NPM_TOKEN - }, - loglevel: conf.get('loglevel'), - registry: require('./lib/get-registry')(pkg, conf), - tag: (pkg.publishConfig || {}).tag || conf.get('tag') || 'latest' - } - - // normalize trailing slash - npm.registry = url.format(url.parse(npm.registry)) - - log.level = npm.loglevel - - const config = {env, pkg, options, plugins, npm} - - let hide = {} - if (options.githubToken) hide.githubToken = '***' - - log.verbose('init', 'options:', _.assign({}, options, hide)) - log.verbose('init', 'Verifying config.') - - const errors = require('./lib/verify')(config) - errors.forEach((err) => log.error('init', `${err.message} ${err.code}`)) - if (errors.length) process.exit(1) - - if (options.argv.remain[0] === 'pre') { - log.verbose('pre', 'Running pre-script.') - log.verbose('pre', 'Veriying conditions.') - - plugins.verifyConditions(config, (err) => { - if (err) { - log[options.debug ? 'warn' : 'error']('pre', err.message) - if (!options.debug) process.exit(1) - } - - const nerfDart = require('nerf-dart')(npm.registry) - let wroteNpmRc = false - - if (env.NPM_TOKEN) { - conf.set(`${nerfDart}:_authToken`, '${NPM_TOKEN}', 'project') - wroteNpmRc = true - } else if (env.NPM_OLD_TOKEN && env.NPM_EMAIL) { - // Using the old auth token format is not considered part of the public API - // This might go away anytime (i.e. once we have a better testing strategy) - conf.set('_auth', '${NPM_OLD_TOKEN}', 'project') - conf.set('email', '${NPM_EMAIL}', 'project') - wroteNpmRc = true - } - - conf.save('project', (err) => { - if (err) return log.error('pre', 'Failed to save npm config.', err) - - if (wroteNpmRc) log.verbose('pre', 'Wrote authToken to .npmrc.') - - require('./pre')(config, (err, release) => { - if (err) { - log.error('pre', 'Failed to determine new version.') - - const args = ['pre', (err.code ? `${err.code} ` : '') + err.message] - if (err.stack) args.push(err.stack) - log.error(...args) - process.exit(1) - } - - const message = `Determined version ${release.version} as "${npm.tag}".` - - log.verbose('pre', message) - - if (options.debug) { - log.error('pre', `${message} Not publishing in debug mode.`, release) - process.exit(1) - } - - try { - let shrinkwrap = JSON.parse(readFileSync('./npm-shrinkwrap.json')) - shrinkwrap.version = release.version - writeFileSync('./npm-shrinkwrap.json', JSON.stringify(shrinkwrap, null, 2)) - log.verbose('pre', `Wrote version ${release.version} to npm-shrinkwrap.json.`) - } catch (e) { - log.silly('pre', `Couldn't find npm-shrinkwrap.json.`) - } - - writeFileSync('./package.json', JSON.stringify(_.assign(pkg, { - version: release.version - }), null, 2)) - - log.verbose('pre', `Wrote version ${release.version} to package.json.`) - }) - }) - }) - } else if (options.argv.remain[0] === 'post') { - log.verbose('post', 'Running post-script.') - - require('./post')(config, (err, published, release) => { - if (err) { - log.error('post', 'Failed to publish release notes.', err) - process.exit(1) - } - - log.verbose('post', `${published ? 'Published' : 'Generated'} release notes.`, release) - }) - } else { - log.error('post', `Command "${options.argv.remain[0]}" not recognized. User either "pre" or "post"`) - } -}) diff --git a/src/lib/commits.js b/src/lib/commits.js index 76f0da5f..cbb2d537 100644 --- a/src/lib/commits.js +++ b/src/lib/commits.js @@ -1,39 +1,43 @@ -const { exec } = require('child_process') +var exec = require('child_process').exec -const log = require('npmlog') +var log = require('npmlog') -const SemanticReleaseError = require('@semantic-release/error') +var SemanticReleaseError = require('@semantic-release/error') -module.exports = function ({lastRelease, options}, cb) { - const branch = options.branch - const from = lastRelease.gitHead - const range = (from ? from + '..' : '') + 'HEAD' +module.exports = function (config, cb) { + var lastRelease = config.lastRelease + var options = config.options + var branch = options.branch + var from = lastRelease.gitHead + var range = (from ? from + '..' : '') + 'HEAD' if (!from) return extract() - exec(`git branch --contains ${from}`, (err, stdout) => { - let inHistory = false - let branches + exec('git branch --contains ' + from, function (err, stdout) { + var inHistory = false + var branches if (!err && stdout) { branches = stdout.split('\n') - .map((result) => { + .map(function (result) { if (branch === result.replace('*', '').trim()) { inHistory = true return null } return result.trim() }) - .filter(branch => !!branch) + .filter(function (branch) { + return !!branch + }) } if (!inHistory) { log.error('commits', -`The commit the last release of this package was derived from is not in the direct history of the "${branch}" branch. -This means semantic-release can not extract the commits between now and then. -This is usually caused by force pushing, releasing from an unrelated branch, or using an already existing package name. -You can recover from this error by publishing manually or restoring the commit "${from}".` + (branches && branches.length - ? `\nHere is a list of branches that still contain the commit in question: \n * ${branches.join('\n * ')}` + 'The commit the last release of this package was derived from is not in the direct history of the "' + branch + '" branch.\n' + + 'This means semantic-release can not extract the commits between now and then.\n' + + 'This is usually caused by force pushing, releasing from an unrelated branch, or using an already existing package name.\n' + + 'You can recover from this error by publishing manually or restoring the commit "' + from + '".' + (branches && branches.length + ? '\nHere is a list of branches that still contain the commit in question: \n * ' + branches.join('\n * ') : '' )) return cb(new SemanticReleaseError('Commit not in history', 'ENOTINHISTORY')) @@ -44,16 +48,18 @@ You can recover from this error by publishing manually or restoring the commit " function extract () { exec( - `git log -E --format=%H==SPLIT==%B==END== ${range}`, - (err, stdout) => { + 'git log -E --format=%H==SPLIT==%B==END== ' + range, + function (err, stdout) { if (err) return cb(err) cb(null, String(stdout).split('==END==\n') - .filter((raw) => !!raw.trim()) + .filter(function (raw) { + return !!raw.trim() + }) - .map((raw) => { - const data = raw.split('==SPLIT==') + .map(function (raw) { + var data = raw.split('==SPLIT==') return { hash: data[0], message: data[1] diff --git a/src/lib/get-registry.js b/src/lib/get-registry.js index a7557c9c..d7006fab 100644 --- a/src/lib/get-registry.js +++ b/src/lib/get-registry.js @@ -3,8 +3,8 @@ module.exports = function (pkg, conf) { if (pkg.name[0] !== '@') return conf.get('registry') || 'https://registry.npmjs.org/' - const scope = pkg.name.split('/')[0] - const scopedRegistry = conf.get(`${scope}/registry`) + var scope = pkg.name.split('/')[0] + var scopedRegistry = conf.get(scope + '/registry') if (scopedRegistry) return scopedRegistry diff --git a/src/lib/plugins.js b/src/lib/plugins.js index 3f1186b2..6ed71154 100644 --- a/src/lib/plugins.js +++ b/src/lib/plugins.js @@ -1,14 +1,14 @@ -const relative = require('require-relative') -const series = require('run-series') +var relative = require('require-relative') +var series = require('run-series') -let exports = module.exports = function (options) { +var exports = module.exports = function (options) { var plugins = { analyzeCommits: exports.normalize(options.analyzeCommits, '@semantic-release/commit-analyzer'), generateNotes: exports.normalize(options.generateNotes, '@semantic-release/release-notes-generator'), getLastRelease: exports.normalize(options.getLastRelease, '@semantic-release/last-release-npm') } - ;['verifyConditions', 'verifyRelease'].forEach((plugin) => { + ;['verifyConditions', 'verifyRelease'].forEach(function (plugin) { if (!Array.isArray(options[plugin])) { plugins[plugin] = exports.normalize( options[plugin], @@ -20,7 +20,7 @@ let exports = module.exports = function (options) { } plugins[plugin] = function (pluginOptions, cb) { - var tasks = options[plugin].map((step) => { + var tasks = options[plugin].map(function (step) { return exports.normalize(step, './plugin-noop').bind(null, pluginOptions) }) diff --git a/src/lib/type.js b/src/lib/type.js index d22ffa73..6787d6ea 100644 --- a/src/lib/type.js +++ b/src/lib/type.js @@ -1,9 +1,10 @@ -const SemanticReleaseError = require('@semantic-release/error') +var SemanticReleaseError = require('@semantic-release/error') module.exports = function (config, cb) { - const { plugins, lastRelease } = config + var plugins = config.plugins + var lastRelease = config.lastRelease - plugins.analyzeCommits(config, (err, type) => { + plugins.analyzeCommits(config, function (err, type) { if (err) return cb(err) if (!type) { diff --git a/src/lib/verify.js b/src/lib/verify.js index 38c952ca..729508c1 100644 --- a/src/lib/verify.js +++ b/src/lib/verify.js @@ -1,9 +1,12 @@ -const parseSlug = require('parse-github-repo-url') +var parseSlug = require('parse-github-repo-url') -const SemanticReleaseError = require('@semantic-release/error') +var SemanticReleaseError = require('@semantic-release/error') -module.exports = function ({pkg, options, env}) { - let errors = [] +module.exports = function (config) { + var pkg = config.pkg + var options = config.options + var env = config.env + var errors = [] if (!pkg.name) { errors.push(new SemanticReleaseError( diff --git a/src/post.js b/src/post.js index e4794db8..0753be9e 100644 --- a/src/post.js +++ b/src/post.js @@ -1,32 +1,34 @@ -const url = require('url') +var url = require('url') -const gitHead = require('git-head') -const GitHubApi = require('github') -const parseSlug = require('parse-github-repo-url') +var gitHead = require('git-head') +var GitHubApi = require('github') +var parseSlug = require('parse-github-repo-url') module.exports = function (config, cb) { - const { pkg, options, plugins } = config - const ghConfig = options.githubUrl ? url.parse(options.githubUrl) : {} + var pkg = config.pkg + var options = config.options + var plugins = config.plugins + var ghConfig = options.githubUrl ? url.parse(options.githubUrl) : {} - const github = new GitHubApi({ + var github = new GitHubApi({ version: '3.0.0', port: ghConfig.port, protocol: (ghConfig.protocol || '').split(':')[0] || null, host: ghConfig.hostname }) - plugins.generateNotes(config, (err, log) => { + plugins.generateNotes(config, function (err, log) { if (err) return cb(err) - gitHead((err, hash) => { + gitHead(function (err, hash) { if (err) return cb(err) - const ghRepo = parseSlug(pkg.repository.url) - const release = { + var ghRepo = parseSlug(pkg.repository.url) + var release = { owner: ghRepo[0], repo: ghRepo[1], - name: `v${pkg.version}`, - tag_name: `v${pkg.version}`, + name: 'v' + pkg.version, + tag_name: 'v' + pkg.version, target_commitish: hash, draft: !!options.debug, body: log @@ -41,7 +43,7 @@ module.exports = function (config, cb) { token: options.githubToken }) - github.releases.createRelease(release, (err) => { + github.releases.createRelease(release, function (err) { if (err) return cb(err) cb(null, true, release) diff --git a/src/pre.js b/src/pre.js index 4d2cd3e8..99ea49d2 100644 --- a/src/pre.js +++ b/src/pre.js @@ -1,32 +1,32 @@ -const _ = require('lodash') -const auto = require('run-auto') -const semver = require('semver') +var _ = require('lodash') +var auto = require('run-auto') +var semver = require('semver') -const getCommits = require('./lib/commits') -const getType = require('./lib/type') +var getCommits = require('./lib/commits') +var getType = require('./lib/type') module.exports = function (config, cb) { - const { plugins } = config + var plugins = config.plugins auto({ lastRelease: plugins.getLastRelease.bind(null, config), - commits: ['lastRelease', (cb, results) => { + commits: ['lastRelease', function (cb, results) { getCommits(_.assign({ lastRelease: results.lastRelease }, config), cb) }], - type: ['commits', 'lastRelease', (cb, results) => { + type: ['commits', 'lastRelease', function (cb, results) { getType(_.assign({ commits: results.commits, lastRelease: results.lastRelease }, config), cb) }] - }, (err, results) => { + }, function (err, results) { if (err) return cb(err) - const nextRelease = { + var nextRelease = { type: results.type, version: results.type === 'initial' ? '1.0.0' @@ -36,8 +36,8 @@ module.exports = function (config, cb) { plugins.verifyRelease(_.assign({ commits: results.commits, lastRelease: results.lastRelease, - nextRelease - }, config), (err) => { + nextRelease: nextRelease + }, config), function (err) { if (err) return cb(err) cb(null, nextRelease) }) diff --git a/test/lib/base-scenario.js b/test/lib/base-scenario.js index cf1a904b..314548f6 100644 --- a/test/lib/base-scenario.js +++ b/test/lib/base-scenario.js @@ -1,4 +1,4 @@ -const nixt = require('nixt') +var nixt = require('nixt') module.exports = function (cwd, uri) { return nixt() @@ -7,8 +7,6 @@ module.exports = function (cwd, uri) { .env('NPM_EMAIL', 'integration@test.com') .env('GH_TOKEN', 'ghtoken') .env('CI', 'true') - .env('TRAVIS', 'true') - .env('TRAVIS_BRANCH', 'master') .env('npm_config_registry', uri) .clone() } diff --git a/test/lib/test-module.js b/test/lib/test-module.js index ed031635..36647f57 100644 --- a/test/lib/test-module.js +++ b/test/lib/test-module.js @@ -1,40 +1,31 @@ -const { exec } = require('child_process') -const { join } = require('path') -const { writeFileSync } = require('fs') +var exec = require('child_process').exec +var join = require('path').join +var writeFileSync = require('fs').writeFileSync -const mkdirp = require('mkdirp') +var mkdirp = require('mkdirp') -module.exports = function (name, cb) { - const cwd = join(__dirname, '../tmp', name) +module.exports = function (name, registry, cb) { + var cwd = join(__dirname, '../tmp', name) mkdirp.sync(cwd) - writeFileSync(join(cwd, '.npmrc'), ` -//localhost:1337/registry/_design/app/_rewrite/:username=integration -//localhost:1337/registry/_design/app/_rewrite/:email=integration@test.com`, null, 2) - writeFileSync(join(cwd, 'package.json'), JSON.stringify({ - name, + name: name, repository: { url: 'git+https://github.com/semantic-release/test' }, - _npmUser: { - name: 'integration', - email: 'integration@test.com' - }, - maintainers: [{ - name: 'integration', - email: 'integration@test.com' - }] + release: { + verifyConditions: '../../../src/lib/plugin-noop' + } }, null, 2)) - exec(` - git init && - git config user.email "integration@test" && - git config user.name "Integration Test" && - git add . && - git commit -m "chore: root"` - , {cwd}, (err, stdout, stderr) => { + exec( + 'git init && ' + + 'git config user.email "integration@test" && ' + + 'git config user.name "Integration Test" && ' + + 'git add . && ' + + 'git commit -m "chore: root"' + , {cwd: cwd}, function (err, stdout, stderr) { if (err) { console.log(stdout, stderr) return cb(err) diff --git a/test/mocks/child-process.js b/test/mocks/child-process.js index a0c0f6a4..123f5b37 100644 --- a/test/mocks/child-process.js +++ b/test/mocks/child-process.js @@ -4,10 +4,10 @@ const rawCommits = [ ] module.exports = { - exec: (command, cb) => { + exec: function (command, cb) { if (/contains/.test(command)) { if (/notinhistory/.test(command)) return cb(new Error()) - return cb(null, `whatever\nmaster\n`) + return cb(null, 'whatever\nmaster\n') } cb( diff --git a/test/mocks/github.js b/test/mocks/github.js index a23ba987..b94d6cdd 100644 --- a/test/mocks/github.js +++ b/test/mocks/github.js @@ -1,6 +1,12 @@ -module.exports = () => ({ - authenticate: () => true, - releases: { - createRelease: (release, cb) => cb(null) +module.exports = function () { + return { + authenticate: function () { + return true + }, + releases: { + createRelease: function (release, cb) { + cb(null) + } + } } -}) +} diff --git a/test/registry/index.js b/test/registry/index.js index c688755e..f4c9da38 100644 --- a/test/registry/index.js +++ b/test/registry/index.js @@ -1,12 +1,11 @@ -const { exec } = require('child_process') -const { join } = require('path') +var exec = require('child_process').exec -const opts = { - cwd: join(__dirname, '../../test/registry') +var opts = { + cwd: __dirname } module.exports = { start: exec.bind(null, './start.sh', opts), stop: exec.bind(null, './stop.sh', opts), - uri: 'http://localhost:15986/registry/_design/app/_rewrite/' + uri: 'http://localhost:' + (process.env.TRAVIS === 'true' ? 5984 : 15986) + '/registry/_design/app/_rewrite/' } diff --git a/test/registry/start.sh b/test/registry/start.sh index 8ad797f6..9e7dad26 100755 --- a/test/registry/start.sh +++ b/test/registry/start.sh @@ -7,25 +7,29 @@ cd $(dirname $0) mkdir -p couch -# start couchdb as a background process, load local config, specify writable logfiles if [[ $TRAVIS = true ]] then - echo 'starting couch with sudo' - sudo couchdb -b -a local.ini -p couch/pid -o couch/stdout.log -e couch/stderr.log + COUCH=http://admin:password@127.0.0.1:5984 + + curl -X PUT http://127.0.0.1:5984/_config/admins/admin -d '"password"' + + curl -X PUT $COUCH/_config/couchdb/delayed_commits -d '"false"' + curl -X PUT $COUCH/_config/couch_httpd_auth/users_db_public -d '"true"' + curl -X PUT $COUCH/_config/couch_httpd_auth/public_fields -d '"appdotnet, avatar, avatarMedium, avatarLarge, date, email, fields, freenode, fullname, github, homepage, name, roles, twitter, type, _id, _rev"' + curl -X PUT $COUCH/_config/httpd/secure_rewrites -d '"false"' + else + COUCH=http://admin:password@127.0.0.1:15986 couchdb -b -a local.ini -p couch/pid -o couch/stdout.log -e couch/stderr.log + # wait for couch to start + sleep 1 fi -# wait for couch to start -sleep 5 - -COUCH=http://admin:password@127.0.0.1:15986 - # create "registry" database curl -X PUT $COUCH/registry # create sample npm user -curl -X PUT $COUCH/_users/org.couchdb.user:integration -H Content-Type:application/json --data-binary '{"_id": "org.couchdb.user:integration","name": "integration","roles": [],"type": "user","password": "suchsecure","email": "integration@test.com"}' +curl -X PUT $COUCH/_users/org.couchdb.user:integration -H Content-Type:application/json --data-binary '{"_id": "org.couchdb.user:integration", "name": "integration", "roles": [], "type": "user", "password": "suchsecure", "email": "integration@test.com"}' # npm-registry-couchpp needs this variable set to run export DEPLOY_VERSION=nope diff --git a/test/registry/stop.sh b/test/registry/stop.sh index 58703638..28a9157f 100755 --- a/test/registry/stop.sh +++ b/test/registry/stop.sh @@ -8,5 +8,6 @@ cd $(dirname $0) cat couch/{couch,stdout,stderr}.log +cat couch/pid | xargs kill rm -rf couch rm -rf data diff --git a/test/scenarios/pre.js b/test/scenarios/pre.js index 12acf2bd..cd6b70d4 100644 --- a/test/scenarios/pre.js +++ b/test/scenarios/pre.js @@ -1,30 +1,27 @@ -const { join } = require('path') +var join = require('path').join -const { test, tearDown } = require('tap') -const rimraf = require('rimraf') +var tap = require('tap') +var rimraf = require('rimraf') -const registry = require('../registry') -const testModule = require('../lib/test-module') -const baseScenario = require('../lib/base-scenario') +var registry = require('../registry') +var testModule = require('../lib/test-module') +var baseScenario = require('../lib/base-scenario') -test('change version', (t) => { +var tearDown = tap.tearDown +var test = tap.test + +test('change version', {bail: process.env.TRAVIS === 'true'}, function (t) { t.plan(7) - registry.start((err) => { + registry.start(function (err, stdout, stderr) { t.error(err, 'registry started') - if (err) { - t.end() - t.bailout('registry not started') - } + if (err) return t.end() - testModule('change-version', (err, cwd) => { + testModule('change-version', registry.uri, function (err, cwd) { t.error(err, 'test-module created') - if (err) { - t.end() - t.bailout('test-module not created') - } + if (err) return t.end() - t.test('no version', (tt) => { + t.test('no version', function (tt) { tt.plan(1) baseScenario(cwd, registry.uri) @@ -35,7 +32,7 @@ test('change version', (t) => { .end(tt.error) }) - t.test('initial version', (tt) => { + t.test('initial version', function (tt) { tt.plan(1) baseScenario(cwd, registry.uri) @@ -47,7 +44,7 @@ test('change version', (t) => { .end(tt.error) }) - t.test('patch version', (tt) => { + t.test('patch version', function (tt) { tt.plan(1) baseScenario(cwd, registry.uri) @@ -59,7 +56,7 @@ test('change version', (t) => { .end(tt.error) }) - t.test('feature version', (tt) => { + t.test('feature version', function (tt) { tt.plan(1) baseScenario(cwd, registry.uri) @@ -71,7 +68,7 @@ test('change version', (t) => { .end(tt.error) }) - t.test('breaking version', (tt) => { + t.test('breaking version', function (tt) { tt.plan(1) baseScenario(cwd, registry.uri) @@ -86,10 +83,11 @@ test('change version', (t) => { }) }) -tearDown(() => { +tearDown(function () { + if (process.env.TRAVIS === 'true') return + function cb (err, stdout, stderr) { if (err) console.log(err) - if (stdout) console.log(stdout) if (stderr) console.log(stderr) } diff --git a/test/specs/commits.js b/test/specs/commits.js index 2daae461..0f8a0bdb 100644 --- a/test/specs/commits.js +++ b/test/specs/commits.js @@ -1,13 +1,16 @@ -const test = require('tap').test -const proxyquire = require('proxyquire') +var test = require('tap').test +var proxyquire = require('proxyquire') -const commits = proxyquire('../../dist/lib/commits', { +var commits = proxyquire('../../src/lib/commits', { + 'npmlog': { + error: function () {} + }, 'child_process': require('../mocks/child-process') }) -test('commits since last release', (t) => { - t.test('get all commits', (tt) => { - commits({lastRelease: {}, options: {branch: 'master'}}, (err, commits) => { +test('commits since last release', function (t) { + t.test('get all commits', function (tt) { + commits({lastRelease: {}, options: {branch: 'master'}}, function (err, commits) { tt.error(err) tt.is(commits.length, 2, 'all commits') tt.is(commits[0].hash, 'hash-one', 'parsed hash') @@ -17,8 +20,8 @@ test('commits since last release', (t) => { }) }) - t.test('get commits since hash', (tt) => { - commits({lastRelease: {gitHead: 'hash'}, options: {branch: 'master'}}, (err, commits) => { + t.test('get commits since hash', function (tt) { + commits({lastRelease: {gitHead: 'hash'}, options: {branch: 'master'}}, function (err, commits) { tt.error(err) tt.is(commits.length, 1, 'specified commits') tt.is(commits[0].hash, 'hash-one', 'parsed hash') @@ -28,8 +31,8 @@ test('commits since last release', (t) => { }) }) - t.test('get commits since hash', (tt) => { - commits({lastRelease: {gitHead: 'notinhistory'}, options: {branch: 'notmaster'}}, (err, commits) => { + t.test('get commits since hash', function (tt) { + commits({lastRelease: {gitHead: 'notinhistory'}, options: {branch: 'notmaster'}}, function (err, commits) { tt.ok(err) tt.is(err.code, 'ENOTINHISTORY') tt.end() diff --git a/test/specs/get-registry.js b/test/specs/get-registry.js index 2b7d3f3c..5cbc636f 100644 --- a/test/specs/get-registry.js +++ b/test/specs/get-registry.js @@ -1,8 +1,8 @@ const test = require('tap').test -const getRegistry = require('../../dist/lib/get-registry') +const getRegistry = require('../../src/lib/get-registry') -test('get correct registry', (t) => { +test('get correct registry', function (t) { t.is(getRegistry({ name: 'publish-config', publishConfig: { @@ -10,20 +10,34 @@ test('get correct registry', (t) => { }}, {}), 'a') - t.is(getRegistry({name: 'normal'}, {get: () => 'b'}), 'b') + t.is(getRegistry({name: 'normal'}, { + get: function () { + return 'b' + } + }), 'b') - t.is(getRegistry({name: 'normal'}, {get: () => null}), 'https://registry.npmjs.org/') + t.is(getRegistry({name: 'normal'}, { + get: function () { + return null + } + }), 'https://registry.npmjs.org/') t.is(getRegistry({name: '@scoped/foo'}, { - get: (input) => input === '@scoped/registry' ? 'c' : 'd' + get: function (input) { + return input === '@scoped/registry' ? 'c' : 'd' + } }), 'c') t.is(getRegistry({name: '@scoped/bar'}, { - get: () => 'e' + get: function () { + return 'e' + } }), 'e') t.is(getRegistry({name: '@scoped/baz'}, { - get: () => null + get: function () { + return null + } }), 'https://registry.npmjs.org/') t.end() diff --git a/test/specs/plugins.js b/test/specs/plugins.js index dba5fa52..572db528 100644 --- a/test/specs/plugins.js +++ b/test/specs/plugins.js @@ -1,11 +1,11 @@ -const test = require('tap').test +var test = require('tap').test -const plugins = require('../../dist/lib/plugins') +var plugins = require('../../src/lib/plugins') -test('export plugins', (t) => { +test('export plugins', function (t) { t.plan(5) - const defaultPlugins = plugins({}) + var defaultPlugins = plugins({}) t.is(typeof defaultPlugins.analyzeCommits, 'function') t.is(typeof defaultPlugins.generateNotes, 'function') @@ -14,51 +14,51 @@ test('export plugins', (t) => { t.is(typeof defaultPlugins.getLastRelease, 'function') }) -test('plugin pipelines', (t) => { +test('plugin pipelines', function (t) { t.plan(3) - t.test('get all results', (tt) => { - const pipelinePlugins = plugins({ + t.test('get all results', function (tt) { + var pipelinePlugins = plugins({ verifyRelease: [ - './dist/lib/plugin-noop', - './.test/mocks/plugin-result-a', - './.test/mocks/plugin-result-b' + './src/lib/plugin-noop', + './test/mocks/plugin-result-a', + './test/mocks/plugin-result-b' ] }) - pipelinePlugins.verifyRelease({}, (err, results) => { + pipelinePlugins.verifyRelease({}, function (err, results) { tt.error(err) tt.same(results, [undefined, 'a', 'b']) tt.end() }) }) - t.test('get first error', (tt) => { - const pipelinePlugins = plugins({ + t.test('get first error', function (tt) { + var pipelinePlugins = plugins({ verifyConditions: [ - './dist/lib/plugin-noop', - './.test/mocks/plugin-error-a', - './.test/mocks/plugin-error-b' + './src/lib/plugin-noop', + './test/mocks/plugin-error-a', + './test/mocks/plugin-error-b' ] }) - pipelinePlugins.verifyConditions({}, (err) => { + pipelinePlugins.verifyConditions({}, function (err) { tt.is(err.message, 'a') tt.end() }) }) - t.test('get error and only results before', (tt) => { - const pipelinePlugins = plugins({ + t.test('get error and only results before', function (tt) { + var pipelinePlugins = plugins({ verifyRelease: [ - './dist/lib/plugin-noop', - './.test/mocks/plugin-result-a', - './.test/mocks/plugin-error-b', - './.test/mocks/plugin-result-b' + './src/lib/plugin-noop', + './test/mocks/plugin-result-a', + './test/mocks/plugin-error-b', + './test/mocks/plugin-result-b' ] }) - pipelinePlugins.verifyRelease({}, (err, results) => { + pipelinePlugins.verifyRelease({}, function (err, results) { tt.is(err.message, 'b') tt.same(results, [undefined, 'a', undefined]) tt.end() @@ -66,18 +66,18 @@ test('plugin pipelines', (t) => { }) }) -test('normalize and load plugin', (t) => { - t.test('load from string', (tt) => { - const plugin = plugins.normalize('./dist/lib/plugin-noop') +test('normalize and load plugin', function (t) { + t.test('load from string', function (tt) { + var plugin = plugins.normalize('./src/lib/plugin-noop') tt.is(typeof plugin, 'function') tt.end() }) - t.test('load from object', (tt) => { - const plugin = plugins.normalize({ - path: './dist/lib/plugin-noop' + t.test('load from object', function (tt) { + var plugin = plugins.normalize({ + path: './src/lib/plugin-noop' }) tt.is(typeof plugin, 'function') @@ -85,8 +85,8 @@ test('normalize and load plugin', (t) => { tt.end() }) - t.test('load from object', (tt) => { - const plugin = plugins.normalize(null, '../../dist/lib/plugin-noop') + t.test('load from fallback', function (tt) { + var plugin = plugins.normalize(null, '../../src/lib/plugin-noop') tt.is(typeof plugin, 'function') diff --git a/test/specs/post.js b/test/specs/post.js index 174cd296..cf0fa900 100644 --- a/test/specs/post.js +++ b/test/specs/post.js @@ -1,20 +1,24 @@ -const { defaults } = require('lodash') -const test = require('tap').test -const proxyquire = require('proxyquire') +var defaults = require('lodash').defaults +var test = require('tap').test +var proxyquire = require('proxyquire') -const post = proxyquire('../../dist/post', { +var post = proxyquire('../../src/post', { 'git-head': require('../mocks/git-head'), github: require('../mocks/github') }) -const pkg = { +var pkg = { version: '1.0.0', repository: {url: 'http://github.com/whats/up.git'} } -const plugins = {generateNotes: (pkg, cb) => cb(null, 'the log')} +var plugins = { + generateNotes: function (pkg, cb) { + cb(null, 'the log') + } +} -const defaultRelease = { +var defaultRelease = { owner: 'whats', repo: 'up', name: 'v1.0.0', @@ -23,13 +27,13 @@ const defaultRelease = { body: 'the log' } -test('full post run', (t) => { - t.test('in debug mode w/o token', (tt) => { +test('full post run', function (t) { + t.test('in debug mode w/o token', function (tt) { post({ options: {debug: true}, - pkg, - plugins - }, (err, published, release) => { + pkg: pkg, + plugins: plugins + }, function (err, published, release) { tt.error(err) tt.is(published, false) tt.match(release, defaults({draft: true}, defaultRelease)) @@ -38,12 +42,12 @@ test('full post run', (t) => { }) }) - t.test('in debug mode w/token', (tt) => { + t.test('in debug mode w/token', function (tt) { post({ options: {debug: true, githubToken: 'yo'}, - pkg, - plugins - }, (err, published, release) => { + pkg: pkg, + plugins: plugins + }, function (err, published, release) { tt.error(err) tt.is(published, true) tt.match(release, defaults({draft: true}, defaultRelease)) @@ -52,12 +56,12 @@ test('full post run', (t) => { }) }) - t.test('production', (tt) => { + t.test('production', function (tt) { post({ options: {githubToken: 'yo'}, - pkg, - plugins - }, (err, published, release) => { + pkg: pkg, + plugins: plugins + }, function (err, published, release) { tt.error(err) tt.is(published, true) tt.match(release, defaultRelease) diff --git a/test/specs/pre.js b/test/specs/pre.js index 6a140e05..ecb5de57 100644 --- a/test/specs/pre.js +++ b/test/specs/pre.js @@ -1,55 +1,59 @@ -const test = require('tap').test -const proxyquire = require('proxyquire') +var test = require('tap').test +var proxyquire = require('proxyquire') require('../mocks/registry') -const pre = proxyquire('../../dist/pre', { - './lib/commits': proxyquire('../../dist/lib/commits', { +var pre = proxyquire('../../src/pre', { + './lib/commits': proxyquire('../../src/lib/commits', { 'child_process': require('../mocks/child-process') }) }) -const versions = { +var versions = { available: '1.0.0' } -const plugins = { - verifyRelease: (release, cb) => cb(null, release), - analyzeCommits: (commits, cb) => cb(null, 'major'), - getLastRelease: ({ pkg }, cb) => { - cb(null, {version: versions[pkg.name] || null, gitHead: 'HEAD'}) +var plugins = { + verifyRelease: function (release, cb) { + cb(null, release) + }, + analyzeCommits: function (commits, cb) { + cb(null, 'major') + }, + getLastRelease: function (config, cb) { + cb(null, {version: versions[config.pkg.name] || null, gitHead: 'HEAD'}) } } -const npm = { +var npm = { registry: 'http://registry.npmjs.org/', tag: 'latest' } -test('full pre run', (t) => { - t.test('increase version', (tt) => { +test('full pre run', function (t) { + t.test('increase version', function (tt) { tt.plan(3) pre({ options: {branch: 'master'}, - npm, + npm: npm, pkg: {name: 'available'}, - plugins - }, (err, release) => { + plugins: plugins + }, function (err, release) { tt.error(err) tt.is(release.type, 'major') tt.is(release.version, '2.0.0') }) }) - t.test('increase version', (tt) => { + t.test('increase version', function (tt) { tt.plan(3) pre({ options: {branch: 'master'}, - npm, + npm: npm, pkg: {name: 'unavailable'}, - plugins - }, (err, release) => { + plugins: plugins + }, function (err, release) { tt.error(err) tt.is(release.type, 'initial') tt.is(release.version, '1.0.0') diff --git a/test/specs/type.js b/test/specs/type.js index 399c2a91..1acd6cde 100644 --- a/test/specs/type.js +++ b/test/specs/type.js @@ -1,9 +1,9 @@ -const test = require('tap').test +var test = require('tap').test -const type = require('../../dist/lib/type') +var type = require('../../src/lib/type') -test('get type from commits', (t) => { - t.test('get type from plugin', (tt) => { +test('get type from commits', function (t) { + t.test('get type from plugin', function (tt) { tt.plan(2) type({ @@ -12,33 +12,45 @@ test('get type from commits', (t) => { message: 'a' }], lastRelease: {version: '1.0.0'}, - plugins: {analyzeCommits: (config, cb) => cb(null, 'major')} - }, (err, type) => { + plugins: { + analyzeCommits: function (config, cb) { + cb(null, 'major') + } + } + }, function (err, type) { tt.error(err) tt.is(type, 'major') }) }) - t.test('error when no changes', (tt) => { + t.test('error when no changes', function (tt) { tt.plan(1) type({ commits: [], lastRelease: {}, - plugins: {analyzeCommits: (config, cb) => cb(null, null)} - }, (err) => { + plugins: { + analyzeCommits: function (config, cb) { + cb(null, null) + } + } + }, function (err) { tt.is(err.code, 'ENOCHANGE') }) }) - t.test('initial version', (tt) => { + t.test('initial version', function (tt) { tt.plan(2) type({ commits: [], lastRelease: {}, - plugins: {analyzeCommits: (config, cb) => cb(null, 'major')} - }, (err, type) => { + plugins: { + analyzeCommits: function (config, cb) { + cb(null, 'major') + } + } + }, function (err, type) { tt.error(err) tt.is(type, 'initial') }) diff --git a/test/specs/verify.js b/test/specs/verify.js index 7f4862c4..3cbae284 100644 --- a/test/specs/verify.js +++ b/test/specs/verify.js @@ -1,10 +1,10 @@ -const test = require('tap').test +var test = require('tap').test -const verify = require('../../dist/lib/verify') +var verify = require('../../src/lib/verify') -test('verify pkg, options and env', (t) => { - t.test('dry run verification', (tt) => { - const noErrors = verify({ +test('verify pkg, options and env', function (t) { + t.test('dry run verification', function (tt) { + var noErrors = verify({ options: {debug: true}, pkg: { name: 'package', @@ -16,7 +16,7 @@ test('verify pkg, options and env', (t) => { tt.is(noErrors.length, 0) - const errors = verify({ + var errors = verify({ options: {debug: true}, pkg: {} }) @@ -25,7 +25,7 @@ test('verify pkg, options and env', (t) => { tt.is(errors[0].code, 'ENOPKGNAME') tt.is(errors[1].code, 'ENOPKGREPO') - const errors2 = verify({ + var errors2 = verify({ options: {debug: true}, pkg: { name: 'package', @@ -41,8 +41,8 @@ test('verify pkg, options and env', (t) => { tt.end() }) - t.test('publish verification', (tt) => { - const noErrors = verify({ + t.test('publish verification', function (tt) { + var noErrors = verify({ env: {NPM_TOKEN: 'yo'}, options: {githubToken: 'sup'}, pkg: { @@ -55,7 +55,7 @@ test('verify pkg, options and env', (t) => { tt.is(noErrors.length, 0) - const errors = verify({env: {}, options: {}, pkg: {}}) + var errors = verify({env: {}, options: {}, pkg: {}}) tt.is(errors.length, 4) tt.is(errors[0].code, 'ENOPKGNAME')