Compare commits

...
88 Commits
Author SHA1 Message Date
Christoph Witzko a5dabed534 fix(pre): use raw body instead of subject 2015-05-12 08:53:38 +02:00
Christoph Witzko be9bb40dd2 refactor(pre): inline if 2015-05-12 08:53:38 +02:00
Stephan Bönnemann 4821aff69e fix(npm-info): correctly encode scoped package names
This adds support for releasing scoped packages that are public and and that have an initial version in the registry available.
More fixes needed to support yet unpublished/private scoped modules.
2015-05-12 00:06:03 +02:00
Stephan Bönnemann 773ecf693f docs(readme): document expected error closes #18 2015-05-11 23:34:35 +02:00
Stephan Bönnemann f2dd66f614 chore(travis): test on iojs-v2 2015-05-08 00:49:11 +02:00
Lewis CowperandChristoph Witzko 3b921a63c5 docs(ci server): typo fix 2015-05-04 14:41:03 +02:00
Christoph Witzko 785e7f7b3b fix(setup): add newline at the end of package.json 2015-05-04 09:18:08 +02:00
Lewis CowperandChristoph Witzko b38f1e0687 docs(intro): grammar fix 2015-05-04 09:06:51 +02:00
Stephan Bönnemann 323b5d5bf8 feat(post): custom release note generation 2015-04-24 15:52:54 +02:00
Stephan Bönnemann 3369f31a8d test(post): custom release note generation 2015-04-24 15:52:25 +02:00
Stephan Bönnemann 63096c50c4 docs(readme): add link to release note generation 2015-04-24 15:34:57 +02:00
Stephan Bönnemann 248c41a504 test(post): account for undeclared breaking change in github package 2015-04-24 00:24:21 +02:00
Stephan Bönnemann e0eee05a7e docs(readme): shorten, clarify, add custom commit analyzer section 2015-04-23 18:12:20 +02:00
Stephan Bönnemann 08ae05fb82 test(pre): custom commit message analyzer 2015-04-22 17:52:45 +02:00
Stephan Bönnemann e445effdcf feat(pre): add option to provide own commit message analyzer 2015-04-22 17:15:10 +02:00
Stephan Bönnemann 29469e0b8a perf(npm-info): remove duplicate status code check 2015-04-22 17:06:19 +02:00
Stephan Bönnemann 615d796f24 style(error): log stack if available 2015-04-21 15:04:12 +02:00
Stephan Bönnemann 49de103753 test(bin): remove legacy check 2015-04-21 15:03:35 +02:00
Stephan Bönnemann 749eb11e58 fix(pre): not running during npm pack 2015-04-21 14:21:57 +02:00
Stephan Bönnemann 36f5555d8e test(ignore): ignore pack and link commands as well 2015-04-21 14:16:44 +02:00
Stephan Bönnemann d4f6ee0d6a chore: make test command cleanup after itself and fail early for style errors 2015-04-04 15:34:31 +02:00
Stephan Bönnemann 6763a006d2 chore(package): update tape 2015-04-03 23:01:58 +02:00
Stephan Bönnemann 0307894914 fix(package): update dependencies and adapt to their internal changes
Released as a patch, because this includes security fixes.
2015-04-03 20:37:29 +02:00
Stephan Bönnemann 06c464f9d8 chore(package): update devDependencies 2015-04-03 20:03:07 +02:00
Stephan Bönnemann f74f764a80 fix(npm-info): registry unexpectedly returned no json formatted error
This only affected publishing of yet unreleased packages.
2015-04-03 19:37:39 +02:00
Stephan Bönnemann d5a8cb1935 style: adhere to standard style 2015-03-22 10:44:19 +01:00
Stephan Bönnemann f32a8e7d03 chore(package): update standard 2015-03-22 10:44:06 +01:00
Stephan Bönnemann 30fd1c19eb Merge pull request #16 from tlvince/15-oauth-scope
docs(readme): add GitHub token scope notes
2015-03-22 10:33:50 +01:00
Tom Vincent f192acc1ff docs(readme): add GitHub token scope notes
Closes #15.
2015-03-22 00:15:43 +00:00
Stephan Bönnemann 4ccda66a39 docs(readme): fix language and formatting 2015-03-01 17:18:37 +01:00
Stephan Bönnemann c2d963be70 Merge pull request #12 from davidpfahler/master
docs(readme): fix ignore scripts flag
2015-02-22 00:08:59 +01:00
David Pfahler f8c4e495fd docs(readme): fix ignore scripts flag 2015-02-22 00:07:53 +01:00
Stephan Bönnemann c3b59d6a06 Merge pull request #10 from boennemann/githead-registry
refactor(pre): use `gitHead` information from registry
2015-02-13 09:13:13 +01:00
Christoph Witzko 53c0adb365 refactor(pre): use gitHead information from registry 2015-02-12 22:07:04 +01:00
Christoph Witzko 045c913342 chore(pretest): automatically clean up 2015-02-11 15:28:46 +01:00
Stephan Bönnemann 5c12e718cb docs(readme): clarify npm abbrevs 2015-02-10 12:31:48 +01:00
Christoph Witzko 4e32c7dde0 chore: updated git-head 2015-02-09 14:32:46 +01:00
Stephan Bönnemann 6f891ed781 Merge pull request #6 from boennemann/fix-git-node
refactor(post): use git-head instead of exec
2015-02-09 00:11:50 +01:00
Christoph Witzko e43ff5573b refactor(post): use git-head instead of exec 2015-02-09 00:08:52 +01:00
Christoph Witzko 19af8b7ef2 test(postpublish): get commit hash in detached HEAD mode 2015-02-09 00:07:11 +01:00
Stephan Bönnemann bf69c1ae93 fix(post): revert to execing git commands
`git-node` is nice in theory, but actually unstable and inconsistent.
2015-02-08 19:14:32 +01:00
Stephan Bönnemann 486ebed9f3 test(standard): ensure cli is tested by standard 2015-02-08 17:58:04 +01:00
Stephan Bönnemann 918e2c08a0 fix(cli): remove unused require call 2015-02-08 17:48:56 +01:00
Stephan Bönnemann a5e50e0d3d chore(travis): npm prune before running tests 2015-02-08 17:48:39 +01:00
Stephan Bönnemann 36f8643f3e docs(readme): add travis encrypt commands 2015-02-08 17:03:36 +01:00
Stephan Bönnemann c7862b8d0d docs(readme): update setup section 2015-02-08 17:03:36 +01:00
Stephan Bönnemann fee6d6baba feat(setup): setup package.json 2015-02-08 17:03:36 +01:00
Stephan Bönnemann 44eb633458 test(setup): setup package.json 2015-02-08 17:03:35 +01:00
Stephan Bönnemann e92bd610bb feat(verify): setup requirement verification 2015-02-08 17:03:35 +01:00
Stephan Bönnemann 5f96cd4589 test(verify): setup requirement verification 2015-02-08 14:19:22 +01:00
Stephan Bönnemann 6f7b382130 docs(readme): show only build status of master 2015-02-08 14:19:21 +01:00
Stephan Bönnemann ed39847510 docs(readme): add link to where you can get a github token 2015-02-08 14:19:21 +01:00
Stephan Bönnemann 7b170b1167 docs(readme): add synopsis of commit message conventions 2015-02-08 14:19:21 +01:00
Stephan Bönnemann c957308716 docs(readme): clarifications for ci and non-ci environments 2015-02-08 14:19:21 +01:00
Stephan Bönnemann 54fe414bab fix(cli): prepublish is executed on link; does nothing then 2015-02-08 14:19:21 +01:00
Stephan Bönnemann e0fc4840de fix(cli): automatically run in debug mode locally
BREAKING CHANGE: The `--no-ci` flag is gone. If you want to run `semantic-release` locally now you have to explicitly run `semantic-release pre --debug=false` && `semantic-release post --debug=false`
2015-02-08 14:19:21 +01:00
Stephan Bönnemann d94c6b76d3 chore(travis): actually require that all minions pass
I'm so good at bash, I'm using string concatenation for this.
2015-02-08 10:31:09 +01:00
Stephan Bönnemann be249fa0e0 chore(package): improve description and keywords 2015-02-08 10:30:35 +01:00
Stephan Bönnemann f5c6c9622a chore(package): clarify that the version is a placeholder 2015-02-08 00:40:01 +01:00
Stephan Bönnemann b309732953 docs(readme): add faq and clarify requirements 2015-02-08 00:35:55 +01:00
Stephan Bönnemann 6ef503001f docs(readme): typos, clarity and formating 2015-02-07 14:21:31 +01:00
Stephan Bönnemann 5610fafb25 chore(travis): also test on node 0.12 2015-02-07 12:26:39 +01:00
Stephan Bönnemann a4dc9c3ef9 docs(readme): verbose instructions and explanations 2015-02-07 12:21:53 +01:00
Stephan Bönnemann 466be0eb7e chore(travis): set up travis_after_all to deploy once 2015-02-05 23:49:00 +01:00
Stephan Bönnemann 7bf436fe8a chore(travis): add iojs to build matrix 2015-02-05 23:34:26 +01:00
Christoph Witzko 4ed5f73a04 chore: updated github-release-fake-server 2015-02-05 14:55:40 +01:00
Stephan Bönnemann 782c992755 Merge pull request #4 from boennemann/refactor-exec
Refactor exec
2015-02-05 13:14:42 +01:00
Christoph Witzko 5d8f6561a8 refactor: use git-node instead of exec git 2015-02-05 13:09:14 +01:00
Christoph Witzko 96fe49662a refactor: use request instead of exec curl 2015-02-05 12:39:20 +01:00
Stephan Bönnemann 875bb038a1 chore(package): change version to yet unpublished version
one last time hopefully >:(
2015-02-05 01:35:53 +01:00
Stephan Bönnemann 89f1928769 test(publish): initial scenario 2015-02-05 01:33:50 +01:00
Christoph Witzko 3799ad0cb6 test(postpublish): initial scenario 2015-02-05 01:04:52 +01:00
Christoph Witzko 7380d586ee feat(release): configure github api endpoint via environment variables 2015-02-05 01:00:42 +01:00
Christoph Witzko eb470712d7 test: added github-release-fake-server 2015-02-05 01:00:42 +01:00
Christoph Witzko f2484b8e42 test: set npm registry inside .npmrc 2015-02-04 20:18:19 +01:00
Stephan Bönnemann 73b888fdc3 docs(readme): remove usage outside of npm scripts 2015-02-04 19:02:37 +01:00
Stephan Bönnemann f44cedbaa7 text: expose correct registry to environment 2015-02-04 18:58:37 +01:00
Stephan Bönnemann a540c402a9 fix(version): use $npm_config_registry variable to ensure the right registry
BREAKING CHANGE: This breaks the usage of the `semantic-release` CLI outside of npm scripts.
2015-02-04 18:56:31 +01:00
Stephan Bönnemann ffbd39e78a test(prepublish): initial scenario 2015-02-04 15:39:05 +01:00
Stephan Bönnemann 81df21b924 test(install): initial scenario 2015-02-04 15:23:30 +01:00
Stephan Bönnemann d22b98a4ee test(create-module): helper to create fresh repo/module 2015-02-04 15:23:21 +01:00
Stephan Bönnemann c936e8be4b test: setup private npm registry w/sinopia 2015-02-04 15:23:16 +01:00
Stephan Bönnemann 019aeeabe1 refator: use error-first-handler 2015-02-03 20:45:03 +01:00
Stephan Bönnemann 19fd15c1dc refactor(cli): parse npmArgv w/minimist 2015-02-03 14:21:42 +01:00
Christoph WitzkoandStephan Bönnemann 16cf9aee9b fix(cli): hooks work correctly w/abbrevd npm commands 2015-02-03 14:09:02 +01:00
Stephan Bönnemann f2c701ca1b feat(cli): use --no-cli to publish locally w/o prompt 2015-02-02 23:30:55 +01:00
Stephan Bönnemann b39fecbdc2 fix(restart): correctly prevent double npm publish run 2015-02-02 17:57:06 +01:00
Stephan Bönnemann f7faebb175 docs(readme): fix json syntax 2015-02-02 16:33:57 +01:00
35 changed files with 1039 additions and 178 deletions
+1
View File
@@ -1,2 +1,3 @@
node_modules
*.log
.tmp
+19
View File
@@ -1,12 +1,30 @@
language: node_js
node_js:
- iojs-v2
- iojs-v1
- '0.10'
- '0.12'
sudo: false
cache:
directories:
- node_modules
notifications:
email: false
before_install:
- npm i -g npm@^2.0.0
before_script:
- npm prune
- curl -Lo travis_after_all.py https://raw.github.com/dmakhno/travis_after_all/master/travis_after_all.py
after_success:
- python travis_after_all.py
- export $(cat .to_export_back)
after_failure:
- python travis_after_all.py
- export $(cat .to_export_back)
before_deploy:
- rm -f travis_after_all.py .to_export_back
after_script:
- echo leader=$BUILD_LEADER status=$BUILD_AGGREGATE_STATUS
deploy:
provider: npm
email: stephan@boennemann.me
@@ -16,3 +34,4 @@ deploy:
on:
branch: master
repo: boennemann/semantic-release
condition: "$BUILD_LEADER$BUILD_AGGREGATE_STATUS = YESothers_succeeded"
+160 -10
View File
@@ -1,29 +1,179 @@
# semantic-release
[![Build Status](https://travis-ci.org/boennemann/semantic-release.svg)](https://travis-ci.org/boennemann/semantic-release)
[![Build Status](https://travis-ci.org/boennemann/semantic-release.svg?branch=master)](https://travis-ci.org/boennemann/semantic-release)
[![Dependency Status](https://david-dm.org/boennemann/semantic-release.svg)](https://david-dm.org/boennemann/semantic-release)
[![devDependency Status](https://david-dm.org/boennemann/semantic-release/dev-status.svg)](https://david-dm.org/boennemann/semantic-release#info=devDependencies)
[![NPM](https://nodei.co/npm/semantic-release.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/semantic-release/)
## 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.
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).
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.
![https://twitter.com/trodrigues/status/509301317467373571](https://cloud.githubusercontent.com/assets/908178/6091690/cc86f58c-aeb8-11e4-94cb-15f15f486cde.png)
## 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.
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).
### The `prepublish` step
Before `npm` actually gets to publish a new version `semantic-release`'s `prepublish` step does the following:
- Extract all commits since the last version was published
- Determine the release type (`major`|`minor`|`patch`) or abort if nothing relevant changed
- Increase the version number accordingly
### The `publish` step
`npm` does its thing.
### The `postpublish` step
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: 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 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
### Installation
First of all you need to install `semantic-release` and save it as a `devDependency`.
```bash
npm i semantic-release
npm install --save-dev semantic-release
# Btw, if you're feeling lazy you can just type this it's the same thing.
npm i -D semantic-release
```
`semantic-release` provides "prepublish" and "postpublish" hooks so you automatically release the correct version.
### Package
Run `semantic-release pre` right before `npm publish` and `semantic-release post` right after.
```bash
./node_modules/.bin/semantic-release setup
```
For maximum comfort you can automate this inside your `package.json`:
What this does:
#### Scripts
The setup command configures `scripts` inside the `package.json`:
```json
"scripts": {
"prepublish": "semantic-release pre"
"prepublish": "semantic-release pre",
"postpublish": "semantic-release post"
}
```
Note: Even though `semantic-release` works around a limitation in npm's "prepublish" hook using it prints an error that you can *safely ignore*.
See [npm/npm#7118](https://github.com/npm/npm/issues/7118).
Note: If you have already configured `scripts` for `prepublish` or `postpublish` they're just executed one after another. For example: `"npm run babelify && semantic-release pre"`.
MIT License
2015 Stephan Bönnemann
#### Version
It would be preferable not to have a version field in the `package.json` at all, but due to an `npm` limitation it is required to have a _not yet published_ version in there [npm/npm#7118](https://github.com/npm/npm/issues/7118). Because of this the version gets changed to `"0.0.0-semantically-released"` until `npm` _hopefully_ removes its limitations.
#### 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.
### CI Server
Inside your `.travis.yml`:
```yml
language: node_js
node_js:
- iojs-v1
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-access-to-your-repo>
deploy:
provider: npm
email: <your-npm-mail@example.com>
# Very important. Don't forget this one.
skip_cleanup: true
# Travis currently only supports the old auth key format.
# Do `echo -n "<username>:<password>" | base64` to get it.
# You should encrypt this:
# `travis encrypt $(echo -n "<username>:<password>" | base64) --add deploy.api_key`
api_key: <npm-api-key>
on:
branch: master
repo: <user>/<repo>
```
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: 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).
## ITYM*FAQ*LT
> I think you might frequently ask questions like these
### Why is the `package.json`'s version not updated in my repository?
The `npm` docs even state:
> The most important things in your package.json are the name and version fields. Those are actually required, and your package won't install without them.
> -- [npm docs](https://docs.npmjs.com/files/package.json#version)
While this entirely true the version number doesn't have to be checked into source control. `semantic-release` takes care of the version field right before `npm publish` uses it and this is the only point where it _really_ is required.
### Is there a way to preview which version would currently get published?
If you're running `npm publish` locally `semantic-release` automatically performs a dry run. This does log the version that would currently get published, but only if you `git fetch --tags` before.
### Can I run this on my own machine rather than on a CI server?
Of course you can, but this doesn't necessarly mean you should. Running your tests on an independent machine before releasing software is a crucial part of this workflow. Also it is a pain to set this up locally, with GitHub tokens lying around and everything. That said, you can either set the environment variable `CI=true`, or run the scripts with `--debug=false` explicitly. Don't forget to export `GH_TOKEN=your_token` as well.
### Can I manually trigger the release of a specific version?
You can trigger a release by pushing to your repository. You deliberately can not trigger a _specific_ version release, because this is the whole point of `semantic-release`. Start your packages with `1.0.0` and semver on.
Note: The default commit message conventions do not support pre-release flags, but you can build this in yourself using [custom analyzers](https://github.com/boennemann/semantic-release/wiki/commit-analysis).
### How do I get back to good ol' `npm publish`?
`npm` offers the `--ignore-scripts` flag. Doing `npm publish --ignore-scripts` doesn't execute the `prepublish` and `postpublish` scripts.
### Is it _really_ a good idea to release on every push?
It is indeed a great idea because it _forces_ you to follow best practices. If you don't feel comfortable making every passing feature or fix on your master branch addressable via `npm` you might not treat your master right. Have a look at [branch workflows](https://guides.github.com/introduction/flow/index.html). If you still think you should have control over the exact point in time of your release, e.g. because you are following a release schedule, configure your CI server to release only on the `production`/`deploy`/`release` branch and push your code there in certain intervals.
### 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.
## License
MIT License
2015 © Stephan Bönnemann and [contributors](https://github.com/boennemann/semantic-release/graphs/contributors)
-75
View File
@@ -1,75 +0,0 @@
#!/usr/bin/env node
'use strict'
var confirm = require('confirm-simple')
var argv = require('minimist')(process.argv.slice(2), {
alias: {
d: 'debug',
dry: 'debug',
t: 'token'
},
default: {
token: process.env.GH_TOKEN || process.env.TOKEN || process.env.GITHUB_TOKEN
}
})
var npmArgv = process.env.npm_config_argv
npmArgv = npmArgv ? JSON.parse(npmArgv).cooked : []
if (~argv._.indexOf('pre')) {
var publish = false
// see src/restart.js
if (~npmArgv.indexOf('--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 (~npmArgv.indexOf('install')) process.exit(0)
return confirmCI(function () {
if (~npmArgv.indexOf('publish')) publish = true
console.log('Determining new version')
require('../src/pre')(argv, function (err, result) {
if (err) {
console.log('Something went wrong.')
throw err
}
if (!result) {
console.log('Nothing changed. Not publishing.')
process.exit(1)
}
console.log('Publishing v' + result)
if (publish) require('../src/restart')()
})
})
}
if (~argv._.indexOf('post')) {
return confirmCI(function () {
require('../src/post')(argv, function (err) {
if (err) {
console.log('Something went wrong.')
throw err
}
// see src/restart.js
if (~npmArgv.indexOf('--semantic-release-rerun')) {
console.log('Everything is alright :) npm will now print an error message that you can safely ignore.')
process.exit(1)
}
})
})
}
function confirmCI (cb) {
if (process.env.CI) 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)
})
}
+87
View File
@@ -0,0 +1,87 @@
#!/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',
dry: 'debug',
t: 'token',
g: 'github-url'
},
booleans: ['debug'],
default: {
debug: !process.env.CI,
token: process.env.GH_TOKEN || process.env.TOKEN || process.env.GITHUB_TOKEN,
'github-url': process.env.GH_URL
}
})
var plugins = JSON.parse(readFile('./package.json')).release || {}
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') ||
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)))
}
Executable
+34
View File
@@ -0,0 +1,34 @@
#!/bin/bash
set -e
npm run test:style
function cleanup {
set +e
cp .tmp/.npmrc ~/.npmrc
cat .tmp/sinopia.pid | xargs kill
cat .tmp/ghrs.pid | xargs kill
rm -rf .tmp
}
trap cleanup EXIT
mkdir -p .tmp/modules
export DEBUG=ghrs:cli
./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
npm run test:integration
+32
View File
@@ -0,0 +1,32 @@
'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
}
+27
View File
@@ -0,0 +1,27 @@
'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==%B==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]
}
}))
})
)
}
+14
View File
@@ -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, err.stack)
if (err.message) return console.log(err.message)
console.log(err)
})
}
+28
View File
@@ -0,0 +1,28 @@
'use strict'
var request = require('request')
var efh = require('./error').efh
module.exports = function (pkgName, cb) {
var encodedPkgName = pkgName.replace(/\//g, '%2F')
request(process.env.npm_config_registry + encodedPkgName, 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)
}))
}
+17
View File
@@ -0,0 +1,17 @@
'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)
}
-14
View File
@@ -1,14 +0,0 @@
'use strict'
var git = require('conventional-changelog/lib/git')
module.exports = function (cb) {
git.latestTag(function (err, from) {
if (err) return cb(err)
git.getCommits({from: from}, function (err, commits) {
if (err) return cb(err)
cb(null, commits)
})
})
}
-12
View File
@@ -1,12 +0,0 @@
'use strict'
var commits = require('./commits')
var analyze = require('./analyze')
module.exports = function (cb) {
commits(function (err, commits) {
if (err) return cb(err)
cb(null, analyze(commits))
})
}
-18
View File
@@ -1,18 +0,0 @@
'use strict'
var exec = require('child_process').exec
var unlink = require('fs').unlinkSync
module.exports = function (pkg, cb) {
if (!pkg.name) return cb('Package must have a name')
exec('npm show ' + pkg.name + ' version', function(err, stdout, stderr) {
if (err) unlink('./npm-debug.log')
if (err && /is not in the npm registry/m.test(stderr)) return cb(null, null, true)
if (err) return cb(err)
cb(null, stdout.trim())
})
}
+31 -11
View File
@@ -1,26 +1,44 @@
{
"name": "semantic-release",
"description": "semantic semver compliant package publishing",
"version": "0.0.3",
"description": "automated semver compliant package publishing",
"version": "0.0.0-semantically-released",
"author": "Stephan Bönnemann <stephan@boennemann.me>",
"bin": "./bin/semantic-release",
"bin": "./bin/semantic-release.js",
"bugs": {
"url": "https://github.com/boennemann/semantic-release/issues"
},
"dependencies": {
"confirm-simple": "^1.0.3",
"conventional-changelog": "0.0.11",
"github": "^0.2.3",
"abbrev": "^1.0.5",
"conventional-changelog": "0.0.17",
"error-first-handler": "^1.0.1",
"git-head": "^1.2.1",
"github": "0.2.4",
"github-url-from-git": "^1.4.0",
"ini": "^1.3.2",
"minimist": "^1.1.0",
"parse-github-repo-url": "^1.0.0",
"semver": "^4.2.0"
"request": "^2.53.0",
"semver": "^4.3.3"
},
"devDependencies": {
"standard": "^2.3.1"
"github-release-fake-server": "^1.3.0",
"lodash.defaults": "^3.0.0",
"nano-uid": "^0.2.0",
"nixt": "^0.4.1",
"sinopia": "^1.0.0",
"standard": "^3.2.1",
"tap-spec": "^3.0.0",
"tape": "^4.0.0"
},
"engines": {
"iojs": "^1",
"node": "^0.10",
"npm": "^2"
},
"homepage": "https://github.com/boennemann/semantic-release",
"keywords": [
"author",
"automation",
"release",
"publish",
"module",
@@ -36,8 +54,10 @@
"url": "https://github.com/boennemann/semantic-release.git"
},
"scripts": {
"prepublish": "./bin/semantic-release pre",
"postpublish": "./bin/semantic-release post",
"test": "standard"
"postpublish": "./bin/semantic-release.js post",
"prepublish": "./bin/semantic-release.js pre",
"test:style": "standard",
"test:integration": "node tests | tap-spec",
"test": "./bin/test"
}
}
+20 -21
View File
@@ -1,33 +1,33 @@
'use strict'
var exec = require('child_process').exec
var readFile = require('fs').readFileSync
var url = require('url')
var changelog = require('conventional-changelog')
var gitHead = require('git-head')
var GitHubApi = require('github')
var parseSlug = require('parse-github-repo-url')
var parseUrl = require('github-url-from-git')
var github = new GitHubApi({
version: '3.0.0'
})
var efh = require('../lib/error').efh
module.exports = function (options, cb) {
module.exports = function (options, plugins, cb) {
var pkg = JSON.parse(readFile('./package.json'))
var repository = pkg.repository ? pkg.repository.url : null
if (!repository) return cb('Package must have a repository')
if (!repository) return cb(new Error('Package must have a repository'))
changelog({
version: pkg.version,
repository: parseUrl(repository),
file: false
}, function(err, log) {
if (err) return cb(err)
var notesGenerator = require(plugins.notes || '../lib/release-notes')
exec('git rev-parse HEAD', function(err, hash) {
if (err) return cb(err)
var config = options['github-url'] ? url.parse(options['github-url']) : {}
var 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 = {
owner: ghRepo[0],
@@ -43,10 +43,9 @@ module.exports = function (options, cb) {
token: options.token
})
github.releases.createRelease(release, function(err) {
if (err) return cb(err)
github.releases.createRelease(release, efh(cb)(function () {
cb(null, true)
})
})
})
}))
}))
}))
}
+16 -13
View File
@@ -4,23 +4,26 @@ var fs = require('fs')
var semver = require('semver')
var type = require('../lib/type')
var version = require('../lib/version')
var getCommits = require('../lib/commits')
var npmInfo = require('../lib/npm-info')
var efh = require('../lib/error').efh
module.exports = function (options, cb) {
type(function (err, type) {
if (err) return cb(err)
if (!type) return cb(null, null)
module.exports = function (options, plugins, cb) {
var path = './package.json'
var pkg = JSON.parse(fs.readFileSync(path))
var path = './package.json'
var pkg = JSON.parse(fs.readFileSync(path))
version(pkg, function (err, version, unpublished) {
if (err) return cb(err)
if (!pkg.name) return cb(new Error('Package must have a name'))
pkg.version = unpublished ? '1.0.0' : semver.inc(version, type)
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)
if (!type) return cb(null, null)
pkg.version = res.version ? semver.inc(res.version, type) : '1.0.0'
if (!options.debug) fs.writeFileSync(path, JSON.stringify(pkg, null, 2))
cb(null, pkg.version)
})
})
}))
}))
}
+15 -1
View File
@@ -2,7 +2,7 @@
var spawn = require('child_process').spawn
module.exports = function () {
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
@@ -10,7 +10,21 @@ module.exports = function () {
// 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'
})
}
+42
View File
@@ -0,0 +1,42 @@
'use strict'
var fs = require('fs')
var ini = require('ini')
var ghUrl = require('github-url-from-git')
module.exports = function () {
var pkg = JSON.parse(fs.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'
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
if (!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
if (repo) pkg.repository = { type: 'git', url: ghUrl(repo) }
}
// set up devDependency
if (!pkg.devDependencies) pkg.devDependencies = {}
if (!pkg.devDependencies['semantic-release']) {
pkg.devDependencies['semantic-release'] = '^' + require('../package.json').version
}
fs.writeFileSync('./package.json', JSON.stringify(pkg, null, 2) + '\n')
}
+71
View File
@@ -0,0 +1,71 @@
'use strict'
var fs = require('fs')
var exports = module.exports = function (input) {
var options = exports.verifyOptions(input)
var pkg = exports.verifyPackage()
var travis = exports.verifyTravis()
return options && pkg && travis
}
exports.verifyTravis = function () {
try {
var travis = fs.readFileSync('.travis.yml') + ''
} catch (e) {
return true
}
var passed = true
if (!/\sdeploy:/m.test(travis)) {
console.error('You should configure deployments inside the ".travis.yml".')
passed = false
}
if (!/skip_cleanup:/m.test(travis)) {
console.error('You must set "skip_cleanup" to "true" inside the ".travis.yml".')
passed = false
}
return passed
}
exports.verifyPackage = function () {
var passed = true
try {
var pkg = fs.readFileSync('./package.json') + ''
} catch (e) {
console.error('You must have a "package.json" present.')
passed = false
pkg = '{}'
}
try {
pkg = JSON.parse(pkg)
} catch (e) {
console.error('You must have a "package.json" that is valid JSON.')
return false
}
if (!pkg.repository || !pkg.repository.url) {
console.error('You must define your GitHub "repository" inside the "package.json".')
passed = false
}
if (!pkg.scripts || !pkg.scripts.prepublish || !pkg.scripts.postpublish) {
console.error('You must define your "scripts" inside the "package.json".')
passed = false
}
return passed
}
exports.verifyOptions = function (options) {
if (!options) return true
if (options.token) return true
console.error('You must define a GitHub token.')
return false
}
+1
View File
@@ -0,0 +1 @@
test:{SHA}C+7Hteo/D9vJXQ3UfzxbwnXaijM=
+3
View File
@@ -0,0 +1,3 @@
_auth=dGVzdDpmb28=
email=test@example.com
registry=http://127.0.0.1:4873/
+17
View File
@@ -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
+13
View File
@@ -0,0 +1,13 @@
'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)
+37
View File
@@ -0,0 +1,37 @@
'use strict'
var fs = require('fs')
var exec = require('child_process').exec
var nixt = require('nixt')
module.exports = function (t, message, version, code, name, cwd) {
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)
})
})
})
}
+45
View File
@@ -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)
}))
}))
}
@@ -4,14 +4,14 @@ module.exports = function (commits) {
var type = null
commits.every(function (commit) {
if (commit.breaks.length) {
if (/FOO/.test(commit.message)) {
type = 'major'
return false
}
if (commit.type === 'feat') type = 'minor'
if (/BAR/.test(commit.message)) type = 'minor'
if (!type && commit.type === 'fix') type = 'patch'
if (!type && /BAZ/.test(commit.message)) type = 'patch'
return true
})
+5
View File
@@ -0,0 +1,5 @@
'use strict'
module.exports = function (cb) {
cb(null, 'custom log')
}
+23
View File
@@ -0,0 +1,23 @@
'use strict'
var path = require('path')
var efh = require('error-first-handler')
var commitToVersionTest = require('../lib/commit-to-version-test')
module.exports = function (test, createModule) {
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)
})
}))
}
+37
View File
@@ -0,0 +1,37 @@
'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('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')
})
})
}
}))
}
+115
View File
@@ -0,0 +1,115 @@
'use strict'
var path = require('path')
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) {
var base = getBase(cwd)
t.test('publish new version to github releases', function (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')
})
})
t.test('publish new version (with detached HEAD) to github releases', function (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')
})
})
t.test('correct data published', function (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')
})
})
})
}))
createModule({
version: '2.0.0',
repository: {
type: 'git',
url: 'http://github.com/user/repo'
},
release: {
notes: path.join(__dirname, '../lib/custom-release-notes')
}
}, efh()(function (name, cwd) {
test('custom-release-notes', function (t) {
var base = getBase(cwd)
t.test('publish new version (with custom notes) to github releases', function (t) {
t.plan(1)
base.clone()
.run('npm run postpublish')
.end(function (err) {
t.error(err, 'nixt')
})
})
t.test('custom notes published', function (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')
})
})
})
}))
}
function getBase (cwd) {
return 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"')
.code(0)
}
+17
View File
@@ -0,0 +1,17 @@
'use strict'
var efh = require('error-first-handler')
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)
})
}))
}
+37
View File
@@ -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')
})
})
}))
}
})
}
+38
View File
@@ -0,0 +1,38 @@
'use strict'
var join = require('path').join
var readFile = require('fs').readFileSync
var efh = require('error-first-handler')
var nixt = require('nixt')
module.exports = function (test, createModule) {
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)
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')
var 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')
})
})
})
}))
}
+34
View File
@@ -0,0 +1,34 @@
'use strict'
var efh = require('error-first-handler')
var nixt = require('nixt')
module.exports = function (test, createModule) {
createModule({
repository: {},
scripts: {
prepublish: 'semantic-release 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')
})
})
})
}))
}