Skip to content

Commit 599e0df

Browse files
committed
fix: do not add comment for unrelated PR returned by search
1 parent c4347eb commit 599e0df

File tree

4 files changed

+82
-9
lines changed

4 files changed

+82
-9
lines changed

lib/success.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
const {isUndefined, uniqBy, template} = require('lodash');
1+
const {isUndefined, uniqBy, template, flatten} = require('lodash');
22
const parseGithubUrl = require('parse-github-url');
3+
const pFilter = require('p-filter');
34
const AggregateError = require('aggregate-error');
45
const issueParser = require('issue-parser')('github');
56
const debug = require('debug')('semantic-release:github');
@@ -17,14 +18,14 @@ module.exports = async (
1718
const {name: repo, owner} = parseGithubUrl(repositoryUrl);
1819
const github = getClient({githubToken, githubUrl, githubApiPathPrefix});
1920
const releaseInfos = releases.filter(release => Boolean(release.name));
21+
const shas = commits.map(commit => commit.hash);
2022

21-
const prs = [].concat(
22-
...(await Promise.all(
23-
getSearchQueries(`repo:${owner}/${repo}+type:pr+is:merged`, commits.map(commit => commit.hash)).map(async q => {
24-
const {data: {items}} = await github.search.issues({q});
25-
return items;
26-
})
27-
))
23+
const searchQueries = getSearchQueries(`repo:${owner}/${repo}+type:pr+is:merged`, shas).map(
24+
async q => (await github.search.issues({q})).data.items
25+
);
26+
27+
const prs = await pFilter(uniqBy(flatten(await Promise.all(searchQueries)), 'number'), async ({number}) =>
28+
(await github.pullRequests.getCommits({owner, repo, number})).data.find(({sha}) => shas.includes(sha))
2829
);
2930

3031
debug('found pull requests: %O', prs.map(pr => pr.number));

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"issue-parser": "^1.0.2",
2727
"lodash": "^4.17.4",
2828
"mime": "^2.0.3",
29+
"p-filter": "^1.0.0",
2930
"p-retry": "^1.0.0",
3031
"parse-github-url": "^1.0.1",
3132
"url-join": "^4.0.0"

test/integration.test.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ test.serial('Comment on PR included in the releases', async t => {
197197
.join('+')}`
198198
)
199199
.reply(200, {items: prs})
200+
.get(`/repos/${owner}/${repo}/pulls/1/commits`)
201+
.reply(200, [{sha: commits[0].hash}])
200202
.get(`/repos/${owner}/${repo}/issues/1`)
201203
.reply(200, {state: 'closed'})
202204
.post(`/repos/${owner}/${repo}/issues/1/comments`, {body: /This PR is included/})
@@ -288,6 +290,8 @@ test.serial('Verify, release and notify success', async t => {
288290
.join('+')}`
289291
)
290292
.reply(200, {items: prs})
293+
.get(`/repos/${owner}/${repo}/pulls/1/commits`)
294+
.reply(200, [{sha: commits[0].hash}])
291295
.get(`/repos/${owner}/${repo}/issues/1`)
292296
.reply(200, {state: 'closed'})
293297
.post(`/repos/${owner}/${repo}/issues/1/comments`, {body: /This PR is included/})

test/success.test.js

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ test.serial('Add comment to PRs associated with release commits and issues close
6464
.join('+')}`
6565
)
6666
.reply(200, {items: prs})
67+
.get(`/repos/${owner}/${repo}/pulls/1/commits`)
68+
.reply(200, [{sha: commits[0].hash}])
69+
.get(`/repos/${owner}/${repo}/pulls/2/commits`)
70+
.reply(200, [{sha: commits[1].hash}])
6771
.get(`/repos/${owner}/${repo}/issues/1`)
6872
.reply(200, {state: 'closed'})
6973
.post(`/repos/${owner}/${repo}/issues/1/comments`, {body: /This PR is included/})
@@ -135,6 +139,18 @@ test.serial('Make multiple search queries if necessary', async t => {
135139
}+${commits[6].hash}`
136140
)
137141
.reply(200, {items: [prs[5], prs[1]]})
142+
.get(`/repos/${owner}/${repo}/pulls/1/commits`)
143+
.reply(200, [{sha: commits[0].hash}])
144+
.get(`/repos/${owner}/${repo}/pulls/2/commits`)
145+
.reply(200, [{sha: commits[1].hash}])
146+
.get(`/repos/${owner}/${repo}/pulls/3/commits`)
147+
.reply(200, [{sha: commits[2].hash}])
148+
.get(`/repos/${owner}/${repo}/pulls/4/commits`)
149+
.reply(200, [{sha: commits[3].hash}])
150+
.get(`/repos/${owner}/${repo}/pulls/5/commits`)
151+
.reply(200, [{sha: commits[4].hash}])
152+
.get(`/repos/${owner}/${repo}/pulls/6/commits`)
153+
.reply(200, [{sha: commits[5].hash}])
138154
.get(`/repos/${owner}/${repo}/issues/1`)
139155
.reply(200, {state: 'closed'})
140156
.post(`/repos/${owner}/${repo}/issues/1/comments`, {body: /This PR is included/})
@@ -177,6 +193,45 @@ test.serial('Make multiple search queries if necessary', async t => {
177193
t.true(github.isDone());
178194
});
179195

196+
test.serial('Do not add comment for unrelated PR returned by search', async t => {
197+
const owner = 'test_user';
198+
const repo = 'test_repo';
199+
process.env.GITHUB_TOKEN = 'github_token';
200+
const failTitle = 'The automated release is failing 🚨';
201+
const pluginConfig = {failTitle};
202+
const prs = [{number: 1, pull_request: {}}, {number: 2, pull_request: {}}];
203+
const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`};
204+
const commits = [{hash: '123', message: 'Commit 1 message'}, {hash: '456', message: 'Commit 2 message'}];
205+
const nextRelease = {version: '1.0.0'};
206+
const releases = [{name: 'GitHub release', url: 'https://github.com/release'}];
207+
const github = authenticate()
208+
.get(
209+
`/search/issues?q=${escape(`repo:${owner}/${repo}`)}+${escape('type:pr')}+${escape('is:merged')}+${commits
210+
.map(commit => commit.hash)
211+
.join('+')}`
212+
)
213+
.reply(200, {items: prs})
214+
.get(`/repos/${owner}/${repo}/pulls/1/commits`)
215+
.reply(200, [{sha: commits[0].hash}])
216+
.get(`/repos/${owner}/${repo}/pulls/2/commits`)
217+
.reply(200, [{sha: 'unrelated_commit'}])
218+
.get(`/repos/${owner}/${repo}/issues/1`)
219+
.reply(200, {state: 'closed'})
220+
.post(`/repos/${owner}/${repo}/issues/1/comments`, {body: /This PR is included/})
221+
.reply(200, {html_url: 'https://github.com/successcomment-1'})
222+
.get(
223+
`/search/issues?q=${escape('in:title')}+${escape(`repo:${owner}/${repo}`)}+${escape('type:issue')}+${escape(
224+
'state:open'
225+
)}+${escape(failTitle)}`
226+
)
227+
.reply(200, {items: []});
228+
229+
await success(pluginConfig, {options, commits, nextRelease, releases, logger: t.context.logger});
230+
231+
t.true(t.context.log.calledWith('Added comment to issue #%d: %s', 1, 'https://github.com/successcomment-1'));
232+
t.true(github.isDone());
233+
});
234+
180235
test.serial('Do not add comment to open issues/PRs', async t => {
181236
const owner = 'test_user';
182237
const repo = 'test_repo';
@@ -195,6 +250,8 @@ test.serial('Do not add comment to open issues/PRs', async t => {
195250
.join('+')}`
196251
)
197252
.reply(200, {items: prs})
253+
.get(`/repos/${owner}/${repo}/pulls/1/commits`)
254+
.reply(200, [{sha: commits[0].hash}])
198255
.get(`/repos/${owner}/${repo}/issues/1`)
199256
.reply(200, {state: 'closed'})
200257
.post(`/repos/${owner}/${repo}/issues/1/comments`, {body: /This PR is included/})
@@ -299,6 +356,10 @@ test.serial('Ignore missing issues/PRs', async t => {
299356
.join('+')}`
300357
)
301358
.reply(200, {items: prs})
359+
.get(`/repos/${owner}/${repo}/pulls/1/commits`)
360+
.reply(200, [{sha: commits[0].hash}])
361+
.get(`/repos/${owner}/${repo}/pulls/2/commits`)
362+
.reply(200, [{sha: commits[1].hash}])
302363
.get(`/repos/${owner}/${repo}/issues/1`)
303364
.reply(200, {state: 'closed'})
304365
.post(`/repos/${owner}/${repo}/issues/1/comments`, {body: /This PR is included/})
@@ -349,6 +410,8 @@ test.serial('Add custom comment', async t => {
349410
.join('+')}`
350411
)
351412
.reply(200, {items: prs})
413+
.get(`/repos/${owner}/${repo}/pulls/1/commits`)
414+
.reply(200, [{sha: commits[0].hash}])
352415
.get(`/repos/${owner}/${repo}/issues/1`)
353416
.reply(200, {state: 'closed'})
354417
.post(`/repos/${owner}/${repo}/issues/1/comments`, {
@@ -380,7 +443,7 @@ test.serial('Ignore errors when adding comments and closing issues', async t =>
380443
];
381444
const prs = [{number: 1, pull_request: {}}, {number: 2, pull_request: {}}];
382445
const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`};
383-
const commits = [{hash: '123', message: 'Commit 1 message'}];
446+
const commits = [{hash: '123', message: 'Commit 1 message'}, {hash: '456', message: 'Commit 2 message'}];
384447
const nextRelease = {version: '1.0.0'};
385448
const releases = [{name: 'GitHub release', url: 'https://github.com/release'}];
386449
const github = authenticate()
@@ -390,6 +453,10 @@ test.serial('Ignore errors when adding comments and closing issues', async t =>
390453
.join('+')}`
391454
)
392455
.reply(200, {items: prs})
456+
.get(`/repos/${owner}/${repo}/pulls/1/commits`)
457+
.reply(200, [{sha: commits[0].hash}])
458+
.get(`/repos/${owner}/${repo}/pulls/2/commits`)
459+
.reply(200, [{sha: commits[1].hash}])
393460
.get(`/repos/${owner}/${repo}/issues/1`)
394461
.reply(200, {state: 'closed'})
395462
.post(`/repos/${owner}/${repo}/issues/1/comments`, {body: /This PR is included/})

0 commit comments

Comments
 (0)