Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2690d30aa0 | ||
|
|
a27998f92a | ||
|
|
e54844ad03 | ||
|
|
995fc07617 | ||
|
|
630bf63034 | ||
|
|
889f5f4360 | ||
|
|
191ae78a9f | ||
|
|
384bc63e5d | ||
|
|
e005662c56 | ||
|
|
1ddb090fec | ||
|
|
3440d2284c | ||
|
|
4e90e4b98b | ||
|
|
649af78c56 | ||
|
|
bd715dfdf4 | ||
|
|
f0bb39a22e | ||
|
|
5a8c8639af | ||
|
|
825c0e66dd | ||
|
|
40b48e375d | ||
|
|
1f3c5e885e | ||
|
|
1db531b511 | ||
|
|
db39c796a6 | ||
|
|
1591608f83 | ||
|
|
3250b9a1af | ||
|
|
96757ac645 | ||
|
|
25828960bc | ||
|
|
8244fe9f7d | ||
|
|
d0032de737 | ||
|
|
6c6562249b | ||
|
|
25cb545ea3 | ||
|
|
0930a6e33d | ||
|
|
890255692f | ||
|
|
fd4c4d1c81 | ||
|
|
7ba1cb956f | ||
|
|
1f70215ffe | ||
|
|
245f918201 | ||
|
|
f0f53f207b | ||
|
|
41c90124f6 | ||
|
|
44db677c4a | ||
|
|
127cb673bd | ||
|
|
a5dabed534 | ||
|
|
be9bb40dd2 | ||
|
|
4821aff69e | ||
|
|
773ecf693f | ||
|
|
f2dd66f614 | ||
|
|
3b921a63c5 | ||
|
|
785e7f7b3b | ||
|
|
b38f1e0687 |
@@ -1,3 +1,10 @@
|
||||
# common
|
||||
coverage
|
||||
node_modules
|
||||
*.log
|
||||
.nyc_output
|
||||
.tests
|
||||
.tmp
|
||||
|
||||
# build-artifacts
|
||||
dist
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
# common
|
||||
coverage
|
||||
node_modules
|
||||
*.log
|
||||
.nyc_output
|
||||
.tests
|
||||
.tmp
|
||||
|
||||
# source/config
|
||||
src
|
||||
*.yml
|
||||
.gitignore
|
||||
+7
-5
@@ -1,14 +1,15 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- iojs-v1
|
||||
- '0.10'
|
||||
- '0.12'
|
||||
sudo: false
|
||||
language: node_js
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
notifications:
|
||||
email: false
|
||||
node_js:
|
||||
- iojs-v2
|
||||
- iojs-v1
|
||||
- '0.12'
|
||||
- '0.10'
|
||||
before_install:
|
||||
- npm i -g npm@^2.0.0
|
||||
before_script:
|
||||
@@ -17,6 +18,7 @@ before_script:
|
||||
after_success:
|
||||
- python travis_after_all.py
|
||||
- export $(cat .to_export_back)
|
||||
- if [[ $BUILD_LEADER = YES ]]; then npm run coveralls; fi
|
||||
after_failure:
|
||||
- python travis_after_all.py
|
||||
- export $(cat .to_export_back)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# semantic-release
|
||||
[](https://travis-ci.org/boennemann/semantic-release)
|
||||
[](https://coveralls.io/r/boennemann/semantic-release)
|
||||
[](https://david-dm.org/boennemann/semantic-release)
|
||||
[](https://david-dm.org/boennemann/semantic-release#info=devDependencies)
|
||||
|
||||
@@ -7,17 +8,19 @@
|
||||
|
||||
## What is `semantic-release` about?
|
||||
|
||||
It fully automates your package's releases. It will determine not only which version to release, but also when – all without you wasting [cognitive resources](https://www.youtube.com/watch?v=FKTxC9pl-WM) on it.
|
||||
At its core `semantic-release` is a set of conventions that gives you entirely automated, semver-compliant package publishing. Luckily these conventions make sense on their own, like having meaningful commit messages.
|
||||
|
||||
[](https://www.youtube.com/watch?v=tc2UgG5L7WM&index=6&list=PLFZ5NyC0xHDaaTy6tY9p0C0jd_rRRl5Zm)
|
||||
|
||||
> This talk gives you a complete introduction to the underlying concepts plus a live demo at the end.
|
||||
|
||||
It is fully integrated into the `npm` lifecycle, so all you need to do is to configure your CI to regularly `npm publish` (i.e. for every commit).
|
||||
|
||||
Removing human descisions and emotions from version numbers and releases – strictly following the [SemVer](http://semver.org/) spec suddenly isn't a problem anymore.
|
||||
|
||||

|
||||
It removes human decisions and emotions from version numbers and releases – suddenly, strictly following the [SemVer](http://semver.org/) spec isn't a problem anymore.
|
||||
|
||||
## How does it work?
|
||||
|
||||
Meaningful conventions. Instead of dumping [lols](http://whatthecommit.com/) into our commit messages, we can take some time to think about what we changed in the codebase and write it down. Following formalized conventions it this then possible to not only generate a helpful changelog, but to determine whether a new version should be released.
|
||||
Instead of dumping [lols](http://whatthecommit.com/) into our commit messages, we can take some time to think about what we changed in the codebase and write it down. Following formalized conventions it this then possible to not only generate a helpful changelog, but to determine whether a new version should be released.
|
||||
|
||||
This module ships with the [AngularJS Commit Message Conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit), but you can [define your own](https://github.com/boennemann/semantic-release/wiki/commit-analysis).
|
||||
|
||||
@@ -40,11 +43,11 @@ After `npm` published the new version the `postpublish` step does this:
|
||||
- Generate release notes
|
||||
- Create a new [GitHub Release](https://help.github.com/articles/about-releases/) (including a git tag) with the release notes
|
||||
|
||||
Note: The default release notes are a [changelog](https://github.com/ajoslin/conventional-changelog) that is generated from git metadata, using the AngularJS commit conventions. You can [specify your own release note generator](https://github.com/boennemann/semantic-release/wiki/release-note-generation).
|
||||
Note: The default release notes are a [changelog](https://github.com/ajoslin/conventional-changelog) that is generated from git metadata, using the AngularJS commit conventions. You can [specify your own release note generator](https://github.com/boennemann/semantic-release/wiki/release-note-generation).
|
||||
|
||||
Note: This is tied to GitHub, feel free to send PRs for other services.
|
||||
|
||||
Note: `semantic-release` works around a limitation in `npm`'s `prepublish` step. Once a version is published it prints an error that you can *safely ignore* [npm/npm#7118](https://github.com/npm/npm/issues/7118).
|
||||
Note: `semantic-release` works around a limitation in `npm`'s `prepublish` step. Once a version is published it prints a "Could not pack" error that you can *safely ignore* [npm/npm#7118](https://github.com/npm/npm/issues/7118).
|
||||
|
||||
## How you can set it up
|
||||
|
||||
@@ -85,28 +88,34 @@ It would be preferable not to have a version field in the `package.json` at all,
|
||||
|
||||
#### Repository
|
||||
|
||||
If you haven't defined your GitHub repository in the `package.json`s [repository field](https://docs.npmjs.com/files/package.json#repository) the remote `origin`'s repository is used.
|
||||
If you haven't defined your GitHub repository in the `package.json`s [repository field](https://docs.npmjs.com/files/package.json#repository) the remote `origin`'s repository is used.
|
||||
|
||||
### CI Server
|
||||
|
||||
Inside your `.travis.yml`:
|
||||
|
||||
```yml
|
||||
```yml
|
||||
language: node_js
|
||||
node_js:
|
||||
- iojs-v1
|
||||
# If you have a more sophisticated build with multiple jobs you should have a look at
|
||||
# https://github.com/dmakhno/travis_after_all which is also configured for this
|
||||
# package. (Check the .travis.yml)
|
||||
sudo: false
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
notifications:
|
||||
email: false
|
||||
# See https://github.com/boennemann/semantic-release/issues/18
|
||||
before_deploy:
|
||||
- npm config set spin false --global
|
||||
env:
|
||||
# Get your token here: https://github.com/settings/tokens/new
|
||||
# Grant the token repo/public_repo scope (all others can be deselected)
|
||||
# You should encrypt this:
|
||||
# `travis encrypt GH_TOKEN=<token> --add`
|
||||
global: GH_TOKEN=<github-access-token-with-acceess-to-your-repo>
|
||||
global: GH_TOKEN=<github-access-token-with-access-to-your-repo>
|
||||
deploy:
|
||||
provider: npm
|
||||
email: <your-npm-mail@example.com>
|
||||
@@ -124,13 +133,11 @@ deploy:
|
||||
|
||||
Note: This isn't tied to a specific service, but example configuration is provided for [Travis CI](https://travis-ci.org/). Feel free to contribute configuration for other servers or services.
|
||||
|
||||
Note: You should [encrypt](http://docs.travis-ci.com/user/environment-variables/#sts=Secure Variables) your api keys and tokens.
|
||||
Note: You should [encrypt](http://docs.travis-ci.com/user/environment-variables/#sts=Secure Variables) your api keys and tokens. If this is a new repository, don't forget to [enable it on Travis](https://travis-ci.org/profile) to make encrypt work.
|
||||
|
||||
Note: Your CI environment has to export `CI=true` in order for `semantic-release` not to automatically perform a dry run. Travis CI does this by default.
|
||||
Note: Your CI environment has to export `CI=true` in order for `semantic-release` not to automatically perform a dry run. Travis CI does this by default.
|
||||
|
||||
Note: It is crucial that your CI server also fetches all tags when checking out your repository. Travis CI does this by default.
|
||||
|
||||
Note: If you have a more sophisticated build with multiple jobs you should have a look at [travis-after-all](https://github.com/dmakhno/travis_after_all), which is also configured for this [package](.travis.yml).
|
||||
Note: It is crucial that your CI server also fetches all tags when checking out your repository. Travis CI does this by default.
|
||||
|
||||
## ITYM*FAQ*LT
|
||||
> I think you might frequently ask questions like these
|
||||
@@ -168,9 +175,11 @@ 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? What if it breaks?
|
||||
|
||||
`semantic-release` has a full integration-test suite that tests _actual_ `npm` publishes and _actual_ GitHub Releases (with private registry/API) on node.js `^0.10`, `^0.12` and io.js `^1`. A new version won't get published if it doesn't pass on all these engines.
|
||||
`semantic-release` has a full integration-test suite that tests _actual_ `npm` publishes and _actual_ GitHub Releases (with private registry/API) 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.
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
MIT License
|
||||
2015 © Stephan Bönnemann and [contributors](https://github.com/boennemann/semantic-release/graphs/contributors)
|
||||
|
||||

|
||||
|
||||
+17
-60
@@ -1,13 +1,9 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict'
|
||||
|
||||
var readFile = require('fs').readFileSync
|
||||
|
||||
var abbrev = require('abbrev')
|
||||
var minimist = require('minimist')
|
||||
|
||||
var efh = require('../lib/error').standard
|
||||
|
||||
var argv = minimist(process.argv.slice(2), {
|
||||
alias: {
|
||||
d: 'debug',
|
||||
@@ -23,65 +19,26 @@ var argv = minimist(process.argv.slice(2), {
|
||||
}
|
||||
})
|
||||
|
||||
var plugins = JSON.parse(readFile('./package.json')).release || {}
|
||||
|
||||
var npmArgv = process.env.npm_config_argv ?
|
||||
minimist(JSON.parse(process.env.npm_config_argv).cooked) :
|
||||
{_: []}
|
||||
|
||||
var plugins = JSON.parse(readFile('./package.json')).release || {}
|
||||
|
||||
var main
|
||||
|
||||
/* istanbul ignore next */
|
||||
try {
|
||||
main = require('../dist/main')
|
||||
} catch (e) {
|
||||
require('babel/register')
|
||||
main = require('../src/main')
|
||||
}
|
||||
|
||||
if (~argv._.indexOf('pre')) {
|
||||
// see src/restart.js
|
||||
if (npmArgv['semantic-release-rerun']) process.exit(0)
|
||||
// the `prepublish` hook is also executed when the package is installed
|
||||
// in this case we abort the command and do nothing.
|
||||
if (
|
||||
isAbbrev(npmArgv, 'install') ||
|
||||
isAbbrev(npmArgv, 'link') ||
|
||||
isAbbrev(npmArgv, 'pack')
|
||||
) process.exit(0)
|
||||
|
||||
if (argv.debug) console.log('This is a dry run')
|
||||
|
||||
console.log('Determining new version')
|
||||
|
||||
var publish = false
|
||||
if (isAbbrev(npmArgv, 'publish')) publish = true
|
||||
|
||||
// require a correct setup during publish
|
||||
if (publish && !argv.debug && !require('../src/verify')(argv)) process.exit(1)
|
||||
|
||||
require('../src/pre')(argv, plugins, efh(function (result) {
|
||||
if (!result) {
|
||||
console.log('Nothing changed. Not publishing.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log('Publishing v' + result)
|
||||
if (!publish) process.exit(0)
|
||||
|
||||
if (argv.debug) process.exit(1)
|
||||
|
||||
require('../src/restart')(efh(function () {
|
||||
process.exit(1)
|
||||
}))
|
||||
}))
|
||||
}
|
||||
|
||||
if (~argv._.indexOf('post')) {
|
||||
require('../src/post')(argv, plugins, efh(function () {
|
||||
// see src/restart.js
|
||||
if (npmArgv['semantic-release-rerun']) {
|
||||
console.log('Everything is alright :) npm will now print an error message that you can safely ignore.')
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
if (~argv._.indexOf('setup')) {
|
||||
require('../src/setup')()
|
||||
console.log('"package.json" is set up properly. Now configure your CI server.')
|
||||
console.log('https://github.com/boennemann/semantic-release#ci-server')
|
||||
}
|
||||
|
||||
function isAbbrev (argv, command) {
|
||||
return argv._.some(Object.prototype.hasOwnProperty.bind(abbrev(command)))
|
||||
main.pre(argv, npmArgv, plugins)
|
||||
} else if (~argv._.indexOf('post')) {
|
||||
main.post(argv, npmArgv, plugins)
|
||||
} else if (~argv._.indexOf('setup')) {
|
||||
main.setup(argv, npmArgv, plugins)
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
var parseRawCommit = require('conventional-changelog/lib/git').parseRawCommit
|
||||
|
||||
module.exports = function (commits) {
|
||||
var type = null
|
||||
|
||||
commits
|
||||
|
||||
.map(function (commit) {
|
||||
return parseRawCommit(commit.hash + '\n' + commit.message)
|
||||
})
|
||||
|
||||
.filter(function (commit) {
|
||||
return !!commit
|
||||
})
|
||||
|
||||
.every(function (commit) {
|
||||
if (commit.breaks.length) {
|
||||
type = 'major'
|
||||
return false
|
||||
}
|
||||
|
||||
if (commit.type === 'feat') type = 'minor'
|
||||
|
||||
if (!type && commit.type === 'fix') type = 'patch'
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
return type
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
var exec = require('child_process').exec
|
||||
|
||||
var efh = require('./error').efh
|
||||
|
||||
module.exports = function (from, cb) {
|
||||
var range = (from ? from + '..' : '') + 'HEAD'
|
||||
exec(
|
||||
'git log -E --format=%H==SPLIT==%s==END== ' + range,
|
||||
efh(cb)(function (stdout) {
|
||||
cb(null, String(stdout).split('==END==\n')
|
||||
|
||||
.filter(function (raw) {
|
||||
return !!raw.trim()
|
||||
})
|
||||
|
||||
.map(function (raw) {
|
||||
var data = raw.split('==SPLIT==')
|
||||
return {
|
||||
hash: data[0],
|
||||
message: data[1]
|
||||
}
|
||||
}))
|
||||
})
|
||||
)
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
var efh = require('error-first-handler')
|
||||
|
||||
module.exports = {
|
||||
efh: efh,
|
||||
standard: efh(function (err) {
|
||||
console.log('Something went wrong:')
|
||||
if (typeof err === 'string') return console.log(err)
|
||||
if (err instanceof Error) return console.log(err.message, err.stack)
|
||||
if (err.message) return console.log(err.message)
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
var request = require('request')
|
||||
|
||||
var efh = require('./error').efh
|
||||
|
||||
module.exports = function (pkgName, cb) {
|
||||
request(process.env.npm_config_registry + pkgName, efh(cb)(function (response, body) {
|
||||
var res = {
|
||||
version: null,
|
||||
gitHead: null,
|
||||
pkg: null
|
||||
}
|
||||
|
||||
if (response.statusCode === 404 || !body) return cb(null, res)
|
||||
|
||||
var pkg = JSON.parse(body)
|
||||
|
||||
if (pkg.error) return cb(pkg.error)
|
||||
|
||||
res.version = pkg['dist-tags'].latest
|
||||
res.gitHead = pkg.versions[res.version].gitHead
|
||||
res.pkg = pkg
|
||||
|
||||
cb(null, res)
|
||||
}))
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
var readFile = require('fs').readFileSync
|
||||
|
||||
var changelog = require('conventional-changelog')
|
||||
var parseUrl = require('github-url-from-git')
|
||||
|
||||
module.exports = function (cb) {
|
||||
var pkg = JSON.parse(readFile('./package.json'))
|
||||
var repository = pkg.repository ? parseUrl(pkg.repository.url) : null
|
||||
|
||||
changelog({
|
||||
version: pkg.version,
|
||||
repository: repository,
|
||||
file: false
|
||||
}, cb)
|
||||
}
|
||||
+33
-12
@@ -7,8 +7,17 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/boennemann/semantic-release/issues"
|
||||
},
|
||||
"config": {
|
||||
"nyc": {
|
||||
"exclude": [
|
||||
".tests",
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"abbrev": "^1.0.5",
|
||||
"async": "^1.0.0",
|
||||
"conventional-changelog": "0.0.17",
|
||||
"error-first-handler": "^1.0.1",
|
||||
"git-head": "^1.2.1",
|
||||
@@ -16,19 +25,23 @@
|
||||
"github-url-from-git": "^1.4.0",
|
||||
"ini": "^1.3.2",
|
||||
"minimist": "^1.1.0",
|
||||
"npmconf": "^2.1.2",
|
||||
"parse-github-repo-url": "^1.0.0",
|
||||
"request": "^2.53.0",
|
||||
"semver": "^4.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"coveralls": "^2.11.2",
|
||||
"cracks": "^2.0.1",
|
||||
"github-release-fake-server": "^1.3.0",
|
||||
"lodash.defaults": "^3.0.0",
|
||||
"nano-uid": "^0.2.0",
|
||||
"nixt": "^0.4.1",
|
||||
"nock": "^2.2.0",
|
||||
"nyc": "^2.3.0",
|
||||
"sinopia": "^1.0.0",
|
||||
"standard": "^3.2.1",
|
||||
"tap-spec": "^3.0.0",
|
||||
"tape": "^4.0.0"
|
||||
"standard": "^4.0.1",
|
||||
"tap": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"iojs": "^1",
|
||||
@@ -39,25 +52,33 @@
|
||||
"keywords": [
|
||||
"author",
|
||||
"automation",
|
||||
"release",
|
||||
"publish",
|
||||
"changelog",
|
||||
"module",
|
||||
"package",
|
||||
"publish",
|
||||
"release",
|
||||
"semver",
|
||||
"version",
|
||||
"changelog"
|
||||
"version"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"main": "dist/main.js",
|
||||
"optionalDependencies": {
|
||||
"babel": "^5.5.6"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/boennemann/semantic-release.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rm -rf dist && mkdir -p dist && babel src --out-dir dist",
|
||||
"build:tests": "rm -rf .tests && mkdir -p .tests && babel tests --out-dir .tests",
|
||||
"coverage": "nyc report",
|
||||
"coveralls": "npm run coverage -- --reporter=lcovonly && cat coverage/lcov.info | coveralls",
|
||||
"postpublish": "./bin/semantic-release.js post",
|
||||
"prepublish": "./bin/semantic-release.js pre",
|
||||
"test:style": "standard",
|
||||
"test:integration": "node tests | tap-spec",
|
||||
"test": "./bin/test"
|
||||
"prepublish": "npm run build && ./bin/semantic-release.js pre",
|
||||
"pretest:integration": "npm run build && npm run build:tests",
|
||||
"test": "./bin/test",
|
||||
"test:integration": "nyc tap --no-cov .tests/{scenarios,tap}/*.js",
|
||||
"test:style": "standard"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
const { parseRawCommit } = require('conventional-changelog/lib/git')
|
||||
|
||||
module.exports = function (commits) {
|
||||
let type = null
|
||||
|
||||
commits
|
||||
|
||||
.map((commit) => parseRawCommit(`${commit.hash}\n${commit.message}`))
|
||||
|
||||
.filter((commit) => !!commit)
|
||||
|
||||
.every((commit) => {
|
||||
if (commit.breaks.length) {
|
||||
type = 'major'
|
||||
return false
|
||||
}
|
||||
|
||||
if (commit.type === 'feat') type = 'minor'
|
||||
|
||||
if (!type && commit.type === 'fix') type = 'patch'
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
return type
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
const { exec } = require('child_process')
|
||||
|
||||
const { efh } = require('./error')
|
||||
|
||||
module.exports = function (from, cb) {
|
||||
const range = (from ? from + '..' : '') + 'HEAD'
|
||||
exec(
|
||||
`git log -E --format=%H==SPLIT==%B==END== ${range}`,
|
||||
efh(cb)((stdout) => {
|
||||
cb(null, String(stdout).split('==END==\n')
|
||||
|
||||
.filter((raw) => !!raw.trim())
|
||||
|
||||
.map((raw) => {
|
||||
const data = raw.split('==SPLIT==')
|
||||
return {
|
||||
hash: data[0],
|
||||
message: data[1]
|
||||
}
|
||||
}))
|
||||
})
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
exports.efh = require('error-first-handler')
|
||||
exports.standard = exports.efh((err) => {
|
||||
console.log('Something went wrong:')
|
||||
if (typeof err === 'string') console.log(err)
|
||||
else if (err instanceof Error) console.log(err.message, err.stack)
|
||||
else if (err.message) console.log(err.message)
|
||||
else console.log(err)
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -0,0 +1,46 @@
|
||||
const async = require('async')
|
||||
const npmconf = require('npmconf')
|
||||
const request = require('request')
|
||||
|
||||
module.exports = function (pkgName, cb) {
|
||||
const registry = process.env.npm_config_registry
|
||||
|
||||
async.waterfall([
|
||||
npmconf.load,
|
||||
(conf, callback) => {
|
||||
const cred = conf.getCredentialsByURI(registry)
|
||||
const reqopts = {
|
||||
url: registry + pkgName.replace(/\//g, '%2F'),
|
||||
headers: {}
|
||||
}
|
||||
|
||||
if (cred.token) {
|
||||
reqopts.headers.Authorization = `Bearer ${cred.token}`
|
||||
} else if (cred.auth) {
|
||||
reqopts.headers.Authorization = `Basic ${cred.auth}`
|
||||
}
|
||||
|
||||
callback(null, reqopts)
|
||||
},
|
||||
request,
|
||||
(response, body, callback) => {
|
||||
let res = {
|
||||
version: null,
|
||||
gitHead: null,
|
||||
pkg: null
|
||||
}
|
||||
|
||||
if (response.statusCode === 404 || !body) return callback(null, res)
|
||||
|
||||
const pkg = JSON.parse(body)
|
||||
|
||||
if (pkg.error) return callback(pkg.error)
|
||||
|
||||
res.version = pkg['dist-tags'].latest
|
||||
res.gitHead = pkg.versions[res.version].gitHead
|
||||
res.pkg = pkg
|
||||
|
||||
callback(null, res)
|
||||
}
|
||||
], cb)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
const { readFileSync } = require('fs')
|
||||
|
||||
const changelog = require('conventional-changelog')
|
||||
const parseUrl = require('github-url-from-git')
|
||||
|
||||
module.exports = function (cb) {
|
||||
const pkg = JSON.parse(readFileSync('./package.json'))
|
||||
const repository = pkg.repository ? parseUrl(pkg.repository.url) : null
|
||||
|
||||
changelog({
|
||||
version: pkg.version,
|
||||
repository: repository,
|
||||
file: false
|
||||
}, cb)
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
const abbrev = require('abbrev')
|
||||
const efh = require('./lib/error').standard
|
||||
|
||||
exports.pre = function (argv, npmArgv, plugins) {
|
||||
// see src/restart.js
|
||||
if (npmArgv['semantic-release-rerun']) {
|
||||
if (!/semantically-released/.test(process.env.npm_package_version)) process.exit(0)
|
||||
|
||||
console.log(
|
||||
`There is something wrong with your setup, as a placeholder version is about to be released.
|
||||
Please verify that your setup is correct.
|
||||
If you think this is a problem with semantic-release please open an issue.`
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
// the `prepublish` hook is also executed when the package is installed
|
||||
// in this case we abort the command and do nothing.
|
||||
if (
|
||||
isAbbrev(npmArgv, 'install') ||
|
||||
isAbbrev(npmArgv, 'link') ||
|
||||
isAbbrev(npmArgv, 'pack')
|
||||
) process.exit(0)
|
||||
|
||||
if (argv.debug) console.log('This is a dry run')
|
||||
|
||||
console.log('Determining new version')
|
||||
|
||||
const publish = isAbbrev(npmArgv, 'publish')
|
||||
|
||||
// require a correct setup during publish
|
||||
if (publish && !argv.debug && !require('./verify')(argv)) process.exit(1)
|
||||
|
||||
require('./pre')(argv, plugins, efh((result) => {
|
||||
if (!result) {
|
||||
console.log('Nothing changed. Not publishing.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log('Publishing v' + result)
|
||||
if (!publish) process.exit(0)
|
||||
|
||||
if (argv.debug) process.exit(1)
|
||||
|
||||
require('./restart')(efh(() => process.exit(1)))
|
||||
}))
|
||||
}
|
||||
|
||||
exports.post = function (argv, npmArgv, plugins) {
|
||||
require('./post')(argv, plugins, efh(function () {
|
||||
// see src/restart.js
|
||||
if (npmArgv['semantic-release-rerun']) {
|
||||
console.log('Everything is alright :) npm will now print an error message that you can safely ignore.')
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
exports.setup = function () {
|
||||
require('./setup')()
|
||||
console.log('"package.json" is set up properly. Now configure your CI server.')
|
||||
console.log('https://github.com/boennemann/semantic-release#ci-server')
|
||||
}
|
||||
|
||||
function isAbbrev (argv, command) {
|
||||
return argv._.some(Object.prototype.hasOwnProperty.bind(abbrev(command)))
|
||||
}
|
||||
+17
-21
@@ -1,38 +1,36 @@
|
||||
'use strict'
|
||||
const { readFileSync } = require('fs')
|
||||
const url = require('url')
|
||||
|
||||
var readFile = require('fs').readFileSync
|
||||
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')
|
||||
|
||||
var efh = require('../lib/error').efh
|
||||
const efh = require('./lib/error').efh
|
||||
|
||||
module.exports = function (options, plugins, cb) {
|
||||
var pkg = JSON.parse(readFile('./package.json'))
|
||||
var repository = pkg.repository ? pkg.repository.url : null
|
||||
const pkg = JSON.parse(readFileSync('./package.json'))
|
||||
const repository = pkg.repository ? pkg.repository.url : null
|
||||
|
||||
if (!repository) return cb(new Error('Package must have a repository'))
|
||||
|
||||
var notesGenerator = require(plugins.notes || '../lib/release-notes')
|
||||
const notesGenerator = require(plugins.notes || './lib/release-notes')
|
||||
|
||||
var config = options['github-url'] ? url.parse(options['github-url']) : {}
|
||||
const config = options['github-url'] ? url.parse(options['github-url']) : {}
|
||||
|
||||
var github = new GitHubApi({
|
||||
const github = new GitHubApi({
|
||||
version: '3.0.0',
|
||||
port: config.port,
|
||||
protocol: (config.protocol || '').split(':')[0] || null,
|
||||
host: config.hostname
|
||||
})
|
||||
|
||||
notesGenerator(efh(cb)(function (log) {
|
||||
gitHead(efh(cb)(function (hash) {
|
||||
var ghRepo = parseSlug(repository)
|
||||
var release = {
|
||||
notesGenerator(efh(cb)((log) => {
|
||||
gitHead(efh(cb)((hash) => {
|
||||
const ghRepo = parseSlug(repository)
|
||||
const release = {
|
||||
owner: ghRepo[0],
|
||||
repo: ghRepo[1],
|
||||
tag_name: 'v' + pkg.version,
|
||||
tag_name: `v${pkg.version}`,
|
||||
target_commitish: hash,
|
||||
draft: options.debug,
|
||||
body: log
|
||||
@@ -43,9 +41,7 @@ module.exports = function (options, plugins, cb) {
|
||||
token: options.token
|
||||
})
|
||||
|
||||
github.releases.createRelease(release, efh(cb)(function () {
|
||||
cb(null, true)
|
||||
}))
|
||||
github.releases.createRelease(release, efh(cb)(() => cb(null, true)))
|
||||
}))
|
||||
}))
|
||||
}
|
||||
|
||||
+49
-16
@@ -1,29 +1,62 @@
|
||||
'use strict'
|
||||
const fs = require('fs')
|
||||
|
||||
var fs = require('fs')
|
||||
const semver = require('semver')
|
||||
|
||||
var semver = require('semver')
|
||||
|
||||
var getCommits = require('../lib/commits')
|
||||
var npmInfo = require('../lib/npm-info')
|
||||
var efh = require('../lib/error').efh
|
||||
const getCommits = require('./lib/commits')
|
||||
const npmInfo = require('./lib/npm-info')
|
||||
const { efh } = require('./lib/error')
|
||||
|
||||
module.exports = function (options, plugins, cb) {
|
||||
var path = './package.json'
|
||||
var pkg = JSON.parse(fs.readFileSync(path))
|
||||
const path = './package.json'
|
||||
let pkg = JSON.parse(fs.readFileSync(path))
|
||||
|
||||
if (!pkg.name) return cb(new Error('Package must have a name'))
|
||||
|
||||
npmInfo(pkg.name, efh(cb)(function (res) {
|
||||
getCommits(res.gitHead, efh(cb)(function (commits) {
|
||||
var analyzer = require(plugins.analyzer || '../lib/analyzer')
|
||||
var type = analyzer(commits)
|
||||
npmInfo(pkg.name, efh(cb)((res) => {
|
||||
getCommits(res.gitHead, efh(cb)((commits) => {
|
||||
const analyzer = require(plugins.analyzer || './lib/analyzer')
|
||||
let type = analyzer(commits)
|
||||
|
||||
if (!type) return cb(null, null)
|
||||
pkg.version = !res.version ? '1.0.0' : semver.inc(res.version, type)
|
||||
if (!options.debug) fs.writeFileSync(path, JSON.stringify(pkg, null, 2))
|
||||
|
||||
cb(null, pkg.version)
|
||||
if (res.version) {
|
||||
pkg.version = semver.inc(res.version, type)
|
||||
} else {
|
||||
type = 'major'
|
||||
pkg.version = '1.0.0'
|
||||
}
|
||||
|
||||
function writePkg () {
|
||||
if (!options.debug) fs.writeFileSync(path, `${JSON.stringify(pkg, null, 2)}\n`)
|
||||
cb(null, pkg.version)
|
||||
}
|
||||
|
||||
if (!plugins.verification) return writePkg()
|
||||
|
||||
let opts = {}
|
||||
|
||||
if (typeof plugins.verification === 'string') {
|
||||
opts.path = plugins.verification
|
||||
}
|
||||
if (typeof plugins.verification === 'object') {
|
||||
opts = plugins.verification
|
||||
opts.path = opts.path || opts.name
|
||||
}
|
||||
|
||||
opts.type = type
|
||||
opts.commits = commits
|
||||
opts.version = res.version
|
||||
opts.nextVersion = pkg.version
|
||||
|
||||
const verification = require(opts.path)
|
||||
|
||||
console.log('Running verification hook...')
|
||||
|
||||
verification(opts, (error, ok) => {
|
||||
if (!error && ok) return writePkg()
|
||||
console.log('Verification failed' + (error ? ': ' + error : ''))
|
||||
process.exit(1)
|
||||
})
|
||||
}))
|
||||
}))
|
||||
}
|
||||
|
||||
+6
-8
@@ -1,16 +1,14 @@
|
||||
'use strict'
|
||||
const { spawn } = require('child_process')
|
||||
|
||||
var spawn = require('child_process').spawn
|
||||
|
||||
var exports = module.exports = function (cb) {
|
||||
let exports = module.exports = function (cb) {
|
||||
// npm loads package.json data before running the `prepublish` hook
|
||||
// changing the version on `prepublish` has no effect
|
||||
// see https://github.com/npm/npm/issues/7118
|
||||
// to circumvent this behavior we are calling `npm publish` inside `prepublish`
|
||||
// the package.json is then loaded again and the correct version will be published
|
||||
|
||||
var child = spawn('npm', ['publish', '--semantic-release-rerun'])
|
||||
var handler = exports.handleCloseAndExit.bind(null, cb)
|
||||
const child = spawn('npm', ['publish', '--semantic-release-rerun'])
|
||||
const handler = exports.handleCloseAndExit.bind(null, cb)
|
||||
|
||||
child.stdout.pipe(process.stdout)
|
||||
child.stderr.pipe(process.stderr)
|
||||
@@ -23,8 +21,8 @@ var exports = module.exports = function (cb) {
|
||||
exports.handleCloseAndExit = function (cb, code, signal) {
|
||||
if (code === 0) return cb(null)
|
||||
cb({
|
||||
code: code,
|
||||
signal: signal,
|
||||
code,
|
||||
signal,
|
||||
message: 'npm publish failed'
|
||||
})
|
||||
}
|
||||
|
||||
+15
-14
@@ -1,32 +1,33 @@
|
||||
'use strict'
|
||||
const {
|
||||
readFileSync,
|
||||
writeFileSync
|
||||
} = require('fs')
|
||||
|
||||
var fs = require('fs')
|
||||
|
||||
var ini = require('ini')
|
||||
var ghUrl = require('github-url-from-git')
|
||||
const ini = require('ini')
|
||||
const ghUrl = require('github-url-from-git')
|
||||
|
||||
module.exports = function () {
|
||||
var pkg = JSON.parse(fs.readFileSync('./package.json') + '')
|
||||
let pkg = JSON.parse(String(readFileSync('./package.json')))
|
||||
|
||||
// ensure a yet unpublished version
|
||||
pkg.version = '0.0.0-semantically-released'
|
||||
|
||||
// set up scripts
|
||||
var pre = 'semantic-release pre'
|
||||
var post = 'semantic-release post'
|
||||
const pre = 'semantic-release pre'
|
||||
const post = 'semantic-release post'
|
||||
|
||||
if (!pkg.scripts) pkg.scripts = {}
|
||||
|
||||
if (!pkg.scripts.prepublish) pkg.scripts.prepublish = pre
|
||||
else if (!(new RegExp(pre).test(pkg.scripts.prepublish))) pkg.scripts.prepublish += ' && ' + pre
|
||||
else if (!(new RegExp(pre).test(pkg.scripts.prepublish))) pkg.scripts.prepublish += ` && ${pre}`
|
||||
|
||||
if (!pkg.scripts.postpublish) pkg.scripts.postpublish = post
|
||||
else if (!(new RegExp(post).test(pkg.scripts.postpublish))) pkg.scripts.postpublish += ' && ' + post
|
||||
else if (!(new RegExp(post).test(pkg.scripts.postpublish))) pkg.scripts.postpublish += ` && ${post}`
|
||||
|
||||
// set up repository
|
||||
if (!pkg.repository || !pkg.repository.url) {
|
||||
var config = ini.decode(fs.readFileSync('./.git/config') + '')
|
||||
var repo = config['remote "origin"'].url
|
||||
const config = ini.decode(String(readFileSync('./.git/config')))
|
||||
const repo = config['remote "origin"'].url
|
||||
|
||||
if (repo) pkg.repository = { type: 'git', url: ghUrl(repo) }
|
||||
}
|
||||
@@ -35,8 +36,8 @@ module.exports = function () {
|
||||
if (!pkg.devDependencies) pkg.devDependencies = {}
|
||||
|
||||
if (!pkg.devDependencies['semantic-release']) {
|
||||
pkg.devDependencies['semantic-release'] = '^' + require('../package.json').version
|
||||
pkg.devDependencies['semantic-release'] = `^${require('../package.json').version}`
|
||||
}
|
||||
|
||||
fs.writeFileSync('./package.json', JSON.stringify(pkg, null, 2))
|
||||
writeFileSync('./package.json', `${JSON.stringify(pkg, null, 2)}\n`)
|
||||
}
|
||||
|
||||
+11
-11
@@ -1,22 +1,21 @@
|
||||
'use strict'
|
||||
const { readFileSync } = require('fs')
|
||||
|
||||
var fs = require('fs')
|
||||
|
||||
var exports = module.exports = function (input) {
|
||||
var options = exports.verifyOptions(input)
|
||||
var pkg = exports.verifyPackage()
|
||||
var travis = exports.verifyTravis()
|
||||
let exports = module.exports = function (input) {
|
||||
const options = exports.verifyOptions(input)
|
||||
const pkg = exports.verifyPackage()
|
||||
const travis = exports.verifyTravis()
|
||||
return options && pkg && travis
|
||||
}
|
||||
|
||||
exports.verifyTravis = function () {
|
||||
let travis
|
||||
try {
|
||||
var travis = fs.readFileSync('.travis.yml') + ''
|
||||
travis = String(readFileSync('.travis.yml'))
|
||||
} catch (e) {
|
||||
return true
|
||||
}
|
||||
|
||||
var passed = true
|
||||
let passed = true
|
||||
|
||||
if (!/\sdeploy:/m.test(travis)) {
|
||||
console.error('You should configure deployments inside the ".travis.yml".')
|
||||
@@ -32,10 +31,11 @@ exports.verifyTravis = function () {
|
||||
}
|
||||
|
||||
exports.verifyPackage = function () {
|
||||
var passed = true
|
||||
let passed = true
|
||||
|
||||
let pkg
|
||||
try {
|
||||
var pkg = fs.readFileSync('./package.json') + ''
|
||||
pkg = String(readFileSync('./package.json'))
|
||||
} catch (e) {
|
||||
console.error('You must have a "package.json" present.')
|
||||
passed = false
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
_auth=dGVzdDpmb28=
|
||||
email=test@example.com
|
||||
registry=http://127.0.0.1:4873/
|
||||
//registry.npmjs.org/:_authToken=testtoken
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
var test = require('tape')
|
||||
|
||||
var createModule = require('./lib/create-module')
|
||||
|
||||
require('./scenarios/custom-analyzer')(test, createModule)
|
||||
require('./scenarios/ignore')(test, createModule)
|
||||
require('./scenarios/prepublish')(test, createModule)
|
||||
require('./scenarios/postpublish')(test, createModule)
|
||||
require('./scenarios/publish')(test, createModule)
|
||||
require('./scenarios/verify')(test, createModule)
|
||||
require('./scenarios/setup')(test, createModule)
|
||||
@@ -1,34 +1,32 @@
|
||||
'use strict'
|
||||
const fs = require('fs')
|
||||
const exec = require('child_process').exec
|
||||
|
||||
var fs = require('fs')
|
||||
var exec = require('child_process').exec
|
||||
|
||||
var nixt = require('nixt')
|
||||
const nixt = require('nixt')
|
||||
|
||||
module.exports = function (t, message, version, code, name, cwd) {
|
||||
t.test(name, function (t) {
|
||||
t.test(name, (t) => {
|
||||
t.plan(3)
|
||||
|
||||
nixt()
|
||||
.cwd(cwd)
|
||||
.env('CI', true)
|
||||
.env('npm_config_registry', 'http://127.0.0.1:4873/')
|
||||
.exec('git commit --allow-empty -m "' + message + '"')
|
||||
.exec(`git commit --allow-empty -m "${message}"`)
|
||||
.run('npm run prepublish')
|
||||
.code(code)
|
||||
.stdout(/> semantic-release pre\n\nDetermining new version\n/m)
|
||||
.end(function (err) {
|
||||
.stdout(/semantic-release.js pre\n\nDetermining new version\n/m)
|
||||
.end((err) => {
|
||||
t.error(err, 'nixt')
|
||||
|
||||
var pkg = JSON.parse(fs.readFileSync(cwd + '/package.json'))
|
||||
const pkg = JSON.parse(fs.readFileSync(`${cwd}/package.json`))
|
||||
t.is(pkg.version, version, 'version')
|
||||
|
||||
if (code === 1) {
|
||||
return t.error(null, 'no publish')
|
||||
}
|
||||
|
||||
exec('npm publish --ignore-scripts', {cwd: cwd}, function (err) {
|
||||
setTimeout(function () {
|
||||
exec('npm publish --ignore-scripts', {cwd}, (err) => {
|
||||
setTimeout(() => {
|
||||
t.error(err, 'publish')
|
||||
}, 300)
|
||||
})
|
||||
|
||||
+20
-26
@@ -1,24 +1,19 @@
|
||||
'use strict'
|
||||
const exec = require('child_process').exec
|
||||
const join = require('path').join
|
||||
|
||||
var exec = require('child_process').exec
|
||||
var join = require('path').join
|
||||
|
||||
var efh = require('error-first-handler')
|
||||
var defaults = require('lodash.defaults')
|
||||
var uid = require('nano-uid')()
|
||||
const efh = require('error-first-handler')
|
||||
const defaults = require('lodash.defaults')
|
||||
const uid = require('nano-uid')()
|
||||
|
||||
module.exports = function (input) {
|
||||
var cb = Array.prototype.pop.call(arguments)
|
||||
uid.generate(5, efh(cb)(function (id) {
|
||||
var pkg = defaults((typeof input === 'object' ? input : {}), {
|
||||
const cb = Array.prototype.pop.call(arguments)
|
||||
uid.generate(5, efh(cb)((id) => {
|
||||
const pkg = defaults((typeof input === 'object' ? input : {}), {
|
||||
name: id,
|
||||
version: '0.0.0',
|
||||
devDependencies: {
|
||||
'semantic-release': 'file:../../../'
|
||||
},
|
||||
scripts: {
|
||||
prepublish: 'semantic-release pre',
|
||||
postpublish: 'semantic-release post'
|
||||
prepublish: '../../../bin/semantic-release.js pre',
|
||||
postpublish: '../../../bin/semantic-release.js post'
|
||||
},
|
||||
publishConfig: {
|
||||
registry: 'http://localhost:4873/'
|
||||
@@ -26,19 +21,18 @@ module.exports = function (input) {
|
||||
})
|
||||
|
||||
id = pkg.name
|
||||
var cwd = join(__dirname, '../../.tmp/modules', id)
|
||||
const cwd = join(__dirname, '../../.tmp/modules', id)
|
||||
|
||||
exec(
|
||||
'mkdir ' + cwd + ' && ' +
|
||||
'cd ' + cwd + ' && ' +
|
||||
'git init && ' +
|
||||
'echo \'' + JSON.stringify(pkg, null, 2) + '\' >> package.json && ' +
|
||||
'git add . && ' +
|
||||
'git config user.email "integration@test" && ' +
|
||||
'git config user.name "Integration Test" && ' +
|
||||
'git commit -m "initial" && ' +
|
||||
'npm install'
|
||||
, efh(cb)(function (stdout) {
|
||||
`mkdir ${cwd} &&
|
||||
cd ${cwd} &&
|
||||
git init &&
|
||||
echo '${JSON.stringify(pkg, null, 2)}' >> package.json &&
|
||||
git add . &&
|
||||
git config user.email "integration@test" &&
|
||||
git config user.name "Integration Test" &&
|
||||
git commit -m "initial"`
|
||||
, efh(cb)((stdout) => {
|
||||
cb(null, id, cwd)
|
||||
}))
|
||||
}))
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = function (commits) {
|
||||
var type = null
|
||||
let type = null
|
||||
|
||||
commits.every(function (commit) {
|
||||
commits.every((commit) => {
|
||||
if (/FOO/.test(commit.message)) {
|
||||
type = 'major'
|
||||
return false
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = function (cb) {
|
||||
cb(null, 'custom log')
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = function (opts, cb) {
|
||||
cb(null, !(opts.commits.length % 2))
|
||||
}
|
||||
@@ -1,23 +1,21 @@
|
||||
'use strict'
|
||||
const path = require('path')
|
||||
|
||||
var path = require('path')
|
||||
const efh = require('error-first-handler')
|
||||
const test = require('tap').test
|
||||
|
||||
var efh = require('error-first-handler')
|
||||
const createModule = require('../lib/create-module')
|
||||
const commitToVersionTest = require('../lib/commit-to-version-test')
|
||||
|
||||
var commitToVersionTest = require('../lib/commit-to-version-test')
|
||||
|
||||
module.exports = function (test, createModule) {
|
||||
test('custom-analyzer', (t) => {
|
||||
createModule({
|
||||
release: {
|
||||
analyzer: path.join(__dirname, '../lib/custom-analyzer')
|
||||
}
|
||||
}, efh()(function (name, cwd) {
|
||||
test('custom-analyzer', function (t) {
|
||||
commitToVersionTest(t, 'HO', '0.0.0', 1, 'abort publish w/o changes', cwd)
|
||||
commitToVersionTest(t, 'BAZ', '1.0.0', 0, 'release 1.0.0 if unpublished', cwd)
|
||||
commitToVersionTest(t, 'BAZ', '1.0.1', 0, 'bump patch for fix', cwd)
|
||||
commitToVersionTest(t, 'BAR', '1.1.0', 0, 'bump minor for feature', cwd)
|
||||
commitToVersionTest(t, 'FOO', '2.0.0', 0, 'bump major for breaking change', cwd)
|
||||
})
|
||||
}, efh()((name, cwd) => {
|
||||
commitToVersionTest(t, 'HO', '0.0.0', 1, 'abort publish w/o changes', cwd)
|
||||
commitToVersionTest(t, 'BAZ', '1.0.0', 0, 'release 1.0.0 if unpublished', cwd)
|
||||
commitToVersionTest(t, 'BAZ', '1.0.1', 0, 'bump patch for fix', cwd)
|
||||
commitToVersionTest(t, 'BAR', '1.1.0', 0, 'bump minor for feature', cwd)
|
||||
commitToVersionTest(t, 'FOO', '2.0.0', 0, 'bump major for breaking change', cwd)
|
||||
}))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
const path = require('path')
|
||||
|
||||
const efh = require('error-first-handler')
|
||||
const nixt = require('nixt')
|
||||
const test = require('tap').test
|
||||
|
||||
const createModule = require('../lib/create-module')
|
||||
|
||||
test('custom-verification', (t) => {
|
||||
createModule({
|
||||
release: {
|
||||
verification: path.join(__dirname, '../lib/custom-verification')
|
||||
}
|
||||
}, efh()((name, cwd) => {
|
||||
t.test('even commit count', (t) => {
|
||||
t.plan(1)
|
||||
nixt()
|
||||
.cwd(cwd)
|
||||
.env('CI', true)
|
||||
.env('npm_config_registry', 'http://127.0.0.1:4873/')
|
||||
.exec('git commit --allow-empty -m "feat: commit"')
|
||||
.run('npm run prepublish')
|
||||
.code(0)
|
||||
.end((err) => t.error(err, 'nixt'))
|
||||
})
|
||||
|
||||
t.test('odd commit count', (t) => {
|
||||
t.plan(1)
|
||||
nixt()
|
||||
.cwd(cwd)
|
||||
.env('CI', true)
|
||||
.env('npm_config_registry', 'http://127.0.0.1:4873/')
|
||||
.exec('git commit --allow-empty -m "feat: commit"')
|
||||
.run('npm run prepublish')
|
||||
.code(1)
|
||||
.stdout(/Verification failed/)
|
||||
.end((err) => t.error(err, 'nixt'))
|
||||
})
|
||||
}))
|
||||
})
|
||||
+31
-32
@@ -1,37 +1,36 @@
|
||||
'use strict'
|
||||
const fs = require('fs')
|
||||
|
||||
var fs = require('fs')
|
||||
const efh = require('error-first-handler')
|
||||
const nixt = require('nixt')
|
||||
const test = require('tap').test
|
||||
|
||||
var efh = require('error-first-handler')
|
||||
var nixt = require('nixt')
|
||||
const createModule = require('../lib/create-module')
|
||||
|
||||
module.exports = function (test, createModule) {
|
||||
createModule(efh()(function (name, cwd) {
|
||||
test('ignore', function (t) {
|
||||
ignoreTest(t, 'npm install', 'not doing anything when the module is installed')
|
||||
ignoreTest(t, 'npm i', 'not doing anything when the module is installed with abbrevd command')
|
||||
ignoreTest(t, 'npm link', 'not doing anything when the module is linked')
|
||||
ignoreTest(t, 'npm lin', 'not doing anything when the module is linked with abbrevd command')
|
||||
ignoreTest(t, 'npm pack', 'not doing anything when the module is packed')
|
||||
ignoreTest(t, 'npm pa', 'not doing anything when the module is packed with abbrevd command')
|
||||
})
|
||||
|
||||
function ignoreTest (t, command, name, last) {
|
||||
t.test(name, function (t) {
|
||||
t.plan(2)
|
||||
|
||||
var pkg = fs.readFileSync(cwd + '/package.json')
|
||||
|
||||
nixt()
|
||||
.cwd(cwd)
|
||||
.run(command)
|
||||
.code(0)
|
||||
.stdout(/> semantic-release pre\n$/m)
|
||||
.end(function (err) {
|
||||
t.is(pkg + '', fs.readFileSync(cwd + '/package.json') + '', 'package')
|
||||
t.error(err, 'nixt')
|
||||
})
|
||||
})
|
||||
}
|
||||
test('ignore', (t) => {
|
||||
createModule(efh()((name, cwd) => {
|
||||
ignoreTest(t, cwd, 'npm install', 'not doing anything when the module is installed')
|
||||
ignoreTest(t, cwd, 'npm i', 'not doing anything when the module is installed with abbrevd command')
|
||||
ignoreTest(t, cwd, 'npm link', 'not doing anything when the module is linked')
|
||||
ignoreTest(t, cwd, 'npm lin', 'not doing anything when the module is linked with abbrevd command')
|
||||
ignoreTest(t, cwd, 'npm pack', 'not doing anything when the module is packed')
|
||||
ignoreTest(t, cwd, 'npm pa', 'not doing anything when the module is packed with abbrevd command')
|
||||
}))
|
||||
})
|
||||
|
||||
function ignoreTest (t, cwd, command, name) {
|
||||
t.test(name, (t) => {
|
||||
t.plan(2)
|
||||
|
||||
const pkg = String(fs.readFileSync(cwd + '/package.json'))
|
||||
|
||||
nixt()
|
||||
.cwd(cwd)
|
||||
.run(command)
|
||||
.code(0)
|
||||
.stdout(/semantic-release.js pre\n$/m)
|
||||
.end((err) => {
|
||||
t.is(pkg, String(fs.readFileSync(`${cwd}/package.json`)), 'package')
|
||||
t.error(err, 'nixt')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
'use strict'
|
||||
const path = require('path')
|
||||
|
||||
var path = require('path')
|
||||
const efh = require('error-first-handler')
|
||||
const GitHubApi = require('github')
|
||||
const nixt = require('nixt')
|
||||
const test = require('tap').test
|
||||
|
||||
var efh = require('error-first-handler')
|
||||
var GitHubApi = require('github')
|
||||
var nixt = require('nixt')
|
||||
const createModule = require('../lib/create-module')
|
||||
|
||||
var github = new GitHubApi({
|
||||
const github = new GitHubApi({
|
||||
version: '3.0.0',
|
||||
port: 4343,
|
||||
protocol: 'http',
|
||||
@@ -18,50 +19,44 @@ github.authenticate({
|
||||
token: '***'
|
||||
})
|
||||
|
||||
module.exports = function (test, createModule) {
|
||||
test('postpublish', (t) => {
|
||||
createModule({
|
||||
version: '2.0.0',
|
||||
repository: {
|
||||
type: 'git',
|
||||
url: 'http://github.com/user/repo'
|
||||
}
|
||||
}, efh()(function (name, cwd) {
|
||||
test('postpublish', function (t) {
|
||||
var base = getBase(cwd)
|
||||
}, efh()((name, cwd) => {
|
||||
const base = getBase(cwd)
|
||||
|
||||
t.test('publish new version to github releases', function (t) {
|
||||
t.plan(1)
|
||||
t.test('publish new version to github releases', (t) => {
|
||||
t.plan(1)
|
||||
|
||||
base.clone()
|
||||
.stdout(/> semantic-release post\n\nGenerating changelog from.*\nParsed/m)
|
||||
.run('npm run postpublish')
|
||||
.end(function (err) {
|
||||
t.error(err, 'nixt')
|
||||
})
|
||||
})
|
||||
base.clone()
|
||||
.stdout(/semantic-release.js post\n\nGenerating changelog from.*\nParsed/m)
|
||||
.run('npm run postpublish')
|
||||
.end((err) => t.error(err, 'nixt'))
|
||||
})
|
||||
|
||||
t.test('publish new version (with detached HEAD) to github releases', function (t) {
|
||||
t.plan(1)
|
||||
t.test('publish new version (with detached HEAD) to github releases', (t) => {
|
||||
t.plan(1)
|
||||
|
||||
base.clone()
|
||||
.stdout(/> semantic-release post\n\nGenerating changelog from.*\nParsed/m)
|
||||
.exec('git checkout `git rev-parse HEAD`')
|
||||
.run('npm run postpublish')
|
||||
.end(function (err) {
|
||||
t.error(err, 'nixt')
|
||||
})
|
||||
})
|
||||
base.clone()
|
||||
.stdout(/semantic-release.js post\n\nGenerating changelog from.*\nParsed/m)
|
||||
.exec('git checkout `git rev-parse HEAD`')
|
||||
.run('npm run postpublish')
|
||||
.end((err) => t.error(err, 'nixt'))
|
||||
})
|
||||
|
||||
t.test('correct data published', function (t) {
|
||||
t.plan(4)
|
||||
t.test('correct data published', (t) => {
|
||||
t.plan(4)
|
||||
|
||||
github.releases.getRelease({ owner: 'user', repo: 'repo', id: 1}, function (err, raw) {
|
||||
var res = JSON.parse(raw)
|
||||
t.error(err, 'github')
|
||||
t.is(res.tag_name, 'v2.0.0', 'version')
|
||||
t.is(res.author.login, 'user', 'user')
|
||||
t.ok(/\n\n\n#### Features\n\n\* \*\*cool:\*\*\n.*the next big thing/.test(res.body), 'body')
|
||||
})
|
||||
github.releases.getRelease({ owner: 'user', repo: 'repo', id: 1}, (err, raw) => {
|
||||
const res = JSON.parse(raw)
|
||||
t.error(err, 'github')
|
||||
t.is(res.tag_name, 'v2.0.0', 'version')
|
||||
t.is(res.author.login, 'user', 'user')
|
||||
t.ok(/\n\n\n#### Features\n\n\* \*\*cool:\*\*\n.*the next big thing/.test(res.body), 'body')
|
||||
})
|
||||
})
|
||||
}))
|
||||
@@ -75,34 +70,30 @@ module.exports = function (test, createModule) {
|
||||
release: {
|
||||
notes: path.join(__dirname, '../lib/custom-release-notes')
|
||||
}
|
||||
}, efh()(function (name, cwd) {
|
||||
test('custom-release-notes', function (t) {
|
||||
var base = getBase(cwd)
|
||||
}, efh()((name, cwd) => {
|
||||
const base = getBase(cwd)
|
||||
|
||||
t.test('publish new version (with custom notes) to github releases', function (t) {
|
||||
t.plan(1)
|
||||
t.test('publish new version (with custom notes) to github releases', (t) => {
|
||||
t.plan(1)
|
||||
|
||||
base.clone()
|
||||
.run('npm run postpublish')
|
||||
.end(function (err) {
|
||||
t.error(err, 'nixt')
|
||||
})
|
||||
})
|
||||
base.clone()
|
||||
.run('npm run postpublish')
|
||||
.end((err) => t.error(err, 'nixt'))
|
||||
})
|
||||
|
||||
t.test('custom notes published', function (t) {
|
||||
t.plan(4)
|
||||
t.test('custom notes published', (t) => {
|
||||
t.plan(4)
|
||||
|
||||
github.releases.getRelease({ owner: 'user', repo: 'repo', id: 3}, function (err, raw) {
|
||||
var res = JSON.parse(raw)
|
||||
t.error(err, 'github')
|
||||
t.is(res.tag_name, 'v2.0.0', 'version')
|
||||
t.is(res.author.login, 'user', 'user')
|
||||
t.ok(/custom log/.test(res.body), 'body')
|
||||
})
|
||||
github.releases.getRelease({ owner: 'user', repo: 'repo', id: 3}, (err, raw) => {
|
||||
const res = JSON.parse(raw)
|
||||
t.error(err, 'github')
|
||||
t.is(res.tag_name, 'v2.0.0', 'version')
|
||||
t.is(res.author.login, 'user', 'user')
|
||||
t.ok(/custom log/.test(res.body), 'body')
|
||||
})
|
||||
})
|
||||
}))
|
||||
}
|
||||
})
|
||||
|
||||
function getBase (cwd) {
|
||||
return nixt()
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
'use strict'
|
||||
const efh = require('error-first-handler')
|
||||
const test = require('tap').test
|
||||
|
||||
var efh = require('error-first-handler')
|
||||
const createModule = require('../lib/create-module')
|
||||
const commitToVersionTest = require('../lib/commit-to-version-test')
|
||||
|
||||
var commitToVersionTest = require('../lib/commit-to-version-test')
|
||||
|
||||
module.exports = function (test, createModule) {
|
||||
createModule(efh()(function (name, cwd) {
|
||||
test('prepublish', function (t) {
|
||||
commitToVersionTest(t, 'refactor: change', '0.0.0', 1, 'abort publish w/o changes', cwd)
|
||||
commitToVersionTest(t, 'fix: change', '1.0.0', 0, 'release 1.0.0 if unpublished', cwd)
|
||||
commitToVersionTest(t, 'fix: change', '1.0.1', 0, 'bump patch for fix', cwd)
|
||||
commitToVersionTest(t, 'feat: change', '1.1.0', 0, 'bump minor for feature', cwd)
|
||||
commitToVersionTest(t, 'fix: BREAKING CHANGE: change', '2.0.0', 0, 'bump major for breaking change', cwd)
|
||||
})
|
||||
test('prepublish', (t) => {
|
||||
createModule(efh()((name, cwd) => {
|
||||
commitToVersionTest(t, 'refactor: change', '0.0.0', 1, 'abort publish w/o changes', cwd)
|
||||
commitToVersionTest(t, 'fix: change', '1.0.0', 0, 'release 1.0.0 if unpublished', cwd)
|
||||
commitToVersionTest(t, 'fix: change', '1.0.1', 0, 'bump patch for fix', cwd)
|
||||
commitToVersionTest(t, 'feat: change', '1.1.0', 0, 'bump minor for feature', cwd)
|
||||
commitToVersionTest(t, 'fix: BREAKING CHANGE: change', '2.0.0', 0, 'bump major for breaking change', cwd)
|
||||
}))
|
||||
}
|
||||
})
|
||||
|
||||
+30
-33
@@ -1,37 +1,34 @@
|
||||
'use strict'
|
||||
const efh = require('error-first-handler')
|
||||
const nixt = require('nixt')
|
||||
const test = require('tap').test
|
||||
|
||||
var efh = require('error-first-handler')
|
||||
var nixt = require('nixt')
|
||||
const createModule = require('../lib/create-module')
|
||||
|
||||
module.exports = function (test, createModule) {
|
||||
test('publish', function (t) {
|
||||
publishTest(t, 'npm publish', 'pre and post hooks work as a part of publish')
|
||||
publishTest(t, 'npm pub', 'pre and post hooks work as a part of publish with abbrevd command')
|
||||
test('publish', (t) => {
|
||||
publishTest(t, 'npm publish', 'pre and post hooks work as a part of publish')
|
||||
publishTest(t, 'npm pub', 'pre and post hooks work as a part of publish with abbrevd command')
|
||||
|
||||
function publishTest (t, command, testname, last) {
|
||||
createModule({
|
||||
repository: {
|
||||
type: 'git',
|
||||
url: 'http://github.com/user/repo'
|
||||
}
|
||||
}, efh()(function (name, cwd) {
|
||||
t.test(testname, function (t) {
|
||||
t.plan(1)
|
||||
function publishTest (t, command, testname, last) {
|
||||
createModule({
|
||||
repository: {
|
||||
type: 'git',
|
||||
url: 'http://github.com/user/repo'
|
||||
}
|
||||
}, efh()((name, cwd) => {
|
||||
t.test(testname, (t) => {
|
||||
t.plan(1)
|
||||
|
||||
nixt()
|
||||
.cwd(cwd)
|
||||
.env('CI', true)
|
||||
.env('GH_URL', 'http://127.0.0.1:4343/')
|
||||
.env('GH_TOKEN', '***')
|
||||
.exec('git commit --allow-empty -m "feat: super"')
|
||||
.run(command)
|
||||
.code(1)
|
||||
.stdout(/Everything is alright/)
|
||||
.end(function (err) {
|
||||
t.error(err, 'nixt')
|
||||
})
|
||||
})
|
||||
}))
|
||||
}
|
||||
})
|
||||
}
|
||||
nixt()
|
||||
.cwd(cwd)
|
||||
.env('CI', true)
|
||||
.env('GH_URL', 'http://127.0.0.1:4343/')
|
||||
.env('GH_TOKEN', '***')
|
||||
.exec('git commit --allow-empty -m "feat: super"')
|
||||
.run(command)
|
||||
.code(1)
|
||||
.stdout(/Everything is alright/)
|
||||
.end((err) => t.error(err, 'nixt'))
|
||||
})
|
||||
}))
|
||||
}
|
||||
})
|
||||
|
||||
+24
-25
@@ -1,38 +1,37 @@
|
||||
'use strict'
|
||||
const join = require('path').join
|
||||
const readFile = require('fs').readFileSync
|
||||
|
||||
var join = require('path').join
|
||||
var readFile = require('fs').readFileSync
|
||||
const efh = require('error-first-handler')
|
||||
const nixt = require('nixt')
|
||||
const test = require('tap').test
|
||||
|
||||
var efh = require('error-first-handler')
|
||||
var nixt = require('nixt')
|
||||
const createModule = require('../lib/create-module')
|
||||
|
||||
module.exports = function (test, createModule) {
|
||||
test('setup', (t) => {
|
||||
createModule({
|
||||
repository: {},
|
||||
scripts: {
|
||||
postpublish: 'npm run gh-pages'
|
||||
}
|
||||
}, efh()(function (name, cwd) {
|
||||
test('setup', function (t) {
|
||||
t.test('setup "package.json"', function (t) {
|
||||
t.plan(5)
|
||||
}, efh()((name, cwd) => {
|
||||
t.test('setup "package.json"', (t) => {
|
||||
t.plan(5)
|
||||
|
||||
nixt()
|
||||
.cwd(cwd)
|
||||
.exec('git remote add origin git@github.com:user/repo.git')
|
||||
.run('./node_modules/.bin/semantic-release setup')
|
||||
.code(0)
|
||||
.end(function (err) {
|
||||
t.error(err, 'nixt')
|
||||
nixt()
|
||||
.cwd(cwd)
|
||||
.exec('git remote add origin git@github.com:user/repo.git')
|
||||
.run('../../../bin/semantic-release.js setup')
|
||||
.code(0)
|
||||
.end((err) => {
|
||||
t.error(err, 'nixt')
|
||||
|
||||
var pkg = JSON.parse(readFile(join(cwd, 'package.json')))
|
||||
const pkg = JSON.parse(readFile(join(cwd, 'package.json')))
|
||||
|
||||
t.is(pkg.version, '0.0.0-semantically-released', 'version')
|
||||
t.is(pkg.repository.url, 'https://github.com/user/repo', 'repo')
|
||||
t.is(pkg.scripts.prepublish, 'semantic-release pre', 'pre')
|
||||
t.is(pkg.scripts.postpublish, 'npm run gh-pages && semantic-release post', 'post')
|
||||
})
|
||||
})
|
||||
t.is(pkg.version, '0.0.0-semantically-released', 'version')
|
||||
t.is(pkg.repository.url, 'https://github.com/user/repo', 'repo')
|
||||
t.is(pkg.scripts.prepublish, 'semantic-release pre', 'pre')
|
||||
t.is(pkg.scripts.postpublish, 'npm run gh-pages && semantic-release post', 'post')
|
||||
})
|
||||
})
|
||||
}))
|
||||
}
|
||||
})
|
||||
|
||||
+37
-26
@@ -1,34 +1,45 @@
|
||||
'use strict'
|
||||
const efh = require('error-first-handler')
|
||||
const nixt = require('nixt')
|
||||
const test = require('tap').test
|
||||
|
||||
var efh = require('error-first-handler')
|
||||
var nixt = require('nixt')
|
||||
const createModule = require('../lib/create-module')
|
||||
|
||||
module.exports = function (test, createModule) {
|
||||
test('verify', (t) => {
|
||||
createModule({
|
||||
repository: {},
|
||||
scripts: {
|
||||
prepublish: 'semantic-release pre --no-token'
|
||||
prepublish: '../../../bin/semantic-release.js pre --no-token'
|
||||
}
|
||||
}, efh()(function (name, cwd) {
|
||||
test('verify', function (t) {
|
||||
t.test('verify package and options before publishing', function (t) {
|
||||
t.plan(1)
|
||||
|
||||
nixt()
|
||||
.cwd(cwd)
|
||||
.env('CI', true)
|
||||
.run('npm publish')
|
||||
.stderr(new RegExp(
|
||||
'You must define a GitHub token\.\n' +
|
||||
'You must define your GitHub "repository" inside the "package.json"\.\n' +
|
||||
'You must define your "scripts" inside the "package.json"\.'
|
||||
, 'm'
|
||||
))
|
||||
.code(1)
|
||||
.end(function (err) {
|
||||
t.error(err, 'nixt')
|
||||
})
|
||||
})
|
||||
}, efh()((name, cwd) => {
|
||||
t.test('verify package and options before publishing', (t) => {
|
||||
t.plan(1)
|
||||
nixt()
|
||||
.cwd(cwd)
|
||||
.env('CI', true)
|
||||
.run('npm publish')
|
||||
.stderr(new RegExp(
|
||||
`You must define a GitHub token\.
|
||||
You must define your GitHub "repository" inside the "package.json"\.
|
||||
You must define your "scripts" inside the "package.json"\.`
|
||||
, 'm'
|
||||
))
|
||||
.code(1)
|
||||
.end((err) => t.error(err, 'nixt'))
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
createModule({
|
||||
version: '1.0.0-semantically-released'
|
||||
}, efh()((name, cwd) => {
|
||||
t.test('not publishing placeholder versions', (t) => {
|
||||
t.plan(1)
|
||||
|
||||
nixt()
|
||||
.cwd(cwd)
|
||||
.env('CI', true)
|
||||
.run('npm publish --semantic-release-rerun')
|
||||
.code(1)
|
||||
.end((err) => t.error(err, 'nixt'))
|
||||
})
|
||||
}))
|
||||
})
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
const test = require('tap').test
|
||||
const nock = require('nock')
|
||||
|
||||
const npmInfo = require('../../dist/lib/npm-info.js')
|
||||
|
||||
const registry = 'http://registry.npmjs.org/'
|
||||
|
||||
const defaultModule = {
|
||||
'dist-tags': {
|
||||
latest: '1.0.0'
|
||||
},
|
||||
versions: {
|
||||
'1.0.0': {
|
||||
gitHead: 'HEAD'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process.env.npm_config_registry = registry
|
||||
|
||||
test('npm-info', (t) => {
|
||||
const regMock = nock(registry, {
|
||||
reqheaders: {
|
||||
'authorization': 'Bearer testtoken'
|
||||
}
|
||||
})
|
||||
.get('/express')
|
||||
.reply(200, defaultModule)
|
||||
.get('/@user%2Fmodule')
|
||||
.reply(200, defaultModule)
|
||||
|
||||
t.test('get unscoped module', (t) => {
|
||||
t.plan(3)
|
||||
npmInfo('express', (err, info) => {
|
||||
t.error(err, 'error')
|
||||
t.is(info.version, '1.0.0', 'version')
|
||||
t.is(info.gitHead, 'HEAD', 'gitHead')
|
||||
})
|
||||
})
|
||||
t.test('get scoped module', (t) => {
|
||||
t.plan(3)
|
||||
npmInfo('@user/module', (err, info) => {
|
||||
t.error(err, 'error')
|
||||
t.is(info.version, '1.0.0', 'version')
|
||||
t.is(info.gitHead, 'HEAD', 'gitHead')
|
||||
regMock.done()
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user