diff --git a/.jscsrc b/.jscsrc
index eb0a3c4..d242367 100644
--- a/.jscsrc
+++ b/.jscsrc
@@ -1,5 +1,4 @@
{
- "additionalRules": ["rules/disallow-dot-notation-for-keywords.js"],
"fileExtensions": [".js", ".jsx"],
"disallowMixedSpacesAndTabs": true,
"disallowNewlineBeforeBlockStatements": true,
@@ -41,7 +40,7 @@
"safeContextKeyword": ["self"],
"validateIndentation": 4,
- "validateJSDoc": {
+ "jsDoc": {
"checkParamNames": true,
"checkRedundantParams": true,
"requireParamTypes": true,
diff --git a/README.md b/README.md
index 7f25071..3ef648f 100644
--- a/README.md
+++ b/README.md
@@ -8,9 +8,11 @@ A gulp plugin to pipe contents to github pull request comments.
Features
--------
-* Write collected info then comment on a github pull request.
* Collect gulp-jshint results.
* Collect gulp-jscs results.
+* Write collected info then comment on a github pull request.
+* Update github pull request status based on collected info.
+* A failThisTask() reporter to fail a gulp task when jscs/jshint issues found
* **TODO** Collect lcov result.
Installation
@@ -33,13 +35,21 @@ gulp.task('link_report_github', function () {
return gulp.src('lib/*.js')
.pipe(jshint())
.pipe(jscs()).on('error', function (E) {
- console.log(E.message); // This handled jscs stream error
+ console.log(E.message); // This handled jscs stream error.
})
- .pipe(github(options)); // comment issues in github PR!
+ .pipe(github(options)); // Comment issues in github PR!
+ .pipe(github.failThisTask()); // Fail this task when jscs/jshint issues found.
});
// Or, direct output your comment with same options
github.commentToPR('Yes! it works!!', options);
+
+// Or, direct set status to a commit
+github.createStatusToCommit({
+ description: 'No! 2 failures...',
+ context: 'my gulp task',
+ state: 'failure'
+}, options);
```
Options
@@ -81,3 +91,5 @@ Options
```
Check this sample gulpfile to see how to migrate this with travis CI.
+
+Check This PR to see live demo. Click on ✘ symbol before d9bc05e to see created status.
diff --git a/gulpfile.js b/gulpfile.js
index 1711300..a041e54 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -19,8 +19,8 @@ gulp.task('default', function () {
git_prid: process.env.TRAVIS_PULL_REQUEST,
git_sha: process.env.TRAVIS_COMMIT,
- jshint_status: 'error',
- jscs_status: 'failure',
+ jshint_status: 'error', // Set status to error when jshint errors
+ jscs_status: 'failure' // Set status to failure when jscs errors
}))
- .pipe(jshint.reporter('fail'));
+ .pipe(github.failThisTask());
});
diff --git a/index.js b/index.js
index 88c5731..97d0676 100644
--- a/index.js
+++ b/index.js
@@ -27,16 +27,25 @@ getGIT = function (opt) {
return GIT;
},
-commentToPR = function (body, opt) {
+closePR = function (opt, cb) {
+ getGIT(opt).issues.edit({
+ user: opt.git_repo.split('/')[0],
+ repo: opt.git_repo.split('/')[1],
+ number: opt.git_prid,
+ state: 'closed'
+ }, cb);
+},
+
+commentToPR = function (body, opt, cb) {
getGIT(opt).issues.createComment({
user: opt.git_repo.split('/')[0],
repo: opt.git_repo.split('/')[1],
number: opt.git_prid,
body: body
- });
+ }, cb);
},
-createStatusToCommit = function (state, opt) {
+createStatusToCommit = function (state, opt, cb) {
getGIT(opt).statuses.create({
user: opt.git_repo.split('/')[0],
repo: opt.git_repo.split('/')[1],
@@ -44,8 +53,108 @@ createStatusToCommit = function (state, opt) {
state: state.state,
description: state.description,
context: state.context
+ }, cb);
+},
+
+isPullRequest = function (opt) {
+ return opt.git_token && opt.git_repo && opt.git_prid && (opt.git_prid !== 'false');
+},
+
+isMerge = function (opt, callback) {
+ if (!isPullRequest(opt)) {
+ return;
+ }
+
+ getGIT(opt).pullRequests.getCommits({
+ user: opt.git_repo.split('/')[0],
+ repo: opt.git_repo.split('/')[1],
+ number: opt.git_prid,
+ per_page: 100
+ }, function (E, D) {
+ var merged = [];
+
+ if (E) {
+ console.warn(E);
+ return callback(E);
+ }
+
+ D.forEach(function (commit) {
+ if (commit.parents.length > 1) {
+ merged.push('* Commit: @' + commit.sha + ' is a merge from ' + commit.parents.map(function (C) {
+ return '@' + C.sha;
+ }).join(' , ') + ' !!');
+ }
+ });
+
+ callback(merged.length ? merged.join('\n') : false);
});
-}
+},
+
+failMergedPR = function (opt, cb) {
+ var count = 0;
+ var err = [];
+ var done = function (E) {
+ count++;
+ if (E) {
+ err.push(E);
+ }
+ if ((count == 3) && cb) {
+ cb(err.length ? err : undefined);
+ }
+ };
+
+ isMerge(opt, function (M) {
+ if (!M) {
+ return;
+ }
+
+ commentToPR('**Do not accept PR with merge, please use rebase always!**\n' + M, opt, done);
+
+ createStatusToCommit({
+ state: 'failure',
+ description: 'merge in PR',
+ context: 'gulp-github/is_merge'
+ }, opt, done);
+
+ closePR(opt, done);
+ });
+},
+
+failThisTask = function () {
+ var jshint_fails = 0,
+ jscs_fails = 0;
+
+ return through.obj(function (file, enc, callback) {
+ if (file.jshint && !file.jshint.success && !file.jshint.ignored) {
+ jshint_fails += file.jshint.results.length;
+ }
+
+ if (file.jscs && !file.jscs.success) {
+ jscs_fails += file.jscs.errors.length;
+ }
+ this.push(file);
+ callback();
+ }, function (cb) {
+ var message = [];
+
+ if (jshint_fails) {
+ message.push('found ' + jshint_fails + ' jshint issues');
+ }
+
+ if (jscs_fails) {
+ message.push('found ' + jscs_fails + ' jscs issues');
+ }
+
+ if (message.length) {
+ this.emit('error', new gutil.PluginError('gulp-github', {
+ message: 'Failed: ' + message.join(', ') + '.',
+ showStack: false
+ }));
+ }
+
+ cb();
+ });
+};
module.exports = function (options) {
var jshint_output = ['**Please fix these jshint issues first:**'],
@@ -71,12 +180,19 @@ module.exports = function (options) {
callback();
}, function (cb) {
var pr_url;
+ var count = 0;
+ var done = function () {
+ count--;
+ if (count == 0) {
+ cb();
+ }
+ };
if ((jshint_output.length === 1) && (jscs_output.length === 1)) {
return cb();
}
- if (opt.git_token && opt.git_repo && opt.git_prid) {
+ if (isPullRequest(opt)) {
pr_url = 'https://' + ((opt.git_option && opt.git_option.host) ? opt.git_option.host : 'github.com') + '/' + opt.git_repo + '/pull/' + opt.git_prid;
if (jshint_output.length > 1) {
commentToPR(jshint_output.join('\n'), opt);
@@ -100,27 +216,37 @@ module.exports = function (options) {
}
if (opt.git_token && opt.git_repo && opt.git_sha) {
+ count++;
if (jshint_output.length > 1) {
if (opt.jshint_status) {
+ count++;
createStatusToCommit({
state: opt.jshint_status,
description: (jshint_output.length - 1) + ' jshint issues found',
context: 'gulp-github/jshint'
- }, opt);
+ }, opt, done);
}
+ }
+ if (jscs_output.length > 1) {
if (opt.jscs_status) {
+ count++;
createStatusToCommit({
state: opt.jscs_status,
description: (jscs_output.length - 1) + ' jscs issues found',
context: 'gulp-github/jscs'
- }, opt);
+ }, opt, done);
}
}
}
- cb();
+ count++;
+ done();
});
};
module.exports.commentToPR = commentToPR;
+module.exports.createStatusToCommit = createStatusToCommit;
+module.exports.failThisTask = failThisTask;
+module.exports.failMergedPR = failMergedPR;
+module.exports.isMerge = isMerge;
diff --git a/package.json b/package.json
index 7c95847..13b6ed3 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "gulp-github",
- "version": "0.1.0",
+ "version": "0.2.3",
"description": "A gulp plugin to pipe contents to github pull request comments.",
"author": "Zordius ",
"contributors": [
@@ -26,14 +26,14 @@
},
"main": "index.js",
"dependencies": {
- "github": "0.2.3",
- "gulp-util": "3.0.1",
+ "github": "0.2.4",
+ "gulp-util": "3.0.6",
"through2": "*"
},
"devDependencies": {
- "gulp": "3.8.10",
- "gulp-jshint": "1.9.0",
- "gulp-jscs": "1.4.0"
+ "gulp": "3.9.0",
+ "gulp-jshint": "1.11.2",
+ "gulp-jscs": "2.0.0"
},
"engines": {
"node": ">=0.8"