Skip to content

Commit

Permalink
Merge pull request #1 from blamattina/issue-comment-once
Browse files Browse the repository at this point in the history
Add support for issue-comment --once
  • Loading branch information
blamattina committed Oct 18, 2015
2 parents 564e4f6 + fa118cc commit 83f7ebf
Show file tree
Hide file tree
Showing 13 changed files with 414 additions and 96 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules/
npm-debug.log
.env
1 change: 1 addition & 0 deletions .node-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
4.1.1
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ npm install -g github-hotline

Usage
```
USAGE: issue-comment USER/REPO#NUMBER COMMENT...
issue-comment --user USER --repo REPO --number NUMBER COMMENT...
USAGE: issue-comment [--once] USER/REPO#NUMBER COMMENT...
issue-comment [--once] -u USER -r REPO -n NUMBER COMMENT...
Issue a comment on a pull request.
Expand All @@ -23,15 +23,28 @@ USAGE: issue-comment USER/REPO#NUMBER COMMENT...
NUMBER pull request number
COMMENT comment to leave
Options:
--once create this comment if it does not already exist
Example:
issue-comment blamattina/github-hotline#3400 This works great!
```

Example
```
# Create a comment on an issue
$ export GITHUB_USERNAME=username
$ export GITHUB_PASSWORD=personal-access-token
$ issue-comment blamattina/github-hotline#13 Looks good :zap:
Comment Created.
```
```
# Create a comment on an issue if one with the same body does not exist
$ issue-comment --once blamattina/github-hotline#1 Looks good
Comment created.
$ issue-comment --once blamattina/github-hotline#1 Looks good
Not created. A comment with this message already exists.
```
27 changes: 18 additions & 9 deletions bin/issue-comment-cli.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
#!/usr/bin/env node
var argv = require('minimist')(process.argv.slice(2)),
'use strict';
var argv = require('minimist')(process.argv.slice(2), {boolean: true}),
help = require('help')(__dirname + '/../doc/issue-comment.txt'),
debug = require('debug')('github-hotline:issue-comment-cli'),
chalk = require('chalk'),
DestinationParser = require('../lib/github-hotline/destination-parser'),
hotline = require('../');

