Skip to content

Commit

Permalink
Merge pull request #4 from groupon/support-matrix-builds
Browse files Browse the repository at this point in the history
Support matrix builds
  • Loading branch information
jkrems committed Dec 21, 2015
2 parents 02f4b20 + a8ce7e9 commit 8fdddff
Show file tree
Hide file tree
Showing 19 changed files with 494 additions and 159 deletions.
17 changes: 12 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
language: node_js
node_js:
- "4.2"
env:
- 'DEBUG=nlm*,gofer*'
before_script:
- '0.10'
- '4.2'
before_install:
- npm install -g npm@latest-2
before_deploy:
- git config --global user.email "opensource@groupon.com"
- git config --global user.name "CI"
after_success: "./bin/nlm.js publish"
deploy:
provider: script
script: './bin/nlm.js release'
skip_cleanup: true
on:
branch: master
node: '4.2'
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
### 1.1.0

* Compatible with node v0.10 - **[@jkrems](https://github.com/jkrems)** [#3](https://github.com/groupon/nlm/pull/3)
- [`981c75c`](https://github.com/groupon/nlm/commit/981c75ca9b2f8b673c98e5e1361b1d6d38e41af3) **fix:** Support latest git's error message
- [`c843504`](https://github.com/groupon/nlm/commit/c843504beae229a2816de052ae98a77b4ce7a0cc) **feat:** Test suite passes on node 0.10
- [`321ce61`](https://github.com/groupon/nlm/commit/321ce61870b19821500a3bd53e6be57f1308debd) **test:** Set git user/email in fixtures


### 1.0.1

* fix: Reference local bin script for publish - **[@jkrems](https://github.com/jkrems)** [#2](https://github.com/groupon/nlm/pull/2)
Expand Down
47 changes: 22 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,6 @@ If you want to use `nlm` to publish, you'll have to add `NPM_TOKEN`:
travis encrypt NPM_TOKEN=your_npm_token --add env
```

Then add the following to your `.travis.yml`:

```yaml
after_success: "./node_modules/.bin/nlm publish"
```
#### DotCI

DotCI lacks native support for encrypted environment variables.
Expand Down Expand Up @@ -114,35 +108,38 @@ Parses an existing `package.json` and makes changes to support `nlm`.
1. Set `publishConfig.registry` (default: read from npm config).


### `nlm changelog`
### `nlm verify`

Preview the changelog that would be generated by the commits between the last version tag and the current `HEAD`.
If there are no unreleased commits, the output will be empty.
*Intended use: `posttest` script for matrix builds.*

Verify that the current state is valid and could be released.
Will also add license headers where they are missing.

1. Add missing license headers.
1. Verify that the checkout is clean.
1. Collect change log items and determine what kind of change it is.


### `nlm release`

*Intended use: `posttest` script.*
*Intended use: `deploy` script, or `posttest` script if not running matrix builds.*

Verify that the current state is valid and could be released.
Will also add license headers where they are missing.

1. Add missing license headers
1. Verify that the checkout is clean
1. Collect change log items and determine what kind of change it is

If this is ran as part of a CI build of the release branch (e.g. `master`),
it will create a new release based on the changes since the last version.
This includes creating and pushing a new git tag.
1. Everything `nlm verify` does.
1. If there are unreleased changes:
1. Create a new CHANGELOG entry and update `package.json#version`.
1. Commit and tag the release.
1. Push the tag and the release branch (e.g. master).
1. Create a Github release.
1. Publish the package to npm or update `dist-tag` if required.

By default `nlm release` will not do anything unless it's running on CI.
You can force a release by running `nlm release --commit`.

### `nlm publish`

*Intended use: Publish a released version.*

This is only for cases where you can't use Travis' native support
for publishing packages. It will create a temporary `.npmrc` file
and check if any npm interactions are required.
### `nlm changelog`

If it's running on CI (or started with `--commit`), it will then
proceed and actually publish to npm.
Preview the changelog that would be generated by the commits between the last version tag and the current `HEAD`.
If there are no unreleased commits, the output will be empty.
20 changes: 16 additions & 4 deletions lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@ var rc = require('rc');
var COMMANDS = {
changelog: require('./commands/changelog'),
init: require('./commands/init'),
publish: require('./commands/publish'),
release: require('./commands/release'),
verify: require('./commands/verify'),
};

var USAGE = [
'Usage: nlm init # Set up a project to use nlm',
' nlm changelog # Preview the changelog for the next release',
' nlm release # Create a release & push to github',
' nlm publish # Publish a released version to npm',
' nlm release # Create a release, push to github & npm',
' nlm verify # Check that the current state could be released',
'',
'Options:',
' -y, --yes Don\'t ask for permission. Just do it.',
Expand All @@ -75,6 +75,16 @@ var argv = rc('nlm', {

var command = COMMANDS[argv._.shift()];

function prettyPrintErrorAndExit(error) {
/* eslint no-console:0 */
if (error.body && error.statusCode) {
console.error('Response %j: %j', error.statusCode, error.body);
}
var errorMessage = error.message.split('\n').join('\n! ');
console.error('\n!\n! ' + errorMessage + '\n!\n! NOT OK');
process.exit(1);
}

if (argv.version) {
process.stdout.write(require('../package.json').version + '\n');
process.exit(0);
Expand All @@ -85,5 +95,7 @@ if (argv.version) {
var cwd = process.cwd();
var packageJsonFile = path.join(cwd, 'package.json');
var pkg = require(packageJsonFile);
command(cwd, pkg, pkg.nlm ? _.merge({}, pkg.nlm, argv) : argv);
command(cwd, pkg, pkg.nlm ? _.merge({}, pkg.nlm, argv) : argv)
.catch(prettyPrintErrorAndExit)
.done();
}
70 changes: 5 additions & 65 deletions lib/commands/release.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,13 @@ var debug = require('debug')('nlm:command:release');
var _ = require('lodash');
var semver = require('semver');

var addLicenseHeaders = require('../license');

var verifyClean = require('../git/verify-clean');
var ensureTag = require('../git/ensure-tag');

var determineReleaseInfo = require('../steps/release-info');
var tagPullRequest = require('../steps/tag-pr');
var generateChangeLog = require('../steps/changelog');
var createVersionCommit = require('../steps/version-commit');
var pushReleaseToRemote = require('../steps/push-to-remote');
var createGithubRelease = require('../steps/github-release');
var getPendingChanges = require('../steps/pending-changes');
var detectBranch = require('../steps/detect-branch');
var publishToNpm = require('../steps/publish-to-npm');

function verifyLicenseHeaders(cwd, pkg, options) {
var whitelist = options.license && options.license.files || pkg.files;
var exclude = options.license && options.license.exclude;
return addLicenseHeaders(cwd, whitelist, exclude);
}
var runVerify = require('./verify');

function bumpVersion(version, type) {
if (type === 'none') {
Expand All @@ -66,43 +54,9 @@ function bumpVersion(version, type) {
return semver.inc(version, type);
}

function getPullRequestId() {
var travisId = process.env.TRAVIS_PULL_REQUEST;
if (travisId && travisId !== 'false') {
return travisId;
}
var dotciId = process.env.DOTCI_PULL_REQUEST;
if (dotciId && dotciId !== 'false') {
return dotciId;
}
return '';
}

function release(cwd, pkg, options) {
// Not making this configurable to prevent some possible abuse
options.pr = getPullRequestId();

function ensureLastVersionTag() {
return ensureTag(cwd, 'v' + pkg.version);
}

function setReleaseType() {
/* eslint no-console:0 */
options.releaseType = determineReleaseInfo(options.commits);
console.log('[nlm] Changes are %j', options.releaseType);
}

var verifyTasks = [
ensureLastVersionTag,
getPendingChanges,
setReleaseType,
verifyLicenseHeaders,
verifyClean,
detectBranch,
tagPullRequest,
];

function setNextVersion() {
/* eslint no-console: 0 */
options.nextVersion = bumpVersion(pkg.version, options.releaseType);
console.log('[nlm] Publishing %j from %j as %j',
options.nextVersion, options.currentBranch, options.distTag);
Expand All @@ -120,10 +74,6 @@ function release(cwd, pkg, options) {
return task(cwd, pkg, options);
}

function runVerifyTasks() {
return Bluebird.each(verifyTasks, runTask);
}

function runPublishTasks() {
if (options.releaseType === 'none') {
debug('Nothing to release');
Expand All @@ -144,18 +94,8 @@ function release(cwd, pkg, options) {
return Bluebird.each(publishTasks, runTask);
}

function prettyPrintErrorAndExit(error) {
/* eslint no-console:0 */
if (error.body && error.statusCode) {
console.error('Response %j: %j', error.statusCode, error.body);
}
var errorMessage = error.message.split('\n').join('\n! ');
console.error('\n!\n! ' + errorMessage + '\n!\n! NOT OK');
process.exit(1);
}

return runVerifyTasks()
return runVerify()
.then(options.commit ? runPublishTasks : _.noop)
.catch(prettyPrintErrorAndExit);
.then(options.commit ? publishToNpm : _.noop);
}
module.exports = release;
98 changes: 98 additions & 0 deletions lib/commands/verify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Copyright (c) 2015, Groupon, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of GROUPON nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
'use strict';

var Bluebird = require('bluebird');

var addLicenseHeaders = require('../license');

var verifyClean = require('../git/verify-clean');
var ensureTag = require('../git/ensure-tag');

var determineReleaseInfo = require('../steps/release-info');
var tagPullRequest = require('../steps/tag-pr');
var getPendingChanges = require('../steps/pending-changes');
var detectBranch = require('../steps/detect-branch');

function verifyLicenseHeaders(cwd, pkg, options) {
var whitelist = options.license && options.license.files || pkg.files;
var exclude = options.license && options.license.exclude;
return addLicenseHeaders(cwd, whitelist, exclude);
}

function getPullRequestId() {
var travisId = process.env.TRAVIS_PULL_REQUEST;
if (travisId && travisId !== 'false') {
return travisId;
}
var dotciId = process.env.DOTCI_PULL_REQUEST;
if (dotciId && dotciId !== 'false') {
return dotciId;
}
return '';
}

function verify(cwd, pkg, options) {
// Not making this configurable to prevent some possible abuse
options.pr = getPullRequestId();

function ensureLastVersionTag() {
return ensureTag(cwd, 'v' + pkg.version);
}

function setReleaseType() {
/* eslint no-console:0 */
options.releaseType = determineReleaseInfo(options.commits);
console.log('[nlm] Changes are %j', options.releaseType);
}

var verifyTasks = [
ensureLastVersionTag,
getPendingChanges,
setReleaseType,
verifyLicenseHeaders,
verifyClean,
detectBranch,
tagPullRequest,
];

function runTask(task) {
return task(cwd, pkg, options);
}

function runVerifyTasks() {
return Bluebird.each(verifyTasks, runTask);
}

return runVerifyTasks();
}
module.exports = verify;
7 changes: 2 additions & 5 deletions lib/git/commits.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,11 @@
*/
'use strict';

var childProcess = require('child_process');

var Bluebird = require('bluebird');
var commitParser = require('conventional-commits-parser');
var debug = require('debug')('nlm:git:commits');
var _ = require('lodash');

var execFileAsync = Bluebird.promisify(childProcess.execFile);
var run = require('../run');

var SEPARATOR = '---nlm-split---';
var GIT_LOG_FORMAT = '--format=%H %P\n%B' + SEPARATOR;
Expand Down Expand Up @@ -103,7 +100,7 @@ function createRange(fromRevision) {
}

function getCommits(directory, fromRevision) {
return execFileAsync('git', [
return run('git', [
'log', '--reverse', '--topo-order', GIT_LOG_FORMAT,
].concat(createRange(fromRevision)), {
cwd: directory,
Expand Down
7 changes: 2 additions & 5 deletions lib/git/current-branch.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,12 @@
*/
'use strict';

var childProcess = require('child_process');

var Bluebird = require('bluebird');
var _ = require('lodash');

var execFileAsync = Bluebird.promisify(childProcess.execFile);
var run = require('../run');

function getCurrentBranch(directory) {
return execFileAsync('git', [
return run('git', [
'rev-parse', '--abbrev-ref', 'HEAD',
], {
cwd: directory,
Expand Down
Loading

0 comments on commit 8fdddff

Please sign in to comment.