Compare commits

..
8 Commits
Author SHA1 Message Date
Stephan Bönnemann 5711e95c79 fix: revert undeclared breaking change 2015-08-23 22:34:10 +02:00
Stephan Bönnemann e55b70dbf8 docs(README): list plugins and more talks 2015-08-23 22:26:35 +02:00
Stephan Bönnemann 399da06843 fix(condition-travis): remove need for python script travis_after_all 2015-08-23 00:57:37 +02:00
Stephan Bönnemann ee2a7306e7 chore(travis): upload coverage from all jobs 2015-08-22 23:59:25 +02:00
Stephan Bönnemann 03534e51bc fix(registry): be better at using the correct registry (relevant for npme)
Closes #53
2015-08-22 23:33:36 +02:00
Stephan Bönnemann 85b35aaed3 chore(package): update last-release-npm to 1.2.1 2015-08-22 21:48:16 +02:00
Stephan Bönnemann 360a514171 feat: add fallbackTag functionality
You can now map dist-tags onto "fallbackTags". E.g. if you want a
development channel like "next" and no version is currently published as "next"
semantic-release could fallback to "latest" to determine the new "next" version.
You can specify your mappings by adding "fallbackTags" to your
`package.json`'s "release" field.
2015-08-22 21:43:22 +02:00
Stephan Bönnemann 90174c80a0 chore: adopt things for being back on master/latest 2015-08-22 20:16:34 +02:00
29 changed files with 526 additions and 617 deletions
+6 -1
View File
@@ -1,9 +1,14 @@
# common
coverage
node_modules
test/registry/couch
test/registry/data
test/tmp
*.log
*.dump
.DS_Store
.nyc_output
.test
.tmp
# build-artifacts
dist
+18
View File
@@ -0,0 +1,18 @@
# 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
+2 -5
View File
@@ -6,9 +6,8 @@ cache:
notifications:
email: false
node_js:
- 5
- 4
- iojs
- iojs-v2
- iojs-v1
- '0.12'
- '0.10'
before_install:
@@ -18,5 +17,3 @@ before_script:
after_success:
- npm run coverage:upload
- npm run semantic-release
services:
- couchdb
+36 -75
View File
@@ -1,21 +1,16 @@
# :package::rocket: semantic-release
# semantic-release
**fully automated package publishing**
> **Trust us, this will change your workflow for the better.**
> [egghead.io](https://egghead.io/lessons/javascript-how-to-write-a-javascript-library-automating-releases-with-semantic-release)
> **fully automated, semver-compliant package publishing**
[![Join the chat at https://gitter.im/semantic-release/semantic-release](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/semantic-release/semantic-release?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard)
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
[![Dependency Status](https://david-dm.org/semantic-release/semantic-release/caribou.svg)](https://david-dm.org/semantic-release/semantic-release/caribou)
[![devDependency Status](https://david-dm.org/semantic-release/semantic-release/caribou/dev-status.svg)](https://david-dm.org/semantic-release/semantic-release/caribou#info=devDependencies)
[![Dependency Status](https://david-dm.org/semantic-release/semantic-release/next.svg)](https://david-dm.org/semantic-release/semantic-release/next)
[![devDependency Status](https://david-dm.org/semantic-release/semantic-release/next/dev-status.svg)](https://david-dm.org/semantic-release/semantic-release/next#info=devDependencies)
[![Build Status](https://travis-ci.org/semantic-release/semantic-release.svg?branch=caribou)](https://travis-ci.org/semantic-release/semantic-release)
[![Coverage Status](https://coveralls.io/repos/semantic-release/semantic-release/badge.svg?branch=caribou&service=github)](https://coveralls.io/github/semantic-release/semantic-release?branch=caribou)
[![Build Status](https://travis-ci.org/semantic-release/semantic-release.svg?branch=next)](https://travis-ci.org/semantic-release/semantic-release)
[![Coverage Status](https://coveralls.io/repos/semantic-release/semantic-release/badge.svg?branch=next&service=github)](https://coveralls.io/github/semantic-release/semantic-release?branch=next)
Out of the box this is just about _commit-messages_, but you can do so much more.
@@ -28,27 +23,12 @@ Out of the box this is just about _commit-messages_, but you can do so much more
  | Commands | Comment
--- | --- | ---
| **manual/before** | <pre><code><div>npm version major</div><div>git push origin master --tags</div><div>npm publish</div></code></pre> | You **manually decide** what the **next version** is. You have to remember what major, minor and patch means. You have to remember to push both commits and tags. You have to wait for the CI to pass. |
| **semantic-release/after** | <pre><code><div>git commit -m "fix: &lt;message&gt;"</div><div>git push</div></code></pre> | You **describe the changes** youve made. A new version is automatically published with the correct version number.
| **manual** | <pre><code><div>npm version major</div><div>git push origin master --tags</div><div>npm publish</div></code></pre> | You **manually decide** what the **next version** is. You have to remember what major, minor and patch means. You have to remember to push both commits and tags. You have to wait for the CI to pass. |
| **semantic-release** | <pre><code><div>git commit -m "fix: &lt;message&gt;"</div><div>git push</div></code></pre> | You **describe the changes** youve made. A new version is automatically published with the correct version number.
This removes the immediate connection between human emotions and version numbers, so strictly following the [SemVer](http://semver.org/) spec is not a problem anymore  and thats ultimately `semantic-release`s goal.
This removes the immediate connection between human emotions and version numbers, so strictly following the [SemVer](http://semver.org/) spec is not a problem anymore and thats ultimately `semantic-release`s goal.
<table>
<tr>
<th colspan="2">
“How to Write a JavaScript Library - Automating Releases with semantic-release”  egghead.io
</th>
</tr>
<tr>
<td colspan="2">
<a href="https://egghead.io/lessons/javascript-how-to-write-a-javascript-library-automating-releases-with-semantic-release"><img src="https://cloud.githubusercontent.com/assets/908178/9730739/7b1da5d8-5610-11e5-88b6-5c75fdda7ee2.png" alt="egghead.io session"></a>
</td>
</tr>
<tr>
<td colspan="2">
A free egghead.io tutorial series on how to write an open source library featuring semantic-release.
</td>
</tr>
<tr>
<th>
“We fail to follow SemVer and why it neednt matter”
@@ -77,11 +57,28 @@ This removes the immediate connection between human emotions and version numbers
## How does it work?
Instead of writing [meaningless commit messages](http://whatthecommit.com/), we can take our time to think about the changes in the codebase and write them down. Following formalized conventions it is then possible to generate a helpful changelog and to derive the next semantic version number from them.
Instead of writing [meaningless commit messages](http://whatthecommit.com/), we can take our time to think about the changes in the codebase and write them down. Following formalized conventions it this then possible to generate a helpful changelog and to derive the next semantic version number from them.
When `semantic-release` is setup it will do that after every successful continuous integration build of your master branch (or any other branch you specify) and publish the new version for you. This way no human is directly involved in the release process and your releases are guaranteed to be [unromantic and unsentimental](http://sentimentalversioning.org/).
_Note: This module ships with the [AngularJS Commit Message Conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit) and changelog generator, but you can [define your own](#plugins) style_.
If you fear the loss of control over timing and marketing implications of software releases you should know that `semantic-release` supports [release channels](https://github.com/npm/npm/issues/2718) using `npm`s [dist-tags](https://docs.npmjs.com/cli/dist-tag). This way you can keep control over what your users end up using by default, you can decide when to promote an automatically released version to the stable channel, and you can choose which versions to write blogposts and tweets about. You can use the same mechanism to [support older versions of your software](https://gist.github.com/boennemann/54042374e49c7ade8910), for example with important security fixes.
> ### Commit Message Format
> Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
format that includes a **type**, a **scope** and a **subject**:
> ```
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
```
> [Full explanation](https://github.com/ajoslin/conventional-changelog/blob/master/conventions/angular.md)
When `semantic-release` got setup it will do that after every successful continuous integration build of your master branch (or any other branch you specify) and publish the new version for you. That way no human is directly involved in the release process and your releases are guaranteed to be [unromantic and unsentimental](http://sentimentalversioning.org/).
If you fear the loss of control over timing and marketing implications of software releases you should know that `semantic-release` supports [release channels](https://github.com/npm/npm/issues/2718) using `npm`s [dist-tags](https://docs.npmjs.com/cli/tag). This way you can keep control over what your users end up using by default, you can decide when to promote an automatically released version to the stable channel and you can choose which versions to write blogposts and tweets about. You can use the same mechanism to support older versions of your software, for example with important security fixes.
This is what happens in series:
@@ -91,43 +88,6 @@ This is what happens in series:
_Note:_ The current release/tag implementation is tied to GitHub, but could be opened up to Bitbucket, GitLab, et al. Feel free to send PRs for these services.
## Default Commit Message Format
This module ships with the [AngularJS Commit Message Conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit) and changelog generator, but you can [define your own](#plugins) style.
Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
format that includes a **type**, a **scope** and a **subject** ([full explanation](https://github.com/stevemao/conventional-changelog-angular/blob/master/convention.md)):
```
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
```
You can simplify using this convention for yourself and contributors by using [commitizen](https://github.com/commitizen/cz-cli) and [validate-commit-msg](https://github.com/kentcdodds/validate-commit-msg).
### Patch Release
```
fix(pencil): stop graphite breaking when too much pressure applied
```
### ~~Minor~~ Feature Release
```
feat(pencil): add 'graphiteWidth' option
```
### ~~Major~~ Breaking Release
```
perf(pencil): remove graphiteWidth option
BREAKING CHANGE: The graphiteWidth option has been removed. The default graphite width of 10mm is always used for performance reason.
```
## Setup
[![NPM](https://nodei.co/npm/semantic-release.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/semantic-release/)
@@ -153,18 +113,17 @@ You can pass options either via command line (in [kebab-case](https://lodash.com
These options are currently available:
- `branch`: The branch on which releases should happen. Default: `'master'`
- `branch`: The branch on which releases should happen. Default: `master`
- `debug`: If true doesnt actually publish to npm or write things to file. Default: `!process.env.CI`
- `githubToken`: The token used to authenticate with GitHub. Default: `process.env.GH_TOKEN`
- `githubUrl`: Optional. Pass your GitHub Enterprise endpoint.
- `githubApiPathPrefix`: Optional. The path prefix for your GitHub Enterprise API.
_A few notes on `npm` config_:
1. The `npm` token can only be defined in the environment as `NPM_TOKEN`, because thats where `npm` itself is going to read it from.
2. In order to publish to a different `npm` registry you can specify that inside the `package.json`s [`publishConfig`](https://docs.npmjs.com/files/package.json#publishconfig) field.
2. In order to publish to a different `npm` registry you can just configure that how you would usually do it and `semantic-release` will respect that setting.
3. If you want to use another dist-tag for your publishes than `'latest'` you can specify that inside the `package.json`s [`publishConfig`](https://docs.npmjs.com/files/package.json#publishconfig) field.
3. If you want to use another dist-tag for your publishes than `latest` you can specify that inside the `package.json`s [`publishConfig`](https://docs.npmjs.com/files/package.json#publishconfig) field.
4. `semantic-release` generally tries to orientate itself towards `npm` it inherits the loglevel for example.
@@ -258,7 +217,9 @@ 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 all major node.js versions from `^0.10` on. A new version wont get published if it doesnt pass on all these engines.
`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 wont get published if it doesnt pass on all these engines.
Note: Currently integration-tests dont run on Travis CI. If you know stuff about npm/Travis/Couch: Please help!
## Badge
@@ -287,4 +248,4 @@ Use this in one of your projects? Include one of these badges in your README.md
MIT License
2015 © Stephan Bönnemann and [contributors](https://github.com/semantic-release/semantic-release/graphs/contributors)
[![](https://cloud.githubusercontent.com/assets/908178/6091690/cc86f58c-aeb8-11e4-94cb-15f15f486cde.png)](https://twitter.com/trodrigues/status/509301317467373571)
![https://twitter.com/trodrigues/status/509301317467373571](https://cloud.githubusercontent.com/assets/908178/6091690/cc86f58c-aeb8-11e4-94cb-15f15f486cde.png)
+9 -161
View File
@@ -1,165 +1,13 @@
#!/usr/bin/env node
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'))
var originalPkg = _.cloneDeep(pkg)
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
},
cafile: conf.get('cafile'),
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(originalPkg, {
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)
})
/* istanbul ignore next */
try {
require('../dist')
} catch (err) {
if (err.code === 'MODULE_NOT_FOUND') {
require('babel/register')
require('../src')
} else {
log.error('post', 'Command "' + options.argv.remain[0] + '" not recognized. Use either "pre" or "post"')
console.log(err)
}
})
}
+40 -42
View File
@@ -1,53 +1,56 @@
{
"name": "semantic-release",
"description": "automated semver compliant package publishing",
"version": "0.0.0-placeholder",
"author": "Stephan Bönnemann <stephan@boennemann.me> (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"
},
"czConfig": {
"path": "node_modules/cz-conventional-changelog/"
"engines": {
"node": ">=0.10",
"npm": ">=2"
},
"config": {
"nyc": {
"exclude": [
".test",
"node_modules"
]
}
},
"dependencies": {
"@bahmutov/parse-github-repo-url": "^0.1.0",
"@semantic-release/commit-analyzer": "^2.0.0",
"@semantic-release/condition-travis": "^5.0.2",
"@semantic-release/condition-travis": "^4.1.2",
"@semantic-release/error": "^1.0.0",
"@semantic-release/last-release-npm": "^1.2.1",
"@semantic-release/release-notes-generator": "^2.0.0",
"git-head": "^1.2.1",
"github": "^0.2.4",
"lodash": "^4.0.0",
"lodash": "^3.9.3",
"nerf-dart": "^1.0.0",
"nopt": "^3.0.3",
"normalize-package-data": "^2.3.4",
"npmconf": "^2.1.2",
"npmlog": "^4.0.0",
"npmlog": "^1.2.1",
"parse-github-repo-url": "^1.0.0",
"require-relative": "^0.8.7",
"run-auto": "^2.0.0",
"run-series": "^1.1.3",
"semver": "^5.0.3"
"run-auto": "^1.1.2",
"run-series": "^1.1.2",
"semver": "^5.0.1"
},
"devDependencies": {
"coveralls": "^2.11.4",
"cz-conventional-changelog": "^1.1.4",
"babel": "^5.5.8",
"coveralls": "^2.11.2",
"mkdirp": "^0.5.1",
"nixt": "^0.5.0",
"nock": "^8.0.0",
"nixt": "^0.4.1",
"nock": "^2.5.0",
"npm-registry-couchapp": "^2.6.11",
"nyc": "^7.0.0",
"proxyquire": "^1.7.3",
"rimraf": "^2.5.0",
"standard": "^7.0.1",
"tap": "^6.2.0"
},
"engines": {
"node": ">=0.10",
"npm": ">=2"
"nyc": "^3.0.0",
"proxyquire": "^1.5.0",
"rimraf": "^2.4.0",
"standard": "^5.0.2",
"tap": "^1.3.1"
},
"homepage": "https://github.com/semantic-release/semantic-release/tree/next#readme",
"keywords": [
@@ -62,28 +65,23 @@
"version"
],
"license": "MIT",
"main": "bin/semantic-release.js",
"files": [
"bin",
"src"
],
"publishConfig": {
"tag": "next"
},
"release": {
"branch": "caribou"
},
"main": "dist/index.js",
"repository": {
"type": "git",
"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 -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"
"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"
}
}
+137
View File
@@ -0,0 +1,137 @@
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')
log.heading = 'semantic-release'
const env = process.env
const pkg = JSON.parse(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',
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)
}
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"`)
}
})
+32 -41
View File
@@ -1,44 +1,40 @@
var exec = require('child_process').exec
const { exec } = require('child_process')
var log = require('npmlog')
const log = require('npmlog')
var SemanticReleaseError = require('@semantic-release/error')
const SemanticReleaseError = require('@semantic-release/error')
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'
module.exports = function ({lastRelease, options}, cb) {
const branch = options.branch
const from = lastRelease.gitHead
const range = (from ? from + '..' : '') + 'HEAD'
if (!from) return extract()
exec('git branch --contains ' + from, function (err, stdout) {
var inHistory = false
var branches
exec(`git branch --contains ${from}`, (err, stdout) => {
if (err) return cb(err)
let inHistory = false
if (!err && stdout) {
branches = stdout.split('\n')
.map(function (result) {
if (branch === result.replace('*', '').trim()) {
inHistory = true
return null
}
return result.trim()
})
.filter(function (branch) {
return !!branch
})
}
const branches = stdout.split('\n')
.map((result) => {
if (branch === result.replace('*', '').trim()) {
inHistory = true
return null
}
return result.trim()
})
.filter(branch => !!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.\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 * ')
: ''
`The commit the last release of this package was derived from is no longer
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 or releasing from an unrelated branch.
You can recover from this error by publishing manually or restoring
the commit "${from}".` + (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'))
}
@@ -48,21 +44,16 @@ module.exports = function (config, cb) {
function extract () {
exec(
'git log -E --format=%H==SPLIT==%B==END== ' + range,
{
maxBuffer: 1024 * 1024 // 1MB instead of 220KB (issue #286)
},
function (err, stdout) {
`git log -E --format=%H==SPLIT==%B==END== ${range}`,
(err, stdout) => {
if (err) return cb(err)
cb(null, String(stdout).split('==END==\n')
.filter(function (raw) {
return !!raw.trim()
})
.filter((raw) => !!raw.trim())
.map(function (raw) {
var data = raw.split('==SPLIT==')
.map((raw) => {
const data = raw.split('==SPLIT==')
return {
hash: data[0],
message: data[1]
+2 -2
View File
@@ -3,8 +3,8 @@ module.exports = function (pkg, conf) {
if (pkg.name[0] !== '@') return conf.get('registry') || 'https://registry.npmjs.org/'
var scope = pkg.name.split('/')[0]
var scopedRegistry = conf.get(scope + '/registry')
const scope = pkg.name.split('/')[0]
const scopedRegistry = conf.get(`${scope}/registry`)
if (scopedRegistry) return scopedRegistry
+8 -8
View File
@@ -1,26 +1,26 @@
var relative = require('require-relative')
var series = require('run-series')
const relative = require('require-relative')
const series = require('run-series')
var exports = module.exports = function (options) {
let 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(function (plugin) {
;['verifyConditions', 'verifyRelease'].forEach((plugin) => {
if (!Array.isArray(options[plugin])) {
plugins[plugin] = exports.normalize(
options[plugin],
plugin === 'verifyConditions'
? '@semantic-release/condition-travis'
: './plugin-noop'
plugin === 'verifyConditions' ?
'@semantic-release/condition-travis' :
'./plugin-noop'
)
return
}
plugins[plugin] = function (pluginOptions, cb) {
var tasks = options[plugin].map(function (step) {
var tasks = options[plugin].map((step) => {
return exports.normalize(step, './plugin-noop').bind(null, pluginOptions)
})
+3 -4
View File
@@ -1,10 +1,9 @@
var SemanticReleaseError = require('@semantic-release/error')
const SemanticReleaseError = require('@semantic-release/error')
module.exports = function (config, cb) {
var plugins = config.plugins
var lastRelease = config.lastRelease
const { plugins, lastRelease } = config
plugins.analyzeCommits(config, function (err, type) {
plugins.analyzeCommits(config, (err, type) => {
if (err) return cb(err)
if (!type) {
+10 -6
View File
@@ -1,10 +1,9 @@
var SemanticReleaseError = require('@semantic-release/error')
const parseSlug = require('parse-github-repo-url')
module.exports = function (config) {
var pkg = config.pkg
var options = config.options
var env = config.env
var errors = []
const SemanticReleaseError = require('@semantic-release/error')
module.exports = function ({pkg, options, env}) {
let errors = []
if (!pkg.name) {
errors.push(new SemanticReleaseError(
@@ -18,6 +17,11 @@ module.exports = function (config) {
'No "repository" found in package.json.',
'ENOPKGREPO'
))
} else if (!parseSlug(pkg.repository.url)) {
errors.push(new SemanticReleaseError(
'The "repository" field in the package.json is malformed.',
'EMALFORMEDPKGREPO'
))
}
if (options.debug) return errors
+15 -18
View File
@@ -1,35 +1,32 @@
var url = require('url')
const url = require('url')
var gitHead = require('git-head')
var GitHubApi = require('github')
var parseSlug = require('@bahmutov/parse-github-repo-url')
const gitHead = require('git-head')
const GitHubApi = require('github')
const parseSlug = require('parse-github-repo-url')
module.exports = function (config, cb) {
var pkg = config.pkg
var options = config.options
var plugins = config.plugins
var ghConfig = options.githubUrl ? url.parse(options.githubUrl) : {}
const { pkg, options, plugins } = config
const ghConfig = options.githubUrl ? url.parse(options.githubUrl) : {}
var github = new GitHubApi({
const github = new GitHubApi({
version: '3.0.0',
port: ghConfig.port,
protocol: (ghConfig.protocol || '').split(':')[0] || null,
host: ghConfig.hostname,
pathPrefix: options.githubApiPathPrefix || null
host: ghConfig.hostname
})
plugins.generateNotes(config, function (err, log) {
plugins.generateNotes(config, (err, log) => {
if (err) return cb(err)
gitHead(function (err, hash) {
gitHead((err, hash) => {
if (err) return cb(err)
var ghRepo = parseSlug(pkg.repository.url)
var release = {
const ghRepo = parseSlug(pkg.repository.url)
const 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
@@ -44,7 +41,7 @@ module.exports = function (config, cb) {
token: options.githubToken
})
github.releases.createRelease(release, function (err) {
github.releases.createRelease(release, (err) => {
if (err) return cb(err)
cb(null, true, release)
+15 -15
View File
@@ -1,43 +1,43 @@
var _ = require('lodash')
var auto = require('run-auto')
var semver = require('semver')
const _ = require('lodash')
const auto = require('run-auto')
const semver = require('semver')
var getCommits = require('./lib/commits')
var getType = require('./lib/type')
const getCommits = require('./lib/commits')
const getType = require('./lib/type')
module.exports = function (config, cb) {
var plugins = config.plugins
const { plugins } = config
auto({
lastRelease: plugins.getLastRelease.bind(null, config),
commits: ['lastRelease', function (results, cb) {
commits: ['lastRelease', (cb, results) => {
getCommits(_.assign({
lastRelease: results.lastRelease
}, config),
cb)
}],
type: ['commits', 'lastRelease', function (results, cb) {
type: ['commits', 'lastRelease', (cb, results) => {
getType(_.assign({
commits: results.commits,
lastRelease: results.lastRelease
}, config),
cb)
}]
}, function (err, results) {
}, (err, results) => {
if (err) return cb(err)
var nextRelease = {
const nextRelease = {
type: results.type,
version: results.type === 'initial'
? '1.0.0'
: semver.inc(results.lastRelease.version, results.type)
version: results.type === 'initial' ?
'1.0.0' :
semver.inc(results.lastRelease.version, results.type)
}
plugins.verifyRelease(_.assign({
commits: results.commits,
lastRelease: results.lastRelease,
nextRelease: nextRelease
}, config), function (err) {
nextRelease
}, config), (err) => {
if (err) return cb(err)
cb(null, nextRelease)
})
+3 -1
View File
@@ -1,4 +1,4 @@
var nixt = require('nixt')
const nixt = require('nixt')
module.exports = function (cwd, uri) {
return nixt()
@@ -7,6 +7,8 @@ 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()
}
+26 -17
View File
@@ -1,31 +1,40 @@
var exec = require('child_process').exec
var join = require('path').join
var writeFileSync = require('fs').writeFileSync
const { exec } = require('child_process')
const { join } = require('path')
const { writeFileSync } = require('fs')
var mkdirp = require('mkdirp')
const mkdirp = require('mkdirp')
module.exports = function (name, registry, cb) {
var cwd = join(__dirname, '../tmp', name)
module.exports = function (name, cb) {
const 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'
},
release: {
verifyConditions: '../../../src/lib/plugin-noop'
}
_npmUser: {
name: 'integration',
email: 'integration@test.com'
},
maintainers: [{
name: 'integration',
email: 'integration@test.com'
}]
}, 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: cwd}, function (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}, (err, stdout, stderr) => {
if (err) {
console.log(stdout, stderr)
return cb(err)
+5 -9
View File
@@ -4,20 +4,16 @@ const rawCommits = [
]
module.exports = {
exec: function (command, options, cb) {
if (typeof cb === 'undefined' && typeof options === 'function') {
cb = options
}
exec: (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(
null,
/\.\.HEAD/.test(command)
? rawCommits[0]
: rawCommits.join()
/\.\.HEAD/.test(command) ?
rawCommits[0] :
rawCommits.join()
)
},
'@noCallThru': true
+5 -11
View File
@@ -1,12 +1,6 @@
module.exports = function () {
return {
authenticate: function () {
return true
},
releases: {
createRelease: function (release, cb) {
cb(null)
}
}
module.exports = () => ({
authenticate: () => true,
releases: {
createRelease: (release, cb) => cb(null)
}
}
})
+5 -4
View File
@@ -1,11 +1,12 @@
var exec = require('child_process').exec
const { exec } = require('child_process')
const { join } = require('path')
var opts = {
cwd: __dirname
const opts = {
cwd: join(__dirname, '../../test/registry')
}
module.exports = {
start: exec.bind(null, './start.sh', opts),
stop: exec.bind(null, './stop.sh', opts),
uri: 'http://localhost:' + (process.env.TRAVIS === 'true' ? 5984 : 15986) + '/registry/_design/app/_rewrite/'
uri: 'http://localhost:15986/registry/_design/app/_rewrite/'
}
+9 -13
View File
@@ -7,29 +7,25 @@ cd $(dirname $0)
mkdir -p couch
# start couchdb as a background process, load local config, specify writable logfiles
if [[ $TRAVIS = true ]]
then
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"'
echo 'starting couch with sudo'
sudo couchdb -b -a local.ini -p couch/pid -o couch/stdout.log -e couch/stderr.log
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
-1
View File
@@ -8,6 +8,5 @@ cd $(dirname $0)
cat couch/{couch,stdout,stderr}.log
cat couch/pid | xargs kill
rm -rf couch
rm -rf data
+24 -22
View File
@@ -1,27 +1,30 @@
var join = require('path').join
const { join } = require('path')
var tap = require('tap')
var rimraf = require('rimraf')
const { test, tearDown } = require('tap')
const rimraf = require('rimraf')
var registry = require('../registry')
var testModule = require('../lib/test-module')
var baseScenario = require('../lib/base-scenario')
const registry = require('../registry')
const testModule = require('../lib/test-module')
const baseScenario = require('../lib/base-scenario')
var tearDown = tap.tearDown
var test = tap.test
test('change version', {bail: process.env.TRAVIS === 'true'}, function (t) {
test('change version', (t) => {
t.plan(7)
registry.start(function (err, stdout, stderr) {
registry.start((err) => {
t.error(err, 'registry started')
if (err) return t.end()
if (err) {
t.end()
t.bailout('registry not started')
}
testModule('change-version', registry.uri, function (err, cwd) {
testModule('change-version', (err, cwd) => {
t.error(err, 'test-module created')
if (err) return t.end()
if (err) {
t.end()
t.bailout('test-module not created')
}
t.test('no version', function (tt) {
t.test('no version', (tt) => {
tt.plan(1)
baseScenario(cwd, registry.uri)
@@ -32,7 +35,7 @@ test('change version', {bail: process.env.TRAVIS === 'true'}, function (t) {
.end(tt.error)
})
t.test('initial version', function (tt) {
t.test('initial version', (tt) => {
tt.plan(1)
baseScenario(cwd, registry.uri)
@@ -44,7 +47,7 @@ test('change version', {bail: process.env.TRAVIS === 'true'}, function (t) {
.end(tt.error)
})
t.test('patch version', function (tt) {
t.test('patch version', (tt) => {
tt.plan(1)
baseScenario(cwd, registry.uri)
@@ -56,7 +59,7 @@ test('change version', {bail: process.env.TRAVIS === 'true'}, function (t) {
.end(tt.error)
})
t.test('feature version', function (tt) {
t.test('feature version', (tt) => {
tt.plan(1)
baseScenario(cwd, registry.uri)
@@ -68,7 +71,7 @@ test('change version', {bail: process.env.TRAVIS === 'true'}, function (t) {
.end(tt.error)
})
t.test('breaking version', function (tt) {
t.test('breaking version', (tt) => {
tt.plan(1)
baseScenario(cwd, registry.uri)
@@ -83,11 +86,10 @@ test('change version', {bail: process.env.TRAVIS === 'true'}, function (t) {
})
})
tearDown(function () {
if (process.env.TRAVIS === 'true') return
tearDown(() => {
function cb (err, stdout, stderr) {
if (err) console.log(err)
if (stdout) console.log(stdout)
if (stderr) console.log(stderr)
}
+10 -13
View File
@@ -1,16 +1,13 @@
var test = require('tap').test
var proxyquire = require('proxyquire')
const test = require('tap').test
const proxyquire = require('proxyquire')
var commits = proxyquire('../../src/lib/commits', {
'npmlog': {
error: function () {}
},
const commits = proxyquire('../../dist/lib/commits', {
'child_process': require('../mocks/child-process')
})
test('commits since last release', function (t) {
t.test('get all commits', function (tt) {
commits({lastRelease: {}, options: {branch: 'master'}}, function (err, commits) {
test('commits since last release', (t) => {
t.test('get all commits', (tt) => {
commits({lastRelease: {}, options: {branch: 'master'}}, (err, commits) => {
tt.error(err)
tt.is(commits.length, 2, 'all commits')
tt.is(commits[0].hash, 'hash-one', 'parsed hash')
@@ -20,8 +17,8 @@ test('commits since last release', function (t) {
})
})
t.test('get commits since hash', function (tt) {
commits({lastRelease: {gitHead: 'hash'}, options: {branch: 'master'}}, function (err, commits) {
t.test('get commits since hash', (tt) => {
commits({lastRelease: {gitHead: 'hash'}, options: {branch: 'master'}}, (err, commits) => {
tt.error(err)
tt.is(commits.length, 1, 'specified commits')
tt.is(commits[0].hash, 'hash-one', 'parsed hash')
@@ -31,8 +28,8 @@ test('commits since last release', function (t) {
})
})
t.test('get commits since hash', function (tt) {
commits({lastRelease: {gitHead: 'notinhistory'}, options: {branch: 'notmaster'}}, function (err, commits) {
t.test('get commits since hash', (tt) => {
commits({lastRelease: {gitHead: 'notinhistory'}, options: {branch: 'notmaster'}}, (err, commits) => {
tt.ok(err)
tt.is(err.code, 'ENOTINHISTORY')
tt.end()
+7 -21
View File
@@ -1,8 +1,8 @@
const test = require('tap').test
const getRegistry = require('../../src/lib/get-registry')
const getRegistry = require('../../dist/lib/get-registry')
test('get correct registry', function (t) {
test('get correct registry', (t) => {
t.is(getRegistry({
name: 'publish-config',
publishConfig: {
@@ -10,34 +10,20 @@ test('get correct registry', function (t) {
}},
{}), 'a')
t.is(getRegistry({name: 'normal'}, {
get: function () {
return 'b'
}
}), 'b')
t.is(getRegistry({name: 'normal'}, {get: () => 'b'}), 'b')
t.is(getRegistry({name: 'normal'}, {
get: function () {
return null
}
}), 'https://registry.npmjs.org/')
t.is(getRegistry({name: 'normal'}, {get: () => null}), 'https://registry.npmjs.org/')
t.is(getRegistry({name: '@scoped/foo'}, {
get: function (input) {
return input === '@scoped/registry' ? 'c' : 'd'
}
get: (input) => input === '@scoped/registry' ? 'c' : 'd'
}), 'c')
t.is(getRegistry({name: '@scoped/bar'}, {
get: function () {
return 'e'
}
get: () => 'e'
}), 'e')
t.is(getRegistry({name: '@scoped/baz'}, {
get: function () {
return null
}
get: () => null
}), 'https://registry.npmjs.org/')
t.end()
+33 -34
View File
@@ -1,11 +1,11 @@
var test = require('tap').test
const test = require('tap').test
var plugins = require('../../src/lib/plugins')
const plugins = require('../../dist/lib/plugins')
test('export plugins', function (t) {
test('export plugins', (t) => {
t.plan(5)
var defaultPlugins = plugins({})
const defaultPlugins = plugins({})
t.is(typeof defaultPlugins.analyzeCommits, 'function')
t.is(typeof defaultPlugins.generateNotes, 'function')
@@ -14,51 +14,51 @@ test('export plugins', function (t) {
t.is(typeof defaultPlugins.getLastRelease, 'function')
})
test('plugin pipelines', function (t) {
test('plugin pipelines', (t) => {
t.plan(3)
t.test('get all results', function (tt) {
var pipelinePlugins = plugins({
t.test('get all results', (tt) => {
const pipelinePlugins = plugins({
verifyRelease: [
'./src/lib/plugin-noop',
'./test/mocks/plugin-result-a',
'./test/mocks/plugin-result-b'
'./dist/lib/plugin-noop',
'./.test/mocks/plugin-result-a',
'./.test/mocks/plugin-result-b'
]
})
pipelinePlugins.verifyRelease({}, function (err, results) {
pipelinePlugins.verifyRelease({}, (err, results) => {
tt.error(err)
tt.same(results, [undefined, 'a', 'b'])
tt.end()
})
})
t.test('get first error', function (tt) {
var pipelinePlugins = plugins({
t.test('get first error', (tt) => {
const pipelinePlugins = plugins({
verifyConditions: [
'./src/lib/plugin-noop',
'./test/mocks/plugin-error-a',
'./test/mocks/plugin-error-b'
'./dist/lib/plugin-noop',
'./.test/mocks/plugin-error-a',
'./.test/mocks/plugin-error-b'
]
})
pipelinePlugins.verifyConditions({}, function (err) {
pipelinePlugins.verifyConditions({}, (err) => {
tt.is(err.message, 'a')
tt.end()
})
})
t.test('get error and only results before', function (tt) {
var pipelinePlugins = plugins({
t.test('get error and only results before', (tt) => {
const pipelinePlugins = plugins({
verifyRelease: [
'./src/lib/plugin-noop',
'./test/mocks/plugin-result-a',
'./test/mocks/plugin-error-b',
'./test/mocks/plugin-result-b'
'./dist/lib/plugin-noop',
'./.test/mocks/plugin-result-a',
'./.test/mocks/plugin-error-b',
'./.test/mocks/plugin-result-b'
]
})
pipelinePlugins.verifyRelease({}, function (err, results) {
pipelinePlugins.verifyRelease({}, (err, results) => {
tt.is(err.message, 'b')
tt.same(results, [undefined, 'a', undefined])
tt.end()
@@ -66,18 +66,19 @@ test('plugin pipelines', function (t) {
})
})
test('normalize and load plugin', function (t) {
t.test('load from string', function (tt) {
var plugin = plugins.normalize('./src/lib/plugin-noop')
test('normalize and load plugin', (t) => {
t.test('load from string', (tt) => {
const plugin = plugins.normalize('./dist/lib/plugin-noop')
tt.is(typeof plugin, 'function')
tt.end()
})
t.test('load from object', function (tt) {
var plugin = plugins.normalize({
path: './src/lib/plugin-noop'
t.test('load from object', (tt) => {
const plugin = plugins.normalize({
path: './dist/lib/plugin-noop'
})
tt.is(typeof plugin, 'function')
@@ -85,13 +86,11 @@ test('normalize and load plugin', function (t) {
tt.end()
})
t.test('load from fallback', function (tt) {
var plugin = plugins.normalize(null, '../../src/lib/plugin-noop')
t.test('load from object', (tt) => {
const plugin = plugins.normalize(null, '../../dist/lib/plugin-noop')
tt.is(typeof plugin, 'function')
tt.end()
})
t.end()
})
+20 -26
View File
@@ -1,24 +1,20 @@
var defaults = require('lodash').defaults
var test = require('tap').test
var proxyquire = require('proxyquire')
const { defaults } = require('lodash')
const test = require('tap').test
const proxyquire = require('proxyquire')
var post = proxyquire('../../src/post', {
const post = proxyquire('../../dist/post', {
'git-head': require('../mocks/git-head'),
github: require('../mocks/github')
})
var pkg = {
const pkg = {
version: '1.0.0',
repository: {url: 'http://github.com/whats/up.git'}
}
var plugins = {
generateNotes: function (pkg, cb) {
cb(null, 'the log')
}
}
const plugins = {generateNotes: (pkg, cb) => cb(null, 'the log')}
var defaultRelease = {
const defaultRelease = {
owner: 'whats',
repo: 'up',
name: 'v1.0.0',
@@ -27,13 +23,13 @@ var defaultRelease = {
body: 'the log'
}
test('full post run', function (t) {
t.test('in debug mode w/o token', function (tt) {
test('full post run', (t) => {
t.test('in debug mode w/o token', (tt) => {
post({
options: {debug: true},
pkg: pkg,
plugins: plugins
}, function (err, published, release) {
pkg,
plugins
}, (err, published, release) => {
tt.error(err)
tt.is(published, false)
tt.match(release, defaults({draft: true}, defaultRelease))
@@ -42,12 +38,12 @@ test('full post run', function (t) {
})
})
t.test('in debug mode w/token', function (tt) {
t.test('in debug mode w/token', (tt) => {
post({
options: {debug: true, githubToken: 'yo'},
pkg: pkg,
plugins: plugins
}, function (err, published, release) {
pkg,
plugins
}, (err, published, release) => {
tt.error(err)
tt.is(published, true)
tt.match(release, defaults({draft: true}, defaultRelease))
@@ -56,12 +52,12 @@ test('full post run', function (t) {
})
})
t.test('production', function (tt) {
t.test('production', (tt) => {
post({
options: {githubToken: 'yo'},
pkg: pkg,
plugins: plugins
}, function (err, published, release) {
pkg,
plugins
}, (err, published, release) => {
tt.error(err)
tt.is(published, true)
tt.match(release, defaultRelease)
@@ -69,6 +65,4 @@ test('full post run', function (t) {
tt.end()
})
})
t.end()
})
+20 -24
View File
@@ -1,59 +1,55 @@
var test = require('tap').test
var proxyquire = require('proxyquire')
const test = require('tap').test
const proxyquire = require('proxyquire')
require('../mocks/registry')
var pre = proxyquire('../../src/pre', {
'./lib/commits': proxyquire('../../src/lib/commits', {
const pre = proxyquire('../../dist/pre', {
'./lib/commits': proxyquire('../../dist/lib/commits', {
'child_process': require('../mocks/child-process')
})
})
var versions = {
const versions = {
available: '1.0.0'
}
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 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 npm = {
const npm = {
registry: 'http://registry.npmjs.org/',
tag: 'latest'
}
test('full pre run', function (t) {
t.test('increase version', function (tt) {
test('full pre run', (t) => {
t.test('increase version', (tt) => {
tt.plan(3)
pre({
options: {branch: 'master'},
npm: npm,
npm,
pkg: {name: 'available'},
plugins: plugins
}, function (err, release) {
plugins
}, (err, release) => {
tt.error(err)
tt.is(release.type, 'major')
tt.is(release.version, '2.0.0')
})
})
t.test('increase version', function (tt) {
t.test('increase version', (tt) => {
tt.plan(3)
pre({
options: {branch: 'master'},
npm: npm,
npm,
pkg: {name: 'unavailable'},
plugins: plugins
}, function (err, release) {
plugins
}, (err, release) => {
tt.error(err)
tt.is(release.type, 'initial')
tt.is(release.version, '1.0.0')
+12 -24
View File
@@ -1,9 +1,9 @@
var test = require('tap').test
const test = require('tap').test
var type = require('../../src/lib/type')
const type = require('../../dist/lib/type')
test('get type from commits', function (t) {
t.test('get type from plugin', function (tt) {
test('get type from commits', (t) => {
t.test('get type from plugin', (tt) => {
tt.plan(2)
type({
@@ -12,45 +12,33 @@ test('get type from commits', function (t) {
message: 'a'
}],
lastRelease: {version: '1.0.0'},
plugins: {
analyzeCommits: function (config, cb) {
cb(null, 'major')
}
}
}, function (err, type) {
plugins: {analyzeCommits: (config, cb) => cb(null, 'major')}
}, (err, type) => {
tt.error(err)
tt.is(type, 'major')
})
})
t.test('error when no changes', function (tt) {
t.test('error when no changes', (tt) => {
tt.plan(1)
type({
commits: [],
lastRelease: {},
plugins: {
analyzeCommits: function (config, cb) {
cb(null, null)
}
}
}, function (err) {
plugins: {analyzeCommits: (config, cb) => cb(null, null)}
}, (err) => {
tt.is(err.code, 'ENOCHANGE')
})
})
t.test('initial version', function (tt) {
t.test('initial version', (tt) => {
tt.plan(2)
type({
commits: [],
lastRelease: {},
plugins: {
analyzeCommits: function (config, cb) {
cb(null, 'major')
}
}
}, function (err, type) {
plugins: {analyzeCommits: (config, cb) => cb(null, 'major')}
}, (err, type) => {
tt.error(err)
tt.is(type, 'initial')
})
+14 -19
View File
@@ -1,10 +1,10 @@
var test = require('tap').test
const test = require('tap').test
var verify = require('../../src/lib/verify')
const verify = require('../../dist/lib/verify')
test('verify pkg, options and env', function (t) {
t.test('dry run verification', function (tt) {
var noErrors = verify({
test('verify pkg, options and env', (t) => {
t.test('dry run verification', (tt) => {
const noErrors = verify({
options: {debug: true},
pkg: {
name: 'package',
@@ -16,7 +16,7 @@ test('verify pkg, options and env', function (t) {
tt.is(noErrors.length, 0)
var errors = verify({
const errors = verify({
options: {debug: true},
pkg: {}
})
@@ -25,27 +25,24 @@ test('verify pkg, options and env', function (t) {
tt.is(errors[0].code, 'ENOPKGNAME')
tt.is(errors[1].code, 'ENOPKGREPO')
tt.end()
})
t.test('dry run verification for gitlab repo', function (tt) {
var noErrors = verify({
const errors2 = verify({
options: {debug: true},
pkg: {
name: 'package',
repository: {
url: 'http://gitlab.corp.com/whats/up.git'
url: 'lol'
}
}
})
console.log(noErrors)
tt.is(noErrors.length, 0)
tt.is(errors2.length, 1)
tt.is(errors2[0].code, 'EMALFORMEDPKGREPO')
tt.end()
})
t.test('publish verification', function (tt) {
var noErrors = verify({
t.test('publish verification', (tt) => {
const noErrors = verify({
env: {NPM_TOKEN: 'yo'},
options: {githubToken: 'sup'},
pkg: {
@@ -58,7 +55,7 @@ test('verify pkg, options and env', function (t) {
tt.is(noErrors.length, 0)
var errors = verify({env: {}, options: {}, pkg: {}})
const errors = verify({env: {}, options: {}, pkg: {}})
tt.is(errors.length, 4)
tt.is(errors[0].code, 'ENOPKGNAME')
@@ -68,6 +65,4 @@ test('verify pkg, options and env', function (t) {
tt.end()
})
t.end()
})