function reportSuccess(data) {
debug('Comment Created.');
const reportSuccess = (data) => {
debug('Exiting successfully.');
debug(data);
console.log('Comment Created.');
if(typeof data == 'object' && data.meta.status == '201 Created') {
console.log('Comment Created.')
} else {
console.log(data);
}
process.exit(0);
}

function reportError(error) {
const reportError = (error) => {
debug('Uncaught exception. Exiting!');
debug(error);
console.error(chalk.red('\nERROR: ' + error.message + '\n'));
help(1);
}

function parseArgs(argv) {
const parseArgs = (argv) => {
var once = !!argv['once'];

if (argv.user && argv.repo && argv.number) {
var user = argv['user'],
repo = argv['repo'],
number = argv['number'];
var user = argv['u'],
repo = argv['r'],
number = argv['n'];
body = argv._.slice(0).join(' ');

} else if (argv._.length >= 2) {
Expand All @@ -41,6 +48,7 @@ function parseArgs(argv) {
return help(1);
}
return {
once: once,
user: user,
repo: repo,
number: number,
Expand All @@ -54,6 +62,7 @@ try {
debug('Issue comment with...');
debug(params);
hotline.createIssueComment({
once: params.once,
user: params.user,
repo: params.repo,
number: params.number,
Expand Down
3 changes: 3 additions & 0 deletions circle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
machine:
node:
version: 4.1.1
8 changes: 6 additions & 2 deletions doc/issue-comment.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
USAGE: issue-comment USER/REPO#NUMBER COMMENT...
issue-comment --user USER --repo REPO --number NUMBER COMMENT...
USAGE: issue-comment [--once] USER/REPO#NUMBER COMMENT...
issue-comment [--once] -u USER -r REPO -n NUMBER COMMENT...

Issue a comment on a pull request.

Expand All @@ -8,6 +8,10 @@ USAGE: issue-comment USER/REPO#NUMBER COMMENT...
NUMBER pull request number
COMMENT comment to leave

Options:

--once create this comment if it does not already exist

Example:

issue-comment blamattina/github-hotline#3400 This works great!
Expand Down
20 changes: 15 additions & 5 deletions lib/github-hotline/actions/create-issue-comment.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
'use strict';
var Promise = require('bluebird');
var GithubApi = require('../github/api');
var Issue = require('../github/issue');

module.exports = function createIssueComment(params) {
const ALREADY_EXISTS = 'Not created. A comment with this message already exists.';

var api = new GithubApi();

var issue = new Issue({
module.exports = (params) => {
const api = new GithubApi();
const issue = new Issue({
api: api,
user: params.user,
repo: params.repo,
number: params.number
});

return issue.createComment(params.body);
const createComment = () => issue.createComment(params.body);
const alreadyExists = () => Promise.resolve(ALREADY_EXISTS);

if(params.once) {
return issue.findComment({body: params.body})
.then(alreadyExists, createComment);
} else {
return createComment();
}
};
99 changes: 68 additions & 31 deletions lib/github-hotline/github/api.js
Original file line number Diff line number Diff line change
@@ -1,55 +1,92 @@
var _ = require('lodash');
var debug = require('debug')('pull-request-hotline:githup-api');
'use strict';
const _ = require('lodash');
const debug = require('debug')('github-hotline:github:api');
const Promise = require('bluebird');

// Rewire-able
var Github = require('github');
var Promise = require('bluebird');

var wrappedFunctions = {
createIssueComment: { module: 'issues', fn: 'createComment' }
const wrappedFunctions = {
getIssue: { module: 'issues', fn: 'getRepoIssue' },
createIssueComment: { module: 'issues', fn: 'createComment' },
getIssueCommentsAsync: { module: 'issues', fn: 'getComments' }
}

var wrapLibraryFunctionsInPromises = function(wrapped, api) {
Object.keys(wrappedFunctions).forEach(function(wrappedFn) {
wrapped[wrappedFn] = function(params) {
const wrapLibraryFunctionsInPromises = (wrapped, api) => {
Object.keys(wrappedFunctions).forEach((wrappedFn) => {
wrapped[wrappedFn] = (params) => {

debug('Calling ' + wrappedFn);
debug(params);
var wrapping = wrappedFunctions[wrappedFn];
var fnAsync = Promise.promisify(api[wrapping.module][wrapping.fn]);
return fnAsync(params);
const wrapping = wrappedFunctions[wrappedFn];
const fnAsync = Promise.promisify(api[wrapping.module][wrapping.fn]);
const promise = fnAsync(params);

promise.then(
(data) => debug('Resolving with: ', data),
(err) => debug('Failing with: ', err)
);
return promise;
}
});
}

function ensureEnvVariables() {
const ensureEnvVariables = () => {
if (!process.env.GITHUB_USERNAME && !process.env.GITHUB_ACCESS_TOKEN) {
throw new Error(
'Missing environment variables: GITHUB_USERNAME, GITHUB_ACCESS_TOKEN'
);
}
}

function GithubApi() {
debug('Creating Github API wrapper.');
ensureEnvVariables();
class GithubApi {
constructor() {
debug('Creating Github API wrapper.');
ensureEnvVariables();

var options = {
version: "3.0.0"
};

if (process.env.GITHUB_ENTERPRISE_HOSTNAME) {
options.host = process.env.GITHUB_ENTERPRISE_HOSTNAME;
options.pathPrefix = '/api/v3';
debug('Using Github Host: ' + options.host);
}

var options = {
version: "3.0.0"
};
this.api = new Github(options);
debug('Authenticating as: ' + process.env.GITHUB_USERNAME);
this.api.authenticate({
type: 'basic',
username: process.env.GITHUB_USERNAME,
password: process.env.GITHUB_ACCESS_TOKEN
});

if (process.env.GITHUB_ENTERPRISE_HOSTNAME) {
options.host = process.env.GITHUB_ENTERPRISE_HOSTNAME;
options.pathPrefix = '/api/v3';
debug('Using Github Host: ' + options.host);
wrapLibraryFunctionsInPromises(this, this.api);
}

this.api = new Github(options);
debug('Authenticating as: ' + process.env.GITHUB_USERNAME);
this.api.authenticate({
type: 'basic',
username: process.env.GITHUB_USERNAME,
password: process.env.GITHUB_ACCESS_TOKEN
});
getIssueComments(params) {
debug('Calling getIssueComments');
debug(params);
return this.getIssue(params).then((issue) => {
const perPage = 30;
var page = 0;

wrapLibraryFunctionsInPromises(this, this.api);
}
debug('Creating comment generator');
return (function* generator(issue) {
const pages = Math.ceil(issue.comments / perPage);

debug(pages + ' comment pages available');
while(page < pages) {
page++;
let pageParams = { page: page, per_page: perPage };

debug('Yeilding ' + page + ' of ' + pages);
yield this.getIssueCommentsAsync(_.assign(pageParams, params))
}
}.bind(this))(issue);
});
}
};

module.exports = GithubApi;
48 changes: 40 additions & 8 deletions lib/github-hotline/github/issue.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,51 @@
function Issue(params) {
this.api = params.api;
this.user = params.user;
this.repo = params.repo;
this.number = params.number;
}
'use strict';
var _ = require('lodash');
var debug = require('debug')('github-hotline:github:issue');

class Issue {
constructor(params) {
this.api = params.api;
this.user = params.user;
this.repo = params.repo;
this.number = params.number;
}

Issue.prototype = {
createComment: function (body) {
createComment(body) {
return this.api.createIssueComment({
user: this.user,
repo: this.repo,
number: this.number,
body: body
});
}

findComment(source) {
var commentGenerator;

const setGenerator = (generator) => commentGenerator = generator;
const hasFoundComment = (comments) => _(comments).findWhere(source);

function findCommentRecursively() {
debug('Recursively searching for comments');
const commentPromise = commentGenerator.next().value;
debug(commentPromise);
if (commentPromise) {
return commentPromise.then((comments) => {
return hasFoundComment(comments) || findCommentRecursively();
});
}
return Promise.reject('Comment not found.');
};

const issueParams = {
user: this.user,
repo: this.repo,
number: this.number
};
return this.api.getIssueComments(issueParams)
.then(setGenerator)
.then(findCommentRecursively);
}
}

module.exports = Issue;
13 changes: 11 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
{
"name": "github-hotline",
"version": "0.1.0",
"version": "0.2.0",
"description": "Simple command line utility for commenting on pull requests",
"main": "index.js",
"bin": {
"issue-comment": "./bin/issue-comment-cli.js"
},
"engines" : { "node" : ">=4.0.0" },
"scripts": {
"eslint": "eslint src/ specs/",
"eslint": "eslint ./",
"jasmine": "NODE_PATH=. jasmine",
"jasmine-debug": "NODE_PATH=. DEBUG='*' node debug node_modules/jasmine/bin/jasmine.js",
"test": "npm run eslint && npm run jasmine"
},
"repository": {
Expand Down Expand Up @@ -42,5 +44,12 @@
"jasmine": "^2.3.2",
"jasmine-core": "^2.3.4",
"rewire": "^2.3.4"
},
"eslintConfig": {
"env": {
"browser": false,
"es6": true,
"node": true
}
}
}
Loading

0 comments on commit 83f7ebf

Please sign in to comment.