From a205154bf6e14d4c915cb01d332dadc2675abd20 Mon Sep 17 00:00:00 2001 From: John Karahalis Date: Thu, 21 Jan 2016 09:19:24 -0500 Subject: [PATCH] Fix #79: Never post the same comment twice --- migrations/20160121091841-create-comment.js | 39 ++++++++ models/comment.js | 17 ++++ routes/hook/index.js | 105 ++++++++++++++------ 3 files changed, 131 insertions(+), 30 deletions(-) create mode 100644 migrations/20160121091841-create-comment.js create mode 100644 models/comment.js diff --git a/migrations/20160121091841-create-comment.js b/migrations/20160121091841-create-comment.js new file mode 100644 index 0000000..6aacd2d --- /dev/null +++ b/migrations/20160121091841-create-comment.js @@ -0,0 +1,39 @@ +'use strict'; +module.exports = { + up: function(queryInterface, Sequelize) { + return queryInterface.createTable('Comments', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + repo: { + type: Sequelize.TEXT + }, + pr: { + type: Sequelize.INTEGER + }, + filename: { + type: Sequelize.TEXT + }, + line: { + type: Sequelize.INTEGER + }, + feature: { + type: Sequelize.TEXT + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: function(queryInterface, Sequelize) { + return queryInterface.dropTable('Comments'); + } +}; diff --git a/models/comment.js b/models/comment.js new file mode 100644 index 0000000..726f0b9 --- /dev/null +++ b/models/comment.js @@ -0,0 +1,17 @@ +'use strict'; +module.exports = function(sequelize, DataTypes) { + var Comment = sequelize.define('Comment', { + repo: DataTypes.TEXT, + pr: DataTypes.INTEGER, + filename: DataTypes.TEXT, + line: DataTypes.INTEGER, + feature: DataTypes.TEXT + }, { + classMethods: { + associate: function(models) { + // associations can be defined here + } + } + }); + return Comment; +}; diff --git a/routes/hook/index.js b/routes/hook/index.js index a704c50..965f6e2 100644 --- a/routes/hook/index.js +++ b/routes/hook/index.js @@ -70,36 +70,51 @@ function processPullRequest(destinationRepo, originRepo, originBranch, prNumber, processor.process(githubClient, originRepo, originBranch, file, discordConfig, function(incompatibility) { // Callback for handling an incompatible line of code var line = diff.lineToIndex(file.patch, incompatibility.usage.source.start.line); - var comment = incompatibility.featureData.title + ' not supported by: ' + incompatibility.featureData.missing; - - var redisQueue = kue.createQueue({ - redis: config.redisURL - }); - - // Create a Redis job that will submit the comment - var commentJob = redisQueue.create('comment', { - commentURL: commentURL, - sha: currentCommit.sha, - filename: file.filename, - line: line, - comment: comment - }); - - // If the comment is rejected, re-attempt several times with - // exponentially longer waits between each attempt. - commentJob.attempts(config.commentAttempts); - commentJob.backoff({ - type: 'exponential' - }); - - // If the comment is rejected after several attempts, log an - // error. - commentJob.on('failed', function() { - logger.error('Error posting comment to line ' + line + ' of ' + file.filename + ' in ' + originRepo + ' pull request #' + prNumber); - }); - - commentJob.save(function(error) { - if (error) return logger.error(error); + var filename = file.filename; + var feature = incompatibility.featureData.title; + var comment = feature + ' not supported by: ' + incompatibility.featureData.missing; + + var alreadyCommented = commentExists(destinationRepo, prNumber, filename, line, feature); + alreadyCommented.then(function(alreadyCommented) { + if (!alreadyCommented) { + var redisQueue = kue.createQueue({ + redis: config.redisURL + }); + + // Create a Redis job that will submit the comment + var commentJob = redisQueue.create('comment', { + commentURL: commentURL, + sha: currentCommit.sha, + filename: filename, + line: line, + comment: comment + }); + + // If the comment is rejected, re-attempt several times with + // exponentially longer waits between each attempt. + commentJob.attempts(config.commentAttempts); + commentJob.backoff({ + type: 'exponential' + }); + + // If the comment is rejected after several attempts, log an + // error. + commentJob.on('failed', function() { + logger.error('Error posting comment to line ' + line + ' of ' + filename + ' in ' + originRepo + ' pull request #' + prNumber); + }); + + commentJob.save(function(error) { + if (error) return logger.error(error); + }); + + models.Comment.create({ + repo: destinationRepo, + pr: prNumber, + filename: filename, + line: line, + feature: feature + }); + } }); }); @@ -177,4 +192,34 @@ function getCommitDetail(repo, sha) { return deferred.promise; } +function commentExists(repo, prNumber, filename, line, feature) { + var deferred = Q.defer(); + + models.Comment.count({ + where: { + repo: repo, + pr: prNumber, + filename: filename, + line: line, + feature: feature + } + }).then( + // Success callback (a matching comment was found) + function(count) { + if (count > 0) { + deferred.resolve(true); + } else { + deferred.resolve(false); + } + }, + + // Failure callback (no matching comments were found) + function(error) { + deferred.reject(error); + } + ); + + return deferred.promise; +} + module.exports = router;