Haunt helps you keep your github issues under control. It does this by allowing you to run unit tests against github issues and pull-requests, then make contextual decisions about closing, sorting, tagging, and commenting.
Haunt pulls all open issues/pull-requests from your repo and gathers a bunch of data about them from github's api. It then runs a series of tests (which you define). Each test is provided a special haunt object which contains all the issue data as well as an api to act directly on the issue.
I run Haunt occasionally against bootstrap's issues/pull requests to keep them in order and to keep the ticketing process sane. Initially haunt closed 48 of 54 pull requests and about 65+ issues. It also tagged a number of issues as popular (accomplished with a small before
filter which checks for +1 comments).
Here's a link to an actual pull request it closed. If you look at the bottom you can see that haunt made a comment explaining why the pull request was invalid, before closing it. Closing an issue of course is optional, we're just doing this in bootstrap to weed out people who file issues and never come back.
The tests I ran against bootstrap are literally the same that are in the examples dir of this repo. The only difference is i've named them .issue-guidlines.js
in bootstrap.
You can use haunt from the command line or programatically.
To use Haunt from the command line, install like so:
$ npm install haunt -g
This will give you a haunt command you can use from terminal.
$ haunt
Running haunt with no arguments will output some simple cli documentation.
Usage:
haunt <test-path> <github-path>
Flags:
--stub - (-s) stubs the github api, so that requests aren't actually made to live github data
--user - (-u u:p) specify a username and password for an account to make issue changes on behalf of
--reporter - (-r Spec) specify a mocha reporter for test output formatting. If not specified, nothing will be output.
Example:
$ haunt .issue_guidelines.js http://github.com/twitter/bootstrap
General Help:
http://git.io/haunt
To run some local tests against a remote repo, you might do something like this:
$ haunt ./path/to/my/local/tests.js http://github.com/my/repo
Note: haunt will prompt you for a username and password. Alternatively, you can specify them as an option by using the --user
or -u
flag. We use this to authenticate against the github api. All actions performed by your tests will be made on behalf of the authenticated user.
It's also worth noting that if you don't provide a local test file, haunt will look for a remote .issue-guidelines.js
file in the root of the remote repo. This might look something like:
$ haunt http://github.com/my/repo
You may want to use the programatic api to build out a service, or something which routinely runs to keep your issues under control at a more consistent interval (like a bot).
To use haunt programmatically, just do something like:
var haunt = require('haunt');
haunt.auth('user', 'pass');
haunt.repo('http://github.com/my/repo', callback);
// haunt.repo also can take an options object.
// This can contain things like:
// + stub - (boolean) stubs the github api write requests
// + tests - (object) a haunt test object
// + reporter - (object) a mocha test reporter type
haunt.repo({
repo: 'http://github.com/my/repo',
tests: myTests,
reporter: 'Landing',
stub: true
}, callback);
All haunt tests are assumed to be synchronous.
A basic haunt test file exports a single object with the two optional properties pull-request
and issue
. This looks something like this:
module.exports = {
'pull-requests' : { … },
'issues' : { … }
}
Each optional object (pull-request
and issue
) should include a series of tests to be ran against the specified issue type. In addition to the tests you may also specify a before and after property. Before will be executed before all tests are ran, after will be executed after all tests have ran. All methods are passed a single argument which contains an interface into a github issue or pull-request.
A simple issue test file might look like this:
var assert = require('assert');
module.exports = {
'issues': {
'should be prefixed with the word bug': function (issue) {
assert.ok(/^bug/.test(issue.title));
},
'after': function (issue) {
if (issue.reporter.stats.failures) {
issue.reportFailures(issue.close.bind(issue));
}
}
}
}
When testing issues, your function will be passed an object with the following properties:
When testing pull-requests, your function will be passed an object with the following properties (in addition to all properties provided to a normal issue as specified above):
Before methods will be passed an object with the same properties as an issue/pull-request.
After methods will be passed an object with the same properties as an issue/pull-request, with the addition of a mocha reporter object:
The following convenience methods are made available on all haunt objects. You can call these at any time - though I recommend you only really use them in after
methods.