diff --git a/README.md b/README.md index 954a38f..a96e967 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,9 @@ Options git_repo: 'zordius/test', git_prid: '1', + // distribute comments into files, optional + dist_to_files: true, + // create status to this commit, optional git_sha: 00000000, jshint_status: 'error', // Set status to error when jshint errors, optional diff --git a/gulpfile.js b/gulpfile.js index 6ebf5ee..ccd4c54 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -4,8 +4,11 @@ var gulp = require('gulp'), eslint = require('gulp-eslint'), github = require('./index'); +require('es6-promise').polyfill(); +require('object.assign').shim(); + gulp.task('default', function () { - return gulp.src('*.js') + return gulp.src(['*.js', 'lint_test/*.js']) .pipe(eslint()) .pipe(jshint()) .pipe(jscs()) @@ -21,8 +24,11 @@ gulp.task('default', function () { git_prid: process.env.TRAVIS_PULL_REQUEST, git_sha: process.env.TRAVIS_COMMIT, - jshint_status: 'error', // Set status to error when jshint errors - jscs_status: 'failure' // Set status to failure when jscs errors + dist_to_files: true, + + jshint_status: 'error', // Set status to error when jshint errors + jscs_status: 'failure', // Set status to failure when jscs errors + eslint_status: 'failure' // Set status to failure when eslint errors })) .pipe(github.failThisTask()); }); diff --git a/index.js b/index.js index 9cc3422..60a505b 100644 --- a/index.js +++ b/index.js @@ -15,6 +15,19 @@ var eslint_simple_reporter = function (E, file) { return ' 1. ' + path.relative(process.cwd(), file.path) + ': line ' + E.line + ', col ' + E.column + ' *' + E.message + '* (' + E.moduleId + ')'; }; +var promisify = function (func) { + return function () { + var args = Array.prototype.slice.call(arguments); + + return new Promise(function (resolve, reject) { + args.push(function (E, result) { + return E ? reject(E) : resolve(result); + }); + func.apply(null, args); + }); + }; +}; + var getGIT = function (opt) { var GIT = new github(opt.git_option || { version: '3.0.0', @@ -29,57 +42,63 @@ var getGIT = function (opt) { return GIT; }; -var closePR = function (opt, cb) { - getGIT(opt).issues.edit({ +var closePR = function (opt) { + return promisify(getGIT(opt).issues.edit)({ user: opt.git_repo.split('/')[0], repo: opt.git_repo.split('/')[1], number: opt.git_prid, state: 'closed' - }, cb); + }); +}; + +var commentToPR = function (body, opt) { + return promisify(getGIT(opt).issues.createComment)({ + user: opt.git_repo.split('/')[0], + repo: opt.git_repo.split('/')[1], + number: opt.git_prid, + body: body + }); }; -var commentToPR = function (body, opt, cb) { - getGIT(opt).issues.createComment({ +var commentToPRFile = function (body, opt, path) { + return promisify(getGIT(opt).pullRequests.createComment)({ user: opt.git_repo.split('/')[0], repo: opt.git_repo.split('/')[1], number: opt.git_prid, + commit_id: opt.git_sha, + path: path, body: body - }, cb); + }); }; -var createStatusToCommit = function (state, opt, cb) { - getGIT(opt).statuses.create({ +var createStatusToCommit = function (state, opt) { + return promisify(getGIT(opt).statuses.create)({ user: opt.git_repo.split('/')[0], repo: opt.git_repo.split('/')[1], sha: opt.git_sha, state: state.state, description: state.description, context: state.context - }, cb); + }); }; var isPullRequest = function (opt) { return opt.git_token && opt.git_repo && opt.git_prid && (opt.git_prid !== 'false'); }; -var isMerge = function (opt, callback) { +var isMerge = function (opt) { if (!isPullRequest(opt)) { - return callback(); + return Promise.resolve(); } - getGIT(opt).pullRequests.getCommits({ + return promisify(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) { + }).then(function (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) { @@ -88,39 +107,24 @@ var isMerge = function (opt, callback) { } }); - callback(merged.length ? merged.join('\n') : false); + return merged.length ? merged.join('\n') : false; }); }; -var 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) { +var failMergedPR = function (opt) { + return isMerge(opt).then(function (M) { if (!M) { return; } - - err.push(M); - - 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); + return Promise.all([ + commentToPR('**Do not accept PR with merge, please use rebase always!**\n' + M, opt), + createStatusToCommit({ + state: 'failure', + description: 'merge in PR', + context: 'gulp-github/is_merge' + }, opt), + closePR(opt) + ]); }); }; @@ -181,35 +185,47 @@ module.exports = function (options) { jscs_reporter = opt.jscs_reporter || jscs_simple_reporter; return through.obj(function (file, enc, callback) { + var promises = []; + if (file.jshint && !file.jshint.success && !file.jshint.ignored) { file.jshint.results.forEach(function (E) { + if (opt.dist_to_files && isPullRequest(opt)) { + promises.push(commentToPRFile('**JSHINT ERROR:**' + E.error.reason, Object.assign({position: E.error.line}, opt), path.relative(process.cwd(), file.path))); + } jshint_output.push(jshint_reporter(E, file)); }); } if (file.jscs && !file.jscs.success) { - file.jscs.errors.forEach(function (E) { + file.jscs.errors.getErrorList().forEach(function (E) { + if (opt.dist_to_files && isPullRequest(opt)) { + promises.push(commentToPRFile('**JSCS ERROR:**' + E.message, Object.assign({position: E.line}, opt), path.relative(process.cwd(), file.path))); + } jscs_output.push(jscs_reporter(E, file)); }); } if (file.eslint) { file.eslint.messages.forEach(function (E) { + if (opt.dist_to_files && isPullRequest(opt)) { + promises.push(commentToPRFile('**ESLINT ERROR:**' + E.message + (E.moduleId ? ' (' + E.moduleId + ')' : ''), Object.assign({position: E.line}, opt), path.relative(process.cwd(), file.path))); + } eslint_output.push(eslint_simple_reporter(E, file)); }); } this.push(file); - callback(); + + if (promises.length) { + Promise.all(promises).then(function () { + callback(); + }, callback); + } else { + callback(); + } }, function (cb) { var pr_url; - var count = 0; - var done = function () { - count--; - if (count === 0) { - cb(); - } - }; + var promises = []; if ((jshint_output.length === 1) && (jscs_output.length === 1) && (eslint_output.length === 1)) { return cb(); @@ -218,15 +234,21 @@ module.exports = function (options) { 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); + if (!opt.dist_to_files) { + promises.push(commentToPR(jshint_output.join('\n'), opt)); + } gutil.log('[gulp-github]', gutil.colors.bold((jshint_output.length - 1) + ' jshint issues were updated to ' + pr_url)); } if (jscs_output.length > 1) { - commentToPR(jscs_output.join('\n'), opt); + if (!opt.dist_to_files) { + promises.push(commentToPR(jscs_output.join('\n'), opt)); + } gutil.log('[gulp-github]', gutil.colors.bold((jscs_output.length - 1) + ' jscs issues were updated to ' + pr_url)); } if (eslint_output.length > 1) { - commentToPR(eslint_output.join('\n'), opt); + if (!opt.dist_to_files) { + promises.push(commentToPR(eslint_output.join('\n'), opt)); + } gutil.log('[gulp-github]', gutil.colors.bold((eslint_output.length - 1) + ' eslint issues were updated to ' + pr_url)); } } else { @@ -247,46 +269,40 @@ 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({ + promises.push(createStatusToCommit({ state: opt.jshint_status, description: (jshint_output.length - 1) + ' jshint issues found', context: 'gulp-github/jshint' - }, opt, done); + }, opt)); } } if (jscs_output.length > 1) { if (opt.jscs_status) { - count++; - createStatusToCommit({ + promises.push(createStatusToCommit({ state: opt.jscs_status, description: (jscs_output.length - 1) + ' jscs issues found', context: 'gulp-github/jscs' - }, opt, done); + }, opt)); } } if (eslint_output.length > 1) { if (opt.eslint_status) { - count++; - createStatusToCommit({ + promises.push(createStatusToCommit({ state: opt.eslint_status, description: (eslint_output.length - 1) + ' eslint issues found', context: 'gulp-github/eslint' - }, opt, done); + }, opt)); } } - - count--; } - count++; - done(); + Promise.all(promises).then(function () { + cb(); + }, cb); }); }; diff --git a/lint_test/test1.js b/lint_test/test1.js new file mode 100644 index 0000000..c09af3e --- /dev/null +++ b/lint_test/test1.js @@ -0,0 +1,7 @@ +var bad = {}; +var foo = 123; + +if (123) { + foo ++; + foo--; +} diff --git a/package.json b/package.json index 015ef3a..80e2929 100644 --- a/package.json +++ b/package.json @@ -27,14 +27,16 @@ "main": "index.js", "dependencies": { "github": "0.2.4", - "gulp-util": "3.0.6", + "gulp-util": "3.0.7", "through2": "*" }, "devDependencies": { - "gulp": "3.9.0", - "gulp-jshint": "1.11.2", - "gulp-jscs": "2.0.0", - "gulp-eslint": "1.0.0" + "gulp": "3.9.1", + "gulp-jshint": "2.0.0", + "gulp-jscs": "3.0.2", + "gulp-eslint": "2.0.0", + "es6-promise": "3.1.2", + "object.assign": "4.0.3" }, "engines": { "node": ">=0.8"