Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
875bb038a1 | ||
|
|
89f1928769 | ||
|
|
3799ad0cb6 | ||
|
|
7380d586ee | ||
|
|
eb470712d7 | ||
|
|
f2484b8e42 | ||
|
|
73b888fdc3 | ||
|
|
f44cedbaa7 | ||
|
|
a540c402a9 | ||
|
|
ffbd39e78a | ||
|
|
81df21b924 | ||
|
|
d22b98a4ee | ||
|
|
c936e8be4b | ||
|
|
019aeeabe1 | ||
|
|
19fd15c1dc | ||
|
|
16cf9aee9b | ||
|
|
f2c701ca1b | ||
|
|
b39fecbdc2 | ||
|
|
f7faebb175 | ||
|
|
cf36c2fe9b | ||
|
|
a48b0c957d | ||
|
|
a1c86fc0d0 | ||
|
|
bd90936927 | ||
|
|
c0aebd9873 | ||
|
|
9191260cb0 | ||
|
|
7fa0754ff2 | ||
|
|
7d21697d78 | ||
|
|
07c5d08d35 | ||
|
|
a89e7e6b1e | ||
|
|
1d9350597a | ||
|
|
fd11c85692 | ||
|
|
fe750f7b9e | ||
|
|
17ad82bfbc | ||
|
|
0ee9cc31e9 | ||
|
|
f31a5dfd04 | ||
|
|
012dce2641 |
@@ -1,11 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
-11
@@ -1,14 +1,3 @@
|
||||
# common
|
||||
coverage
|
||||
node_modules
|
||||
test/registry/couch
|
||||
test/registry/data
|
||||
*.log
|
||||
*.dump
|
||||
.DS_Store
|
||||
.nyc_output
|
||||
.test
|
||||
.tmp
|
||||
|
||||
# build-artifacts
|
||||
dist
|
||||
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
# common
|
||||
coverage
|
||||
node_modules
|
||||
test/registry/couch
|
||||
test/registry/data
|
||||
*.log
|
||||
*.dump
|
||||
.DS_Store
|
||||
.nyc_output
|
||||
.test
|
||||
.tmp
|
||||
|
||||
# source/config
|
||||
src
|
||||
*.yml
|
||||
.gitignore
|
||||
.editorconfig
|
||||
.npmrc
|
||||
+13
-15
@@ -1,22 +1,20 @@
|
||||
sudo: false
|
||||
language: node_js
|
||||
node_js:
|
||||
- '0.10'
|
||||
sudo: false
|
||||
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:
|
||||
- npm prune
|
||||
- curl -Lo travis_after_all.py https://git.io/vLSON
|
||||
after_success:
|
||||
- python travis_after_all.py
|
||||
- export $(cat .to_export_back)
|
||||
- if [[ $BUILD_LEADER = YES ]]; then npm run coverage:upload; fi
|
||||
- npm run semantic-release
|
||||
- npm i -g npm@^2.0.0
|
||||
deploy:
|
||||
provider: npm
|
||||
email: stephan@boennemann.me
|
||||
skip_cleanup: true
|
||||
api_key:
|
||||
secure: Lq1FZweaNr/Ah8M7h3oWQ59HTswzvcksTUfzWb/dpqNn5FECN9I+4gi79EQPD62ZbJDCuDHY0EEEDLdnaB1z8N7kOj1RtmvC1k0teTEXFsGBPS4evXakRj+AfoBAGsTaXHqBYBOvYBxJT2Md/UoOgPSQjtAdZSNsmoFb1xkngQ0=
|
||||
on:
|
||||
branch: master
|
||||
repo: boennemann/semantic-release
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
# semantic-release
|
||||
[](https://travis-ci.org/semantic-release/semantic-release)
|
||||
[](https://coveralls.io/github/semantic-release/semantic-release?branch=next)
|
||||
[](https://david-dm.org/semantic-release/semantic-release/next)
|
||||
[](https://david-dm.org/semantic-release/semantic-release/next#info=devDependencies)
|
||||
[](https://github.com/feross/standard)
|
||||
[](https://travis-ci.org/boennemann/semantic-release)
|
||||
[](https://david-dm.org/boennemann/semantic-release)
|
||||
[](https://david-dm.org/boennemann/semantic-release#info=devDependencies)
|
||||
|
||||
[](https://nodei.co/npm/semantic-release/)
|
||||
|
||||
## What is `semantic-release` about?
|
||||
```bash
|
||||
npm i semantic-release
|
||||
```
|
||||
You *need* to set it up inside your `package.json`:
|
||||
|
||||
At its core `semantic-release` is a set of conventions that gives you entirely automated, semver-compliant package publishing. _Coincidentally_ these conventions make sense on their own, like having meaningful commit messages.
|
||||
```json
|
||||
"scripts": {
|
||||
"prepublish": "semantic-release pre",
|
||||
"postpublish": "semantic-release post"
|
||||
}
|
||||
```
|
||||
|
||||
[](https://www.youtube.com/watch?v=tc2UgG5L7WM&index=6&list=PLFZ5NyC0xHDaaTy6tY9p0C0jd_rRRl5Zm)
|
||||
Note: `semantic-release` works around a limitation in npm's "prepublish" hook. Once a version is published it prints an error that you can *safely ignore*.
|
||||
See [npm/npm#7118](https://github.com/npm/npm/issues/7118).
|
||||
|
||||
> This talk gives you a complete introduction to the underlying concepts
|
||||
|
||||
The next branch is a completely rewritten version of `semantic-release`, that isn't fully tested and documented yet.
|
||||
It has lots and lots of great new features, but also breaks a lot of things.
|
||||
Unless you're adventurous you should look at the [stable master branch](https://github.com/semantic-release/semantic-release/tree/master).
|
||||
MIT License
|
||||
2015 Stephan Bönnemann
|
||||
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
cat .tmp/sinopia.pid | xargs kill
|
||||
|
||||
cat .tmp/ghrs.pid | xargs kill
|
||||
|
||||
cp .tmp/.npmrc ~/.npmrc
|
||||
|
||||
rm -rf .tmp
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
mkdir -p .tmp/modules
|
||||
|
||||
./node_modules/.bin/sinopia ./tests/config.yml & echo $! >> .tmp/sinopia.pid
|
||||
./node_modules/.bin/github-release-fake-server -p 4343 & echo $! >> .tmp/ghrs.pid
|
||||
|
||||
sleep 0.5
|
||||
|
||||
cp ~/.npmrc .tmp/.npmrc
|
||||
|
||||
cp tests/.npmrc ~/.npmrc
|
||||
Executable
+78
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict'
|
||||
|
||||
var abbrev = require('abbrev')
|
||||
var confirm = require('confirm-simple')
|
||||
var minimist = require('minimist')
|
||||
|
||||
var efh = require('../lib/error').standard
|
||||
|
||||
var argv = minimist(process.argv.slice(2), {
|
||||
alias: {
|
||||
d: 'debug',
|
||||
dry: 'debug',
|
||||
t: 'token',
|
||||
g: 'github-url'
|
||||
},
|
||||
default: {
|
||||
token: process.env.GH_TOKEN || process.env.TOKEN || process.env.GITHUB_TOKEN,
|
||||
'github-url': process.env.GH_URL
|
||||
}
|
||||
})
|
||||
|
||||
var npmArgv = process.env.npm_config_argv ?
|
||||
minimist(JSON.parse(process.env.npm_config_argv).cooked) :
|
||||
{_: []}
|
||||
|
||||
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')) process.exit(0)
|
||||
|
||||
return confirmCI(function () {
|
||||
console.log('Determining new version')
|
||||
|
||||
var publish = false
|
||||
if (isAbbrev(npmArgv, 'publish')) publish = true
|
||||
|
||||
require('../src/pre')(argv, efh(function (result) {
|
||||
if (!result) {
|
||||
console.log('Nothing changed. Not publishing.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log('Publishing v' + result)
|
||||
if (!publish) process.exit(0)
|
||||
|
||||
require('../src/restart')(efh(function () {
|
||||
process.exit(1)
|
||||
}))
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
if (~argv._.indexOf('post')) {
|
||||
return confirmCI(function () {
|
||||
require('../src/post')(argv, 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.')
|
||||
}
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
function confirmCI (cb) {
|
||||
if (process.env.CI || argv.ci === false) return cb(null, true)
|
||||
|
||||
confirm('Not running in a CI enviroment. Are you sure you want to run this hook?', function (ok) {
|
||||
if (!ok) process.exit(1)
|
||||
cb(null, ok)
|
||||
})
|
||||
}
|
||||
|
||||
function isAbbrev (argv, command) {
|
||||
return argv._.some(Object.prototype.hasOwnProperty.bind(abbrev(command)))
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/* istanbul ignore next */
|
||||
try {
|
||||
require('../dist')
|
||||
} catch (err) {
|
||||
if (err.code === 'MODULE_NOT_FOUND') {
|
||||
require('babel/register')
|
||||
require('../src')
|
||||
} else {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
'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)
|
||||
if (err.message) return console.log(err.message)
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = function (commits) {
|
||||
var type = null
|
||||
|
||||
commits.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
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
'use strict'
|
||||
|
||||
var git = require('conventional-changelog/lib/git')
|
||||
|
||||
var efh = require('../error').efh
|
||||
|
||||
module.exports = function (cb) {
|
||||
git.latestTag(efh(cb)(function (from) {
|
||||
git.getCommits({from: from}, efh(cb)(function (commits) {
|
||||
cb(null, commits)
|
||||
}))
|
||||
}))
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
'use strict'
|
||||
|
||||
var analyze = require('./analyze')
|
||||
var commits = require('./commits')
|
||||
var efh = require('../error').efh
|
||||
|
||||
module.exports = function (cb) {
|
||||
commits(efh(cb)(function (commits) {
|
||||
cb(null, analyze(commits))
|
||||
}))
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
'use strict'
|
||||
|
||||
var exec = require('child_process').exec
|
||||
|
||||
var efh = require('./error').efh
|
||||
|
||||
module.exports = function (pkg, cb) {
|
||||
if (!pkg.name) return cb(new Error('Package must have a name'))
|
||||
|
||||
exec('curl -s "' + process.env.npm_config_registry + pkg.name + '"', efh(cb)(function(stdout) {
|
||||
var pkg = JSON.parse(stdout)
|
||||
|
||||
if (pkg.error) return cb(null, null, true)
|
||||
|
||||
cb(null, pkg['dist-tags'].latest)
|
||||
}))
|
||||
}
|
||||
+36
-71
@@ -1,93 +1,58 @@
|
||||
{
|
||||
"name": "semantic-release",
|
||||
"description": "automated semver compliant package publishing",
|
||||
"author": "Stephan Bönnemann <stephan@boennemann.me> (http://boennemann.me)",
|
||||
"bin": {
|
||||
"semantic-release": "./bin/semantic-release.js"
|
||||
},
|
||||
"description": "semantic semver compliant package publishing",
|
||||
"version": "0.0.6",
|
||||
"author": "Stephan Bönnemann <stephan@boennemann.me>",
|
||||
"bin": "./bin/semantic-release",
|
||||
"bugs": {
|
||||
"url": "https://github.com/semantic-release/semantic-release/issues"
|
||||
},
|
||||
"bundleDependencies": [
|
||||
"@semantic-release/commit-analyzer",
|
||||
"@semantic-release/condition-travis",
|
||||
"@semantic-release/error",
|
||||
"@semantic-release/release-notes-generator"
|
||||
],
|
||||
"config": {
|
||||
"nyc": {
|
||||
"exclude": [
|
||||
".test",
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
"url": "https://github.com/boennemann/semantic-release/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@semantic-release/commit-analyzer": "^2.0.0",
|
||||
"@semantic-release/condition-travis": "^4.0.0",
|
||||
"@semantic-release/error": "^1.0.0",
|
||||
"@semantic-release/release-notes-generator": "^2.0.0",
|
||||
"git-head": "^1.2.1",
|
||||
"github": "^0.2.4",
|
||||
"lodash": "^3.9.3",
|
||||
"nopt": "^3.0.3",
|
||||
"npm-registry-client": "^6.4.0",
|
||||
"npmconf": "^2.1.2",
|
||||
"npmlog": "^1.2.1",
|
||||
"abbrev": "^1.0.5",
|
||||
"confirm-simple": "^1.0.3",
|
||||
"conventional-changelog": "0.0.11",
|
||||
"error-first-handler": "^1.0.1",
|
||||
"github": "^0.2.3",
|
||||
"github-url-from-git": "^1.4.0",
|
||||
"minimist": "^1.1.0",
|
||||
"parse-github-repo-url": "^1.0.0",
|
||||
"require-relative": "^0.8.7",
|
||||
"run-auto": "^1.1.2",
|
||||
"semver": "^5.0.1"
|
||||
"semver": "^4.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel": "^5.5.8",
|
||||
"coveralls": "^2.11.2",
|
||||
"mkdirp": "^0.5.1",
|
||||
"github-release-fake-server": "^1.1.1",
|
||||
"lodash.defaults": "^3.0.0",
|
||||
"nano-uid": "^0.2.0",
|
||||
"nixt": "^0.4.1",
|
||||
"nock": "^2.5.0",
|
||||
"npm-registry-couchapp": "^2.6.11",
|
||||
"nyc": "^3.0.0",
|
||||
"proxyquire": "^1.5.0",
|
||||
"rimraf": "^2.4.0",
|
||||
"standard": "^4.2.1",
|
||||
"tap": "^1.3.1"
|
||||
"sinopia": "^1.0.0",
|
||||
"standard": "^2.3.1",
|
||||
"tap-spec": "^2.2.0",
|
||||
"tape": "^3.5.0"
|
||||
},
|
||||
"homepage": "https://github.com/semantic-release/semantic-release/tree/next#readme",
|
||||
"engines": {
|
||||
"node": "^0.10.0",
|
||||
"npm": "^2.0.0"
|
||||
},
|
||||
"homepage": "https://github.com/boennemann/semantic-release",
|
||||
"keywords": [
|
||||
"author",
|
||||
"automation",
|
||||
"changelog",
|
||||
"release",
|
||||
"publish",
|
||||
"module",
|
||||
"package",
|
||||
"publish",
|
||||
"release",
|
||||
"semver",
|
||||
"version"
|
||||
"version",
|
||||
"changelog"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "dist/index.js",
|
||||
"publishConfig": {
|
||||
"tag": "next"
|
||||
},
|
||||
"release": {
|
||||
"branch": "next"
|
||||
},
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/semantic-release/semantic-release.git"
|
||||
"url": "https://github.com/boennemann/semantic-release.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rimraf dist && mkdirp dist && babel src --out-dir dist",
|
||||
"coverage": "nyc report",
|
||||
"coverage:upload": "npm run coverage -- --reporter=lcovonly && coveralls < coverage/lcov.info",
|
||||
"prepublish": "npm run build",
|
||||
"pretest:integration": "npm run build && npm run test:build",
|
||||
"pretest:unit": "npm run build && npm run test:build",
|
||||
"semantic-release": "./bin/semantic-release.js pre && npm dedupe && npm publish && ./bin/semantic-release.js post",
|
||||
"test": "npm run test:style && npm run test:unit",
|
||||
"test:build": "rimraf .test && mkdirp .test && babel test --out-dir .test",
|
||||
"test:integration": "tap --no-cov .test/scenarios/*.js",
|
||||
"test:style": "standard",
|
||||
"test:unit": "nyc tap --no-cov .test/specs/*.js"
|
||||
"postpublish": "./bin/semantic-release post",
|
||||
"posttest": "./bin/post-test",
|
||||
"prepublish": "./bin/semantic-release pre",
|
||||
"pretest": "./bin/pre-test",
|
||||
"test": "standard && node tests | tap-spec"
|
||||
}
|
||||
}
|
||||
|
||||
-134
@@ -1,134 +0,0 @@
|
||||
const { readFileSync, writeFileSync } = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const _ = require('lodash')
|
||||
const log = require('npmlog')
|
||||
const nopt = require('nopt')
|
||||
const npmconf = require('npmconf')
|
||||
|
||||
const PREFIX = '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(PREFIX, 'Failed to load npm config.', err)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
let npm = {
|
||||
auth: {
|
||||
token: env.NPM_TOKEN
|
||||
},
|
||||
loglevel: conf.get('loglevel'),
|
||||
registry: conf.get('registry'),
|
||||
tag: (pkg.publishConfig || {}).tag || conf.get('tag') || 'latest'
|
||||
}
|
||||
|
||||
if (npm.registry[npm.registry.length - 1] !== '/') npm.registry += '/'
|
||||
|
||||
log.level = npm.loglevel
|
||||
|
||||
const config = {PREFIX, log, env, pkg, options, plugins, npm}
|
||||
|
||||
log.verbose(PREFIX, 'options:', _.assign({
|
||||
githubToken: options.githubToken ? '***' : undefined
|
||||
}), options)
|
||||
log.verbose(PREFIX, 'Verifying config.')
|
||||
|
||||
const errors = require('./lib/verify')(config)
|
||||
errors.forEach((err) => log.error(PREFIX, `${err.message} ${err.code}`))
|
||||
if (errors.length) process.exit(1)
|
||||
|
||||
if (options.argv.remain[0] === 'pre') {
|
||||
log.verbose(PREFIX, 'Running pre-script.')
|
||||
log.verbose(PREFIX, 'Veriying conditions.')
|
||||
|
||||
plugins.verifyConditions(config, (err) => {
|
||||
if (err) {
|
||||
log[options.debug ? 'warn' : 'error'](PREFIX, err.message)
|
||||
if (!options.debug) process.exit(1)
|
||||
}
|
||||
|
||||
const nerfDart = require('./lib/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(PREFIX, 'Failed to save npm config.', err)
|
||||
|
||||
if (wroteNpmRc) log.verbose(PREFIX, 'Wrote authToken to .npmrc.')
|
||||
|
||||
require('./pre')(config, (err, release) => {
|
||||
if (err) {
|
||||
log.error(PREFIX, 'Failed to determine new version.')
|
||||
|
||||
const args = [PREFIX, (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(PREFIX, message)
|
||||
|
||||
if (options.debug) {
|
||||
log.error(PREFIX, `${message} Not publishing in debug mode.`, release)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
writeFileSync('./package.json', JSON.stringify(_.assign(pkg, {
|
||||
version: release.version
|
||||
}), null, 2))
|
||||
|
||||
log.verbose(PREFIX, `Wrote version ${release.version} to package.json.`)
|
||||
})
|
||||
})
|
||||
})
|
||||
} else if (options.argv.remain[0] === 'post') {
|
||||
log.verbose(PREFIX, 'Running post-script.')
|
||||
|
||||
require('./post')(config, (err, published, release) => {
|
||||
if (err) {
|
||||
log.error(PREFIX, 'Failed to publish release notes.', err)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
log.verbose(PREFIX, `${published ? 'Published' : 'Generated'} release notes.`, release)
|
||||
})
|
||||
} else {
|
||||
log.error(PREFIX, `Command "${options.argv.remain[0]}" not recognized. User either "pre" or "post"`)
|
||||
}
|
||||
})
|
||||
@@ -1,25 +0,0 @@
|
||||
const { exec } = require('child_process')
|
||||
|
||||
module.exports = function ({lastRelease}, cb) {
|
||||
const from = lastRelease.gitHead
|
||||
const range = (from ? from + '..' : '') + 'HEAD'
|
||||
|
||||
exec(
|
||||
`git log -E --format=%H==SPLIT==%B==END== ${range}`,
|
||||
(err, stdout) => {
|
||||
if (err) return cb(err)
|
||||
|
||||
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]
|
||||
}
|
||||
}))
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
const SemanticReleaseError = require('@semantic-release/error')
|
||||
|
||||
const npmlog = require('npmlog')
|
||||
const RegClient = require('npm-registry-client')
|
||||
|
||||
module.exports = function ({pkg, npm}, cb) {
|
||||
npmlog.level = npm.loglevel || 'error'
|
||||
const client = new RegClient({log: npmlog})
|
||||
|
||||
client.get(`${npm.registry}${pkg.name}`, {
|
||||
auth: npm.auth
|
||||
}, (err, data) => {
|
||||
if (err && err.statusCode === 404) return cb(null, {})
|
||||
if (err) return cb(err)
|
||||
|
||||
const version = data['dist-tags'][npm.tag]
|
||||
|
||||
if (!version) return cb(new SemanticReleaseError(`There is no release with the dist-tag "${npm.tag}" yet. Tag a version first.`, 'ENODISTTAG'))
|
||||
|
||||
cb(null, {
|
||||
version,
|
||||
gitHead: data.versions[version].gitHead,
|
||||
tag: npm.tag
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
// borrowed from https://github.com/npm/npm/blob/master/lib/config/nerf-dart.js
|
||||
const url = require('url')
|
||||
|
||||
/* istanbul ignore next */
|
||||
module.exports = function toNerfDart (uri) {
|
||||
let parsed = url.parse(uri)
|
||||
delete parsed.protocol
|
||||
delete parsed.auth
|
||||
delete parsed.query
|
||||
delete parsed.search
|
||||
delete parsed.hash
|
||||
|
||||
return url.resolve(url.format(parsed), '.')
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
/* istanbul ignore next */
|
||||
module.exports = function (config, options, cb) {
|
||||
cb(null)
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
const relative = require('require-relative')
|
||||
|
||||
let exports = module.exports = function (options) {
|
||||
return {
|
||||
analyzeCommits: exports.normalize(options.analyzeCommits, '@semantic-release/commit-analyzer'),
|
||||
generateNotes: exports.normalize(options.generateNotes, '@semantic-release/release-notes-generator'),
|
||||
verifyConditions: exports.normalize(options.verifyConditions, '@semantic-release/condition-travis'),
|
||||
verifyRelease: exports.normalize(options.verifyRelease, './plugin-noop')
|
||||
}
|
||||
}
|
||||
|
||||
exports.normalize = function (pluginConfig, fallback) {
|
||||
if (typeof pluginConfig === 'string') return relative(pluginConfig).bind(null, {})
|
||||
|
||||
if (pluginConfig && (typeof pluginConfig.path === 'string')) {
|
||||
return relative(pluginConfig.path).bind(null, pluginConfig)
|
||||
}
|
||||
|
||||
return require(fallback).bind(null, pluginConfig)
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
const SemanticReleaseError = require('@semantic-release/error')
|
||||
|
||||
module.exports = function (config, cb) {
|
||||
const { plugins, lastRelease } = config
|
||||
|
||||
plugins.analyzeCommits(config, (err, type) => {
|
||||
if (err) return cb(err)
|
||||
|
||||
if (!type) {
|
||||
return cb(new SemanticReleaseError(
|
||||
'There are no relevant changes, so no new version is released.',
|
||||
'ENOCHANGE'
|
||||
))
|
||||
}
|
||||
|
||||
if (!lastRelease.version) return cb(null, 'initial')
|
||||
|
||||
cb(null, type)
|
||||
})
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
const parseSlug = require('parse-github-repo-url')
|
||||
|
||||
const SemanticReleaseError = require('@semantic-release/error')
|
||||
|
||||
module.exports = function ({pkg, options, env}) {
|
||||
let errors = []
|
||||
|
||||
if (!pkg.name) {
|
||||
errors.push(new SemanticReleaseError(
|
||||
'No "name" found in package.json.',
|
||||
'ENOPKGNAME'
|
||||
))
|
||||
}
|
||||
|
||||
if (!pkg.repository || !pkg.repository.url) {
|
||||
errors.push(new SemanticReleaseError(
|
||||
'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
|
||||
|
||||
if (!options.githubToken) {
|
||||
errors.push(new SemanticReleaseError(
|
||||
'No github token specified.',
|
||||
'ENOGHTOKEN'
|
||||
))
|
||||
}
|
||||
|
||||
if (!(env.NPM_TOKEN || (env.NPM_OLD_TOKEN && env.NPM_EMAIL))) {
|
||||
errors.push(new SemanticReleaseError(
|
||||
'No npm token specified.',
|
||||
'ENONPMTOKEN'
|
||||
))
|
||||
}
|
||||
|
||||
return errors
|
||||
}
|
||||
+38
-34
@@ -1,51 +1,55 @@
|
||||
const url = require('url')
|
||||
'use strict'
|
||||
|
||||
const gitHead = require('git-head')
|
||||
const GitHubApi = require('github')
|
||||
const parseSlug = require('parse-github-repo-url')
|
||||
var exec = require('child_process').exec
|
||||
var readFile = require('fs').readFileSync
|
||||
var url = require('url')
|
||||
|
||||
module.exports = function (config, cb) {
|
||||
const { pkg, options, plugins } = config
|
||||
const ghConfig = options.githubUrl ? url.parse(options.githubUrl) : {}
|
||||
var changelog = require('conventional-changelog')
|
||||
var GitHubApi = require('github')
|
||||
var parseSlug = require('parse-github-repo-url')
|
||||
var parseUrl = require('github-url-from-git')
|
||||
|
||||
const github = new GitHubApi({
|
||||
var efh = require('../lib/error').efh
|
||||
|
||||
module.exports = function (options, cb) {
|
||||
var pkg = JSON.parse(readFile('./package.json'))
|
||||
var repository = pkg.repository ? pkg.repository.url : null
|
||||
|
||||
if (!repository) return cb(new Error('Package must have a repository'))
|
||||
|
||||
var config = options['github-url'] ? url.parse(options['github-url']) : {}
|
||||
|
||||
var github = new GitHubApi({
|
||||
version: '3.0.0',
|
||||
port: ghConfig.port,
|
||||
protocol: (ghConfig.protocol || '').split(':')[0] || null,
|
||||
host: ghConfig.hostname
|
||||
port: config.port,
|
||||
protocol: (config.protocol || '').split(':')[0] || null,
|
||||
host: config.hostname
|
||||
})
|
||||
|
||||
plugins.generateNotes(config, (err, log) => {
|
||||
if (err) return cb(err)
|
||||
|
||||
gitHead((err, hash) => {
|
||||
if (err) return cb(err)
|
||||
|
||||
const ghRepo = parseSlug(pkg.repository.url)
|
||||
const release = {
|
||||
changelog({
|
||||
version: pkg.version,
|
||||
repository: parseUrl(repository),
|
||||
file: false
|
||||
}, efh(cb)(function (log) {
|
||||
exec('git rev-parse HEAD', efh(cb)(function (hash) {
|
||||
var ghRepo = parseSlug(repository)
|
||||
var release = {
|
||||
owner: ghRepo[0],
|
||||
repo: ghRepo[1],
|
||||
name: `v${pkg.version}`,
|
||||
tag_name: `v${pkg.version}`,
|
||||
tag_name: 'v' + pkg.version,
|
||||
target_commitish: hash,
|
||||
draft: !!options.debug,
|
||||
draft: options.debug,
|
||||
body: log
|
||||
}
|
||||
|
||||
if (options.debug && !options.githubToken) {
|
||||
return cb(null, false, release)
|
||||
}
|
||||
|
||||
github.authenticate({
|
||||
type: 'oauth',
|
||||
token: options.githubToken
|
||||
token: options.token
|
||||
})
|
||||
|
||||
github.releases.createRelease(release, (err) => {
|
||||
if (err) return cb(err)
|
||||
|
||||
cb(null, true, release)
|
||||
})
|
||||
})
|
||||
})
|
||||
github.releases.createRelease(release, efh(cb)(function () {
|
||||
cb(null, true)
|
||||
}))
|
||||
}))
|
||||
}))
|
||||
}
|
||||
|
||||
+19
-40
@@ -1,45 +1,24 @@
|
||||
const _ = require('lodash')
|
||||
const auto = require('run-auto')
|
||||
const semver = require('semver')
|
||||
'use strict'
|
||||
|
||||
const getLastRelease = require('./lib/last-release')
|
||||
const getCommits = require('./lib/commits')
|
||||
const getType = require('./lib/type')
|
||||
var fs = require('fs')
|
||||
|
||||
module.exports = function (config, cb) {
|
||||
const {plugins} = config
|
||||
auto({
|
||||
lastRelease: getLastRelease.bind(null, config),
|
||||
commits: ['lastRelease', (cb, results) => {
|
||||
getCommits(_.assign({
|
||||
lastRelease: results.lastRelease
|
||||
}, config),
|
||||
cb)
|
||||
}],
|
||||
type: ['commits', 'lastRelease', (cb, results) => {
|
||||
getType(_.assign({
|
||||
commits: results.commits,
|
||||
lastRelease: results.lastRelease
|
||||
}, config),
|
||||
cb)
|
||||
}]
|
||||
}, (err, results) => {
|
||||
if (err) return cb(err)
|
||||
var semver = require('semver')
|
||||
|
||||
const nextRelease = {
|
||||
type: results.type,
|
||||
version: results.type === 'initial' ?
|
||||
'1.0.0' :
|
||||
semver.inc(results.lastRelease.version, results.type)
|
||||
}
|
||||
var type = require('../lib/type')
|
||||
var version = require('../lib/version')
|
||||
var efh = require('../lib/error').efh
|
||||
|
||||
plugins.verifyRelease(_.assign({
|
||||
commits: results.commits,
|
||||
lastRelease: results.lastRelease,
|
||||
nextRelease
|
||||
}, config), (err) => {
|
||||
if (err) return cb(err)
|
||||
cb(null, nextRelease)
|
||||
})
|
||||
})
|
||||
module.exports = function (options, cb) {
|
||||
type(efh(cb)(function (type) {
|
||||
if (!type) return cb(null, null)
|
||||
|
||||
var path = './package.json'
|
||||
var pkg = JSON.parse(fs.readFileSync(path))
|
||||
version(pkg, efh(cb)(function (version, unpublished) {
|
||||
pkg.version = unpublished ? '1.0.0' : semver.inc(version, type)
|
||||
if (!options.debug) fs.writeFileSync(path, JSON.stringify(pkg, null, 2))
|
||||
|
||||
cb(null, pkg.version)
|
||||
}))
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
'use strict'
|
||||
|
||||
var spawn = require('child_process').spawn
|
||||
|
||||
var 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)
|
||||
|
||||
child.stdout.pipe(process.stdout)
|
||||
child.stderr.pipe(process.stderr)
|
||||
|
||||
child.on('close', handler)
|
||||
child.on('exit', handler)
|
||||
child.on('error', cb)
|
||||
}
|
||||
|
||||
exports.handleCloseAndExit = function (cb, code, signal) {
|
||||
if (code === 0) return cb(null)
|
||||
cb({
|
||||
code: code,
|
||||
signal: signal,
|
||||
message: 'npm publish failed'
|
||||
})
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
const nixt = require('nixt')
|
||||
|
||||
module.exports = function (cwd, uri) {
|
||||
return nixt()
|
||||
.cwd(cwd)
|
||||
.env('NPM_OLD_TOKEN', 'aW50ZWdyYXRpb246c3VjaHNlY3VyZQ==')
|
||||
.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()
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
const { exec } = require('child_process')
|
||||
const { join } = require('path')
|
||||
const { writeFileSync } = require('fs')
|
||||
|
||||
const mkdirp = require('mkdirp')
|
||||
|
||||
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,
|
||||
repository: {
|
||||
url: 'git+https://github.com/semantic-release/test'
|
||||
},
|
||||
_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}, (err, stdout, stderr) => {
|
||||
if (err) {
|
||||
console.log(stdout, stderr)
|
||||
return cb(err)
|
||||
}
|
||||
|
||||
cb(null, cwd)
|
||||
})
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
const rawCommits = [
|
||||
'hash-one==SPLIT==commit-one==END==\n',
|
||||
'hash-two==SPLIT==commit-two==END==\n'
|
||||
]
|
||||
|
||||
module.exports = {
|
||||
exec: (command, cb) => {
|
||||
cb(
|
||||
null,
|
||||
/\.\.HEAD/.test(command) ?
|
||||
rawCommits[0] :
|
||||
rawCommits.join()
|
||||
)
|
||||
},
|
||||
'@noCallThru': true
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
module.exports = function (cb) {
|
||||
cb(null, 'bar')
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
module.exports = () => ({
|
||||
authenticate: () => true,
|
||||
releases: {
|
||||
createRelease: (release, cb) => cb(null)
|
||||
}
|
||||
})
|
||||
@@ -1,28 +0,0 @@
|
||||
const nock = require('nock')
|
||||
|
||||
const availableModule = {
|
||||
'dist-tags': {
|
||||
latest: '1.33.7',
|
||||
foo: '0.8.15'
|
||||
},
|
||||
versions: {
|
||||
'0.8.15': {
|
||||
gitHead: 'bar'
|
||||
},
|
||||
'1.33.7': {
|
||||
gitHead: 'HEAD'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = nock('http://registry.npmjs.org')
|
||||
.get('/available')
|
||||
.reply(200, availableModule)
|
||||
.get('/tagged')
|
||||
.reply(200, availableModule)
|
||||
.get('/untagged')
|
||||
.reply(200, availableModule)
|
||||
.get('/@scoped/available')
|
||||
.reply(200, availableModule)
|
||||
.get('/unavailable')
|
||||
.reply(404, {})
|
||||
@@ -1,12 +0,0 @@
|
||||
const { exec } = require('child_process')
|
||||
const { join } = require('path')
|
||||
|
||||
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:15986/registry/_design/app/_rewrite/'
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
[couchdb]
|
||||
database_dir = data
|
||||
view_index_dir = data
|
||||
delayed_commits = false
|
||||
|
||||
[couch_httpd_auth]
|
||||
public_fields = appdotnet, avatar, avatarMedium, avatarLarge, date, email, fields, freenode, fullname, github, homepage, name, roles, twitter, type, _id, _rev
|
||||
users_db_public = true
|
||||
|
||||
[httpd]
|
||||
port = 15986
|
||||
bind_address = 127.0.0.1
|
||||
secure_rewrites = false
|
||||
|
||||
[log]
|
||||
file = couch/couch.log
|
||||
|
||||
[admins]
|
||||
admin = -pbkdf2-89582b49cd2e8443e29a841f5a76d367956a8e58,1afa2f1531a17ac97f2ac9e334293753,10
|
||||
@@ -1,36 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# exit if an error occurs
|
||||
set -e
|
||||
|
||||
cd $(dirname $0)
|
||||
|
||||
mkdir -p couch
|
||||
|
||||
# start couchdb as a background process, load local config, specify writable logfiles
|
||||
if [[ $TRAVIS = true ]]
|
||||
then
|
||||
echo 'starting couch with sudo'
|
||||
sudo couchdb -b -a local.ini -p couch/pid -o couch/stdout.log -e couch/stderr.log
|
||||
else
|
||||
couchdb -b -a local.ini -p couch/pid -o couch/stdout.log -e couch/stderr.log
|
||||
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"}'
|
||||
|
||||
# npm-registry-couchpp needs this variable set to run
|
||||
export DEPLOY_VERSION=nope
|
||||
|
||||
# setup npm-registry-couchapp
|
||||
npm explore npm-registry-couchapp -- npm start --npm-registry-couchapp:couch=$COUCH/registry
|
||||
npm explore npm-registry-couchapp -- npm run load --npm-registry-couchapp:couch=$COUCH/registry
|
||||
npm explore npm-registry-couchapp -- NO_PROMPT=yes npm run copy --npm-registry-couchapp:couch=$COUCH/registry
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# close couchdb background process
|
||||
couchdb -d
|
||||
|
||||
# delete data and logs
|
||||
cd $(dirname $0)
|
||||
|
||||
cat couch/{couch,stdout,stderr}.log
|
||||
|
||||
rm -rf couch
|
||||
rm -rf data
|
||||
@@ -1,98 +0,0 @@
|
||||
const { join } = require('path')
|
||||
|
||||
const { test, tearDown } = require('tap')
|
||||
const rimraf = require('rimraf')
|
||||
|
||||
const registry = require('../registry')
|
||||
const testModule = require('../lib/test-module')
|
||||
const baseScenario = require('../lib/base-scenario')
|
||||
|
||||
test('change version', (t) => {
|
||||
t.plan(7)
|
||||
|
||||
registry.start((err) => {
|
||||
t.error(err, 'registry started')
|
||||
if (err) {
|
||||
t.end()
|
||||
t.bailout('registry not started')
|
||||
}
|
||||
|
||||
testModule('change-version', (err, cwd) => {
|
||||
t.error(err, 'test-module created')
|
||||
if (err) {
|
||||
t.end()
|
||||
t.bailout('test-module not created')
|
||||
}
|
||||
|
||||
t.test('no version', (tt) => {
|
||||
tt.plan(1)
|
||||
|
||||
baseScenario(cwd, registry.uri)
|
||||
.env('npm_config_loglevel', 'info')
|
||||
.run('node ../../../bin/semantic-release.js pre')
|
||||
.stderr(/ENOCHANGE/)
|
||||
.code(1)
|
||||
.end(tt.error)
|
||||
})
|
||||
|
||||
t.test('initial version', (tt) => {
|
||||
tt.plan(1)
|
||||
|
||||
baseScenario(cwd, registry.uri)
|
||||
.exec('git commit -m "feat: initial" --allow-empty')
|
||||
.exec('node ../../../bin/semantic-release.js pre')
|
||||
.run('npm publish')
|
||||
.stdout(/1\.0\.0/)
|
||||
.code(0)
|
||||
.end(tt.error)
|
||||
})
|
||||
|
||||
t.test('patch version', (tt) => {
|
||||
tt.plan(1)
|
||||
|
||||
baseScenario(cwd, registry.uri)
|
||||
.exec('git commit -m "fix: foo" --allow-empty')
|
||||
.exec('node ../../../bin/semantic-release.js pre')
|
||||
.run('npm publish')
|
||||
.stdout(/1\.0\.1/)
|
||||
.code(0)
|
||||
.end(tt.error)
|
||||
})
|
||||
|
||||
t.test('feature version', (tt) => {
|
||||
tt.plan(1)
|
||||
|
||||
baseScenario(cwd, registry.uri)
|
||||
.exec('git commit -m "feat: foo" --allow-empty')
|
||||
.exec('node ../../../bin/semantic-release.js pre')
|
||||
.run('npm publish')
|
||||
.code(0)
|
||||
.stdout(/1\.1\.0/)
|
||||
.end(tt.error)
|
||||
})
|
||||
|
||||
t.test('breaking version', (tt) => {
|
||||
tt.plan(1)
|
||||
|
||||
baseScenario(cwd, registry.uri)
|
||||
.exec('git commit -m "feat: foo\n\n BREAKING CHANGE: bar" --allow-empty')
|
||||
.exec('node ../../../bin/semantic-release.js pre')
|
||||
.run('npm publish')
|
||||
.code(0)
|
||||
.stdout(/2\.0\.0/)
|
||||
.end(tt.error)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tearDown(() => {
|
||||
function cb (err, stdout, stderr) {
|
||||
if (err) console.log(err)
|
||||
if (stdout) console.log(stdout)
|
||||
if (stderr) console.log(stderr)
|
||||
}
|
||||
|
||||
rimraf(join(__dirname, '../tmp'), cb)
|
||||
registry.stop(cb)
|
||||
})
|
||||
@@ -1,32 +0,0 @@
|
||||
const test = require('tap').test
|
||||
const proxyquire = require('proxyquire')
|
||||
|
||||
const commits = proxyquire('../../dist/lib/commits', {
|
||||
'child_process': require('../mocks/child-process')
|
||||
})
|
||||
|
||||
test('commits since last release', (t) => {
|
||||
t.test('get all commits', (tt) => {
|
||||
commits({lastRelease: {}}, (err, commits) => {
|
||||
tt.error(err)
|
||||
tt.is(commits.length, 2, 'all commits')
|
||||
tt.is(commits[0].hash, 'hash-one', 'parsed hash')
|
||||
tt.is(commits[1].message, 'commit-two', 'parsed message')
|
||||
|
||||
tt.end()
|
||||
})
|
||||
})
|
||||
|
||||
t.test('get commits since hash', (tt) => {
|
||||
commits({lastRelease: {gitHead: 'hash'}}, (err, commits) => {
|
||||
tt.error(err)
|
||||
tt.is(commits.length, 1, 'specified commits')
|
||||
tt.is(commits[0].hash, 'hash-one', 'parsed hash')
|
||||
tt.is(commits[0].message, 'commit-one', 'parsed message')
|
||||
|
||||
tt.end()
|
||||
})
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
@@ -1,79 +0,0 @@
|
||||
const { defaults } = require('lodash')
|
||||
const test = require('tap').test
|
||||
|
||||
require('../mocks/registry')
|
||||
const lastRelease = require('../../dist/lib/last-release')
|
||||
|
||||
const npm = {
|
||||
registry: 'http://registry.npmjs.org/',
|
||||
tag: 'latest'
|
||||
}
|
||||
|
||||
test('last release from registry', (t) => {
|
||||
t.plan(5)
|
||||
|
||||
t.test('get release from package name', (tt) => {
|
||||
lastRelease({
|
||||
pkg: {name: 'available'},
|
||||
npm
|
||||
}, (err, release) => {
|
||||
tt.error(err)
|
||||
tt.is(release.version, '1.33.7', 'version')
|
||||
tt.is(release.gitHead, 'HEAD', 'gitHead')
|
||||
tt.is(release.tag, 'latest', 'dist-tag')
|
||||
|
||||
tt.end()
|
||||
})
|
||||
})
|
||||
|
||||
t.test('get release from a tagged package\'s name', (tt) => {
|
||||
lastRelease({
|
||||
pkg: {name: 'tagged'},
|
||||
npm: defaults({tag: 'foo'}, npm)
|
||||
}, (err, release) => {
|
||||
tt.error(err)
|
||||
tt.is(release.version, '0.8.15', 'version')
|
||||
tt.is(release.gitHead, 'bar', 'gitHead')
|
||||
tt.is(release.tag, 'foo', 'dist-tag')
|
||||
|
||||
tt.end()
|
||||
})
|
||||
})
|
||||
|
||||
t.test('get error from an untagged package\'s name', (tt) => {
|
||||
lastRelease({
|
||||
pkg: {name: 'untagged'},
|
||||
npm: defaults({tag: 'bar'}, npm)
|
||||
}, (err) => {
|
||||
tt.is(err.code, 'ENODISTTAG', 'error')
|
||||
|
||||
tt.end()
|
||||
})
|
||||
})
|
||||
|
||||
t.test('get release from scoped package name', (tt) => {
|
||||
lastRelease({
|
||||
pkg: {name: '@scoped/available'},
|
||||
npm
|
||||
}, (err, release) => {
|
||||
tt.error(err)
|
||||
tt.is(release.version, '1.33.7', 'version')
|
||||
tt.is(release.gitHead, 'HEAD', 'gitHead')
|
||||
tt.is(release.tag, 'latest', 'dist-tag')
|
||||
|
||||
tt.end()
|
||||
})
|
||||
})
|
||||
|
||||
t.test('get nothing from not yet published package name', (tt) => {
|
||||
lastRelease({
|
||||
pkg: {name: 'unavailable'},
|
||||
npm
|
||||
}, (err, release) => {
|
||||
tt.error(err)
|
||||
tt.is(release.version, undefined, 'no version')
|
||||
|
||||
tt.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,43 +0,0 @@
|
||||
const test = require('tap').test
|
||||
|
||||
const plugins = require('../../dist/lib/plugins')
|
||||
|
||||
test('export plugins', (t) => {
|
||||
t.plan(4)
|
||||
|
||||
const defaultPlugins = plugins({})
|
||||
|
||||
t.is(typeof defaultPlugins.analyzeCommits, 'function')
|
||||
t.is(typeof defaultPlugins.generateNotes, 'function')
|
||||
t.is(typeof defaultPlugins.verifyConditions, 'function')
|
||||
t.is(typeof defaultPlugins.verifyRelease, 'function')
|
||||
})
|
||||
|
||||
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', (tt) => {
|
||||
const plugin = plugins.normalize({
|
||||
path: './dist/lib/plugin-noop'
|
||||
})
|
||||
|
||||
tt.is(typeof plugin, 'function')
|
||||
|
||||
tt.end()
|
||||
})
|
||||
|
||||
t.test('load from object', (tt) => {
|
||||
const plugin = plugins.normalize(null, '../../dist/lib/plugin-noop')
|
||||
|
||||
tt.is(typeof plugin, 'function')
|
||||
|
||||
tt.end()
|
||||
})
|
||||
})
|
||||
@@ -1,68 +0,0 @@
|
||||
const { defaults } = require('lodash')
|
||||
const test = require('tap').test
|
||||
const proxyquire = require('proxyquire')
|
||||
|
||||
const post = proxyquire('../../dist/post', {
|
||||
'git-head': require('../mocks/git-head'),
|
||||
github: require('../mocks/github')
|
||||
})
|
||||
|
||||
const pkg = {
|
||||
version: '1.0.0',
|
||||
repository: {url: 'http://github.com/whats/up.git'}
|
||||
}
|
||||
|
||||
const plugins = {generateNotes: (pkg, cb) => cb(null, 'the log')}
|
||||
|
||||
const defaultRelease = {
|
||||
owner: 'whats',
|
||||
repo: 'up',
|
||||
name: 'v1.0.0',
|
||||
tag_name: 'v1.0.0',
|
||||
target_commitish: 'bar',
|
||||
body: 'the log'
|
||||
}
|
||||
|
||||
test('full post run', (t) => {
|
||||
t.test('in debug mode w/o token', (tt) => {
|
||||
post({
|
||||
options: {debug: true},
|
||||
pkg,
|
||||
plugins
|
||||
}, (err, published, release) => {
|
||||
tt.error(err)
|
||||
tt.is(published, false)
|
||||
tt.match(release, defaults({draft: true}, defaultRelease))
|
||||
|
||||
tt.end()
|
||||
})
|
||||
})
|
||||
|
||||
t.test('in debug mode w/token', (tt) => {
|
||||
post({
|
||||
options: {debug: true, githubToken: 'yo'},
|
||||
pkg,
|
||||
plugins
|
||||
}, (err, published, release) => {
|
||||
tt.error(err)
|
||||
tt.is(published, true)
|
||||
tt.match(release, defaults({draft: true}, defaultRelease))
|
||||
|
||||
tt.end()
|
||||
})
|
||||
})
|
||||
|
||||
t.test('production', (tt) => {
|
||||
post({
|
||||
options: {githubToken: 'yo'},
|
||||
pkg,
|
||||
plugins
|
||||
}, (err, published, release) => {
|
||||
tt.error(err)
|
||||
tt.is(published, true)
|
||||
tt.match(release, defaultRelease)
|
||||
|
||||
tt.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,50 +0,0 @@
|
||||
const test = require('tap').test
|
||||
const proxyquire = require('proxyquire')
|
||||
|
||||
require('../mocks/registry')
|
||||
const pre = proxyquire('../../dist/pre', {
|
||||
'child_process': require('../mocks/child-process')
|
||||
})
|
||||
|
||||
const plugins = {
|
||||
verifyRelease: (release, cb) => cb(null, release),
|
||||
analyzeCommits: (commits, cb) => cb(null, 'major')
|
||||
}
|
||||
|
||||
const npm = {
|
||||
registry: 'http://registry.npmjs.org/',
|
||||
tag: 'latest'
|
||||
|
||||
}
|
||||
|
||||
test('full pre run', (t) => {
|
||||
t.test('increase version', (tt) => {
|
||||
tt.plan(3)
|
||||
|
||||
pre({
|
||||
npm,
|
||||
pkg: {name: 'available'},
|
||||
plugins
|
||||
}, (err, release) => {
|
||||
tt.error(err)
|
||||
tt.is(release.type, 'major')
|
||||
tt.is(release.version, '2.0.0')
|
||||
})
|
||||
})
|
||||
|
||||
t.test('increase version', (tt) => {
|
||||
tt.plan(3)
|
||||
|
||||
pre({
|
||||
npm,
|
||||
pkg: {name: 'unavailable'},
|
||||
plugins
|
||||
}, (err, release) => {
|
||||
tt.error(err)
|
||||
tt.is(release.type, 'initial')
|
||||
tt.is(release.version, '1.0.0')
|
||||
})
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
@@ -1,48 +0,0 @@
|
||||
const test = require('tap').test
|
||||
|
||||
const type = require('../../dist/lib/type')
|
||||
|
||||
test('get type from commits', (t) => {
|
||||
t.test('get type from plugin', (tt) => {
|
||||
tt.plan(2)
|
||||
|
||||
type({
|
||||
commits: [{
|
||||
hash: '0',
|
||||
message: 'a'
|
||||
}],
|
||||
lastRelease: {version: '1.0.0'},
|
||||
plugins: {analyzeCommits: (config, cb) => cb(null, 'major')}
|
||||
}, (err, type) => {
|
||||
tt.error(err)
|
||||
tt.is(type, 'major')
|
||||
})
|
||||
})
|
||||
|
||||
t.test('error when no changes', (tt) => {
|
||||
tt.plan(1)
|
||||
|
||||
type({
|
||||
commits: [],
|
||||
lastRelease: {},
|
||||
plugins: {analyzeCommits: (config, cb) => cb(null, null)}
|
||||
}, (err) => {
|
||||
tt.is(err.code, 'ENOCHANGE')
|
||||
})
|
||||
})
|
||||
|
||||
t.test('initial version', (tt) => {
|
||||
tt.plan(2)
|
||||
|
||||
type({
|
||||
commits: [],
|
||||
lastRelease: {},
|
||||
plugins: {analyzeCommits: (config, cb) => cb(null, 'major')}
|
||||
}, (err, type) => {
|
||||
tt.error(err)
|
||||
tt.is(type, 'initial')
|
||||
})
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
@@ -1,68 +0,0 @@
|
||||
const test = require('tap').test
|
||||
|
||||
const verify = require('../../dist/lib/verify')
|
||||
|
||||
test('verify pkg, options and env', (t) => {
|
||||
t.test('dry run verification', (tt) => {
|
||||
const noErrors = verify({
|
||||
options: {debug: true},
|
||||
pkg: {
|
||||
name: 'package',
|
||||
repository: {
|
||||
url: 'http://github.com/whats/up.git'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
tt.is(noErrors.length, 0)
|
||||
|
||||
const errors = verify({
|
||||
options: {debug: true},
|
||||
pkg: {}
|
||||
})
|
||||
|
||||
tt.is(errors.length, 2)
|
||||
tt.is(errors[0].code, 'ENOPKGNAME')
|
||||
tt.is(errors[1].code, 'ENOPKGREPO')
|
||||
|
||||
const errors2 = verify({
|
||||
options: {debug: true},
|
||||
pkg: {
|
||||
name: 'package',
|
||||
repository: {
|
||||
url: 'lol'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
tt.is(errors2.length, 1)
|
||||
tt.is(errors2[0].code, 'EMALFORMEDPKGREPO')
|
||||
|
||||
tt.end()
|
||||
})
|
||||
|
||||
t.test('publish verification', (tt) => {
|
||||
const noErrors = verify({
|
||||
env: {NPM_TOKEN: 'yo'},
|
||||
options: {githubToken: 'sup'},
|
||||
pkg: {
|
||||
name: 'package',
|
||||
repository: {
|
||||
url: 'http://github.com/whats/up.git'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
tt.is(noErrors.length, 0)
|
||||
|
||||
const errors = verify({env: {}, options: {}, pkg: {}})
|
||||
|
||||
tt.is(errors.length, 4)
|
||||
tt.is(errors[0].code, 'ENOPKGNAME')
|
||||
tt.is(errors[1].code, 'ENOPKGREPO')
|
||||
tt.is(errors[2].code, 'ENOGHTOKEN')
|
||||
tt.is(errors[3].code, 'ENONPMTOKEN')
|
||||
|
||||
tt.end()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1 @@
|
||||
test:{SHA}C+7Hteo/D9vJXQ3UfzxbwnXaijM=
|
||||
@@ -0,0 +1,3 @@
|
||||
_auth=dGVzdDpmb28=
|
||||
email=test@example.com
|
||||
registry=http://127.0.0.1:4873/
|
||||
@@ -0,0 +1,17 @@
|
||||
storage: ../.tmp/.storage
|
||||
|
||||
auth:
|
||||
htpasswd:
|
||||
file: ./.htpasswd
|
||||
|
||||
uplinks:
|
||||
npmjs:
|
||||
url: https://registry.npmjs.org/
|
||||
|
||||
logs:
|
||||
- {type: stdout, format: pretty, level: silent}
|
||||
|
||||
packages:
|
||||
'*':
|
||||
allow_access: all
|
||||
allow_publish: all
|
||||
@@ -0,0 +1,10 @@
|
||||
'use strict'
|
||||
|
||||
var test = require('tape')
|
||||
|
||||
var createModule = require('./lib/create-module')
|
||||
|
||||
require('./scenarios/install')(test, createModule)
|
||||
require('./scenarios/prepublish')(test, createModule)
|
||||
require('./scenarios/postpublish')(test, createModule)
|
||||
require('./scenarios/publish')(test, createModule)
|
||||
@@ -0,0 +1,45 @@
|
||||
'use strict'
|
||||
|
||||
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')()
|
||||
|
||||
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 : {}), {
|
||||
name: id,
|
||||
version: '0.0.0',
|
||||
devDependencies: {
|
||||
'semantic-release': 'file:../../../'
|
||||
},
|
||||
scripts: {
|
||||
prepublish: 'semantic-release pre',
|
||||
postpublish: 'semantic-release post'
|
||||
},
|
||||
publishConfig: {
|
||||
registry: 'http://localhost:4873/'
|
||||
}
|
||||
})
|
||||
|
||||
id = pkg.name
|
||||
var 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) {
|
||||
cb(null, id, cwd)
|
||||
}))
|
||||
}))
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
'use strict'
|
||||
|
||||
var fs = require('fs')
|
||||
|
||||
var efh = require('error-first-handler')
|
||||
var nixt = require('nixt')
|
||||
|
||||
module.exports = function (test, createModule) {
|
||||
createModule(efh()(function (name, cwd) {
|
||||
test('install', function (t) {
|
||||
installTest(t, 'npm install', 'not doing anything when the module is installed')
|
||||
installTest(t, 'npm i', 'not doing anything when the module is installed with abbrevd command')
|
||||
})
|
||||
|
||||
function installTest (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')
|
||||
})
|
||||
})
|
||||
}
|
||||
}))
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
'use strict'
|
||||
|
||||
var efh = require('error-first-handler')
|
||||
var GitHubApi = require('github')
|
||||
var nixt = require('nixt')
|
||||
|
||||
var github = new GitHubApi({
|
||||
version: '3.0.0',
|
||||
port: 4343,
|
||||
protocol: 'http',
|
||||
host: '127.0.0.1'
|
||||
})
|
||||
|
||||
github.authenticate({
|
||||
type: 'oauth',
|
||||
token: '***'
|
||||
})
|
||||
|
||||
module.exports = function (test, createModule) {
|
||||
createModule({
|
||||
version: '2.0.0',
|
||||
repository: {
|
||||
type: 'git',
|
||||
url: 'http://github.com/user/repo'
|
||||
}
|
||||
}, efh()(function (name, cwd) {
|
||||
test('postpublish', function (t) {
|
||||
t.test('publish new version to github releases', function (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(cool): the next big thing"')
|
||||
.run('npm run postpublish')
|
||||
.code(0)
|
||||
.stdout(/> semantic-release post\n\nGenerating changelog from.*\nParsed/m)
|
||||
.end(function(err) {
|
||||
t.error(err, 'nixt')
|
||||
})
|
||||
})
|
||||
|
||||
t.test('correct data published', function (t) {
|
||||
t.plan(4)
|
||||
|
||||
github.releases.getRelease({ owner: 'user', repo: 'repo', id: 1}, function (err, res) {
|
||||
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:\*\* the next big thing/.test(res.body), 'body')
|
||||
})
|
||||
})
|
||||
})
|
||||
}))
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
'use strict'
|
||||
|
||||
var fs = require('fs')
|
||||
var exec = require('child_process').exec
|
||||
|
||||
var efh = require('error-first-handler')
|
||||
var nixt = require('nixt')
|
||||
|
||||
module.exports = function (test, createModule) {
|
||||
createModule(efh()(function (name, cwd) {
|
||||
test('prepublish', function (t) {
|
||||
prepublishTest(t, 'refactor: change', '0.0.0', 1, 'abort publish w/o changes')
|
||||
prepublishTest(t, 'fix: change', '1.0.0', 0, 'release 1.0.0 if unpublished')
|
||||
prepublishTest(t, 'fix: change', '1.0.1', 0, 'bump patch for fix')
|
||||
prepublishTest(t, 'feat: change', '1.1.0', 0, 'bump minor for feature')
|
||||
prepublishTest(t, 'fix: BREAKING CHANGE: change', '2.0.0', 0, 'bump major for breaking change')
|
||||
})
|
||||
|
||||
function prepublishTest (t, message, version, code, name) {
|
||||
t.test(name, function (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 + '"')
|
||||
.run('npm run prepublish')
|
||||
.code(code)
|
||||
.stdout(/> semantic-release pre\n\nDetermining new version\n/m)
|
||||
.end(function(err) {
|
||||
t.error(err, 'nixt')
|
||||
|
||||
var 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() {
|
||||
t.error(err, 'publish')
|
||||
}, 300)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}))
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
'use strict'
|
||||
|
||||
var efh = require('error-first-handler')
|
||||
var nixt = require('nixt')
|
||||
|
||||
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')
|
||||
|
||||
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)
|
||||
|
||||
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')
|
||||
})
|
||||
})
|
||||
}))
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user