From d7e86e62cb8899168b7036046b9f1a107f5ae23a Mon Sep 17 00:00:00 2001 From: Victor Chan Date: Wed, 14 Aug 2019 17:13:35 +1000 Subject: [PATCH 1/7] issue #26 Add placeholder code to execute action --- lib/actions/comment.js | 10 ++++++++++ lib/actions/constants.js | 1 + lib/actions/dispatcher.js | 4 +++- lib/actions/index.js | 8 +++++--- 4 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 lib/actions/comment.js diff --git a/lib/actions/comment.js b/lib/actions/comment.js new file mode 100644 index 0000000..2564e93 --- /dev/null +++ b/lib/actions/comment.js @@ -0,0 +1,10 @@ +'use strict'; + +module.exports = { + executeCommentAction, +}; + +function executeCommentAction({ args, config, credentials }) { + console.log(args, config, credentials); + return Promise.resolve(); +} diff --git a/lib/actions/constants.js b/lib/actions/constants.js index ff60e2a..cdd13a1 100644 --- a/lib/actions/constants.js +++ b/lib/actions/constants.js @@ -2,5 +2,6 @@ module.exports = { ACTION_COMMENTS: 'comments', + ACTION_COMMENT: 'comment', ACTION_SCRIPT: 'run', }; diff --git a/lib/actions/dispatcher.js b/lib/actions/dispatcher.js index 87e26f0..1a01cbe 100644 --- a/lib/actions/dispatcher.js +++ b/lib/actions/dispatcher.js @@ -1,14 +1,16 @@ 'use strict'; -const { ACTION_COMMENTS, ACTION_SCRIPT } = require('./constants'); +const { ACTION_COMMENTS, ACTION_COMMENT, ACTION_SCRIPT } = require('./constants'); const { executeCommentsAction } = require('./comments'); +const { executeCommentAction } = require('./comment'); const { executeScriptAction } = require('./script'); const { highlightText } = require('../colors'); const actions = { [ACTION_COMMENTS]: executeCommentsAction, + [ACTION_COMMENT]: executeCommentAction, [ACTION_SCRIPT]: executeScriptAction, }; diff --git a/lib/actions/index.js b/lib/actions/index.js index 3f5ea9e..08d3afa 100644 --- a/lib/actions/index.js +++ b/lib/actions/index.js @@ -1,7 +1,9 @@ 'use strict'; -module.exports = Object.assign({}, +module.exports = Object.assign( + {}, require('./comments'), require('./constants'), - require('./dispatcher') -); \ No newline at end of file + require('./dispatcher'), + require('./comment') +); From af2616e39bfa7a8215fa4c0c36685e24f2658560 Mon Sep 17 00:00:00 2001 From: Victor Chan Date: Wed, 14 Aug 2019 17:17:05 +1000 Subject: [PATCH 2/7] issue #26 Add command line argument for comment file --- lib/args.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/args.js b/lib/args.js index 10399f7..2fd39d9 100644 --- a/lib/args.js +++ b/lib/args.js @@ -1,7 +1,7 @@ 'use strict'; const path = require('path'); -const {Command} = require('commander'); +const { Command } = require('commander'); module.exports = { getArgs, @@ -33,6 +33,7 @@ function getArgs(argv) { .option('--username ', 'Bitbucket username. Needed if credentials path not provided.') .option('--password ', 'Bitbucket password. Needed if credentials path not provided.') .option('--fail-on-severity ', 'e.g, critical, error, fatal, warning etc', collectSeverities, []) + .option('--comment-file ', 'file to comment with. Only used for comment action.') .parse(argv); const args = { @@ -46,6 +47,7 @@ function getArgs(argv) { username: program.username, password: program.password, failOnSeverity: program.failOnSeverity.map(severity => severity.toLowerCase()), + commentFile: program.commentFile, }; return { args, From 9e0b55a933113fc03b2acb8ee039b3c3e0e9444c Mon Sep 17 00:00:00 2001 From: Victor Chan Date: Wed, 14 Aug 2019 17:38:46 +1000 Subject: [PATCH 3/7] issue #26 Move making the pull request out to common factory --- lib/actions/comments.js | 8 +++----- lib/factory/pull-request.js | 12 ++++++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 lib/factory/pull-request.js diff --git a/lib/actions/comments.js b/lib/actions/comments.js index 85d0a38..31bdf53 100644 --- a/lib/actions/comments.js +++ b/lib/actions/comments.js @@ -4,6 +4,7 @@ const Q = require('q'); const logger = require('../logger'); const { BitbucketClient } = require('../bitbucket'); +const { makePullRequest } = require('../factory/pull-request'); const { loadAndroidLintResults, loadCheckstyleResults } = require('../loaders'); const TOTAL_STEPS = 3; @@ -25,10 +26,6 @@ function executeCommentsAction({ args, config, credentials }) { failOnSeverity = [], } = args; - if (!repoSlug || !repoUser || !pullRequestID) { - throw new Error('Required repo slug, repo user and pull request id'); - } - if (checkstyleFilePaths.length === 0 && androidLintFilePaths.length === 0) { throw new Error('Please supply --checkstyle or --android-lint result files.'); } @@ -41,7 +38,8 @@ function executeCommentsAction({ args, config, credentials }) { username: credentials.bitbucket.username, password: credentials.bitbucket.password, }); - const pullRequest = client.repository(repoUser, repoSlug).pullRequest(pullRequestID); + + const pullRequest = makePullRequest({ client, user: repoUser, slug: repoSlug, id: pullRequestID }); const loader = checkstyleFilePaths.length > 0 ? loadCheckstyleResults : loadAndroidLintResults; const loaderFilePaths = checkstyleFilePaths.length > 0 ? checkstyleFilePaths : androidLintFilePaths; diff --git a/lib/factory/pull-request.js b/lib/factory/pull-request.js new file mode 100644 index 0000000..13f78ba --- /dev/null +++ b/lib/factory/pull-request.js @@ -0,0 +1,12 @@ +'use strict'; + +module.exports = { + makePullRequest, +}; + +function makePullRequest({ client, user, slug, id }) { + if (!slug || !user || !id) { + throw new Error('Required repo slug, repo user and pull request id'); + } + return client.repository(user, slug).pullRequest(id); +} From bc5b088666bfd8807a98c15b473dcdb5da7ee44c Mon Sep 17 00:00:00 2001 From: Victor Chan Date: Wed, 14 Aug 2019 17:39:12 +1000 Subject: [PATCH 4/7] issue #26 Create a pull request from client --- lib/actions/comment.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/actions/comment.js b/lib/actions/comment.js index 2564e93..8692b54 100644 --- a/lib/actions/comment.js +++ b/lib/actions/comment.js @@ -1,10 +1,25 @@ 'use strict'; +const { makePullRequest } = require('../factory/pull-request'); +const { BitbucketClient } = require('../bitbucket'); + module.exports = { executeCommentAction, }; function executeCommentAction({ args, config, credentials }) { - console.log(args, config, credentials); + const { + repoUser = config.bitbucket.repoUser, + repoSlug = config.bitbucket.repoSlug, + messageIdentifier = config.messageIdentifier, + pullRequestID, + commentFile, + } = args; + const client = new BitbucketClient({ + username: credentials.bitbucket.username, + password: credentials.bitbucket.password, + }); + const pullRequest = makePullRequest({ client, user: repoUser, slug: repoSlug, id: pullRequestID }); + console.log(credentials, pullRequest, messageIdentifier, commentFile); return Promise.resolve(); } From 9a24fe0694afba2c7157874d1e2b4b0998aed58c Mon Sep 17 00:00:00 2001 From: Victor Chan Date: Thu, 15 Aug 2019 12:12:13 +1000 Subject: [PATCH 5/7] issue #26 Add action to add comment to pull request --- lib/actions/comment.js | 15 +++++++++---- lib/args.js | 4 ++-- lib/bitbucket/pull-request.js | 40 ++++++++++++++++++----------------- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/lib/actions/comment.js b/lib/actions/comment.js index 8692b54..d630009 100644 --- a/lib/actions/comment.js +++ b/lib/actions/comment.js @@ -2,6 +2,7 @@ const { makePullRequest } = require('../factory/pull-request'); const { BitbucketClient } = require('../bitbucket'); +const logger = require('../logger'); module.exports = { executeCommentAction, @@ -11,15 +12,21 @@ function executeCommentAction({ args, config, credentials }) { const { repoUser = config.bitbucket.repoUser, repoSlug = config.bitbucket.repoSlug, - messageIdentifier = config.messageIdentifier, pullRequestID, - commentFile, + commentMessage: message, } = args; + + if (!message) { + throw new Error('No comment to post onto pull request'); + } + const client = new BitbucketClient({ username: credentials.bitbucket.username, password: credentials.bitbucket.password, }); const pullRequest = makePullRequest({ client, user: repoUser, slug: repoSlug, id: pullRequestID }); - console.log(credentials, pullRequest, messageIdentifier, commentFile); - return Promise.resolve(); + + logger.step(1, 1, `posting message to pull request id ${pullRequestID}`); + logger.debug(`message: \n${message}`); + return pullRequest.addComment({ message }); } diff --git a/lib/args.js b/lib/args.js index 2fd39d9..2d98357 100644 --- a/lib/args.js +++ b/lib/args.js @@ -33,7 +33,7 @@ function getArgs(argv) { .option('--username ', 'Bitbucket username. Needed if credentials path not provided.') .option('--password ', 'Bitbucket password. Needed if credentials path not provided.') .option('--fail-on-severity ', 'e.g, critical, error, fatal, warning etc', collectSeverities, []) - .option('--comment-file ', 'file to comment with. Only used for comment action.') + .option('--comment-message ', 'comment message to send. Only used for comment action.') .parse(argv); const args = { @@ -47,7 +47,7 @@ function getArgs(argv) { username: program.username, password: program.password, failOnSeverity: program.failOnSeverity.map(severity => severity.toLowerCase()), - commentFile: program.commentFile, + commentMessage: program.commentMessage, }; return { args, diff --git a/lib/bitbucket/pull-request.js b/lib/bitbucket/pull-request.js index 7145b48..6b359e7 100644 --- a/lib/bitbucket/pull-request.js +++ b/lib/bitbucket/pull-request.js @@ -102,26 +102,28 @@ class BitbucketPullRequest { addComment(comment) { const url = `${constants.API_2_BASE}/repositories/${this.repository.repoUser}/${this.repository .repoSlug}/pullrequests/${this.pullRequestId}/comments`; + const requestParams = { + content: { raw: comment.message }, + }; + + if (comment.fileName) { + // Line from is for unchanged and line to for changed + const lineParamKey = comment.changed ? 'to' : 'from'; + const line = comment.changed ? comment.newLine : comment.previousLine; + + requestParams.inline = { + [lineParamKey]: line, + path: comment.fileName, + }; + } - // Line from is for unchanged and line to for changed - const lineParamKey = comment.changed ? 'to' : 'from'; - const line = comment.changed ? comment.newLine : comment.previousLine; - - return this._backend - .request('post', url, { - inline: { - [lineParamKey]: line, - path: comment.fileName, - }, - content: { raw: comment.message }, - }) - .then(({ statusCode, body }) => { - if (!isStatusCodeSuccess(statusCode)) { - console.error(body); - return false; - } - return true; - }); + return this._backend.request('post', url, requestParams).then(({ statusCode, body }) => { + if (!isStatusCodeSuccess(statusCode)) { + console.error(body); + return false; + } + return true; + }); } } From 88e1052f58ffd00c74a6c85cdab04bfecc4f2677 Mon Sep 17 00:00:00 2001 From: Victor Chan Date: Thu, 15 Aug 2019 13:38:59 +1000 Subject: [PATCH 6/7] issue #26 Add test file for comment action --- lib/actions/comment.spec.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 lib/actions/comment.spec.js diff --git a/lib/actions/comment.spec.js b/lib/actions/comment.spec.js new file mode 100644 index 0000000..e69de29 From 97af864599a1c3ef9cf08723a1c76fa578e8ff03 Mon Sep 17 00:00:00 2001 From: Victor Chan Date: Thu, 15 Aug 2019 14:04:16 +1000 Subject: [PATCH 7/7] issue #26 Test comment works as expected --- lib/actions/comment.js | 2 +- lib/actions/comment.spec.js | 70 +++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/lib/actions/comment.js b/lib/actions/comment.js index d630009..b76d612 100644 --- a/lib/actions/comment.js +++ b/lib/actions/comment.js @@ -17,7 +17,7 @@ function executeCommentAction({ args, config, credentials }) { } = args; if (!message) { - throw new Error('No comment to post onto pull request'); + return Promise.reject(new Error('No comment to post onto pull request')); } const client = new BitbucketClient({ diff --git a/lib/actions/comment.spec.js b/lib/actions/comment.spec.js index e69de29..14c09d4 100644 --- a/lib/actions/comment.spec.js +++ b/lib/actions/comment.spec.js @@ -0,0 +1,70 @@ +'use strict'; + +const chai = require('chai'); +const nock = require('nock'); + +const { executeCommentAction } = require('./comment'); + +const HTTP_CREATED = 201; + +describe('Action Comment', () => { + describe('executeCommentAction', () => { + let config, credentials, args, postCommentNock; + beforeEach(() => { + config = { + bitbucket: { + repoUser: 'my-user', + repoSlug: 'my-repo', + }, + }; + credentials = { + bitbucket: { + username: 'user1', + password: 'pass1', + }, + }; + args = { + pullRequestID: 10, + commentMessage: 'foo bar', + }; + postCommentNock = nock('https://api.bitbucket.org/2.0') + .post('/repositories/my-user/my-repo/pullrequests/10/comments') + .once() + .reply(HTTP_CREATED, {}); + }); + + afterEach(() => { + nock.cleanAll(); + }); + + it('returns error if there are no comments to post', done => { + delete args.commentMessage; + executeCommentAction({ + args, + config, + credentials, + }) + .then(() => done('expected error when there is no comment message to post')) + .catch(({ message }) => { + chai.expect(message).to.equal('No comment to post onto pull request'); + chai.expect(postCommentNock.isDone(), 'Request should not be called').to.be.false; + done(); + }); + }); + + it('returns success when posting comment with all args', done => { + executeCommentAction({ + args, + config, + credentials, + }) + .then(() => { + chai.expect(postCommentNock.isDone(), 'Request should have been called once').to.be.true; + done(); + }) + .catch(({ message }) => { + done(message); + }); + }); + }); +});