From 83b4bead4885cdeb97cf5d898a011b1ccbca2fda Mon Sep 17 00:00:00 2001 From: Rhys Arkins <rhys@arkins.net> Date: Sun, 16 Dec 2018 13:47:05 +0100 Subject: [PATCH] fix: ensureIssue logic (#2957) if ensureIssue once, and the first matching issue was closed, then any other matching open ones are also closed. If ensureIssue regular, and all are closed, then reopen the latest one. --- lib/platform/github/index.js | 66 +++++++++++++++++------------- test/platform/github/index.spec.js | 24 +++++++++++ 2 files changed, 61 insertions(+), 29 deletions(-) diff --git a/lib/platform/github/index.js b/lib/platform/github/index.js index f4992d4030..a7590cc1e1 100644 --- a/lib/platform/github/index.js +++ b/lib/platform/github/index.js @@ -602,7 +602,7 @@ async function getIssueList() { logger.debug('Retrieving issueList'); const res = await get( `repos/${config.parentRepo || - config.repository}/issues?filter=created&state=all&per_page=100&sort=updated`, + config.repository}/issues?filter=created&state=all&per_page=100&sort=created&direction=asc`, { paginate: true, useCache: false } ); // istanbul ignore if @@ -647,48 +647,56 @@ async function ensureIssue(title, body, once = false) { logger.debug(`ensureIssue()`); try { const issueList = await getIssueList(); - const issues = issueList.filter(i => i.title === title).reverse(); + const issues = issueList.filter(i => i.title === title); if (issues.length) { - if (issues.length > 1) { + if (once && issues[0].state === 'closed') { + // Close all other matching issues and return for (const issue of issues.slice(1)) { if (issue.state === 'open') { logger.warn('Closing duplicate issue ' + issue.number); await closeIssue(issue.number); } } - } - const [issue] = issues; - if (once && issue.state === 'closed') { - logger.debug('Issue is closed - skipping'); return null; } + const issue = + issues.find(i => i.state === 'open') || issues[issues.length - 1]; + logger.info({ issue }); + for (const i of issues) { + if (i.state === 'open' && i.number !== issue.number) { + logger.warn('Closing duplicate issue ' + i.number); + await closeIssue(i.number); + } + } const issueBody = (await get( `repos/${config.parentRepo || config.repository}/issues/${issue.number}` )).body.body; - if (issueBody !== body) { - logger.info('Issue updated'); - await get.patch( - `repos/${config.parentRepo || config.repository}/issues/${ - issue.number - }`, - { - body: { body }, - } - ); - return 'updated'; + if (issueBody === body && issue.state === 'open') { + logger.info('Issue is open and up to date - nothing to do'); + return null; } - } else { - await get.post(`repos/${config.parentRepo || config.repository}/issues`, { - body: { - title, - body, - }, - }); - logger.info('Issue created'); - // reset issueList so that it will be fetched again as-needed - delete config.issueList; - return 'created'; + logger.info('Patching issue'); + await get.patch( + `repos/${config.parentRepo || config.repository}/issues/${ + issue.number + }`, + { + body: { body, state: 'open' }, + } + ); + logger.info('Issue updated'); + return 'updated'; } + await get.post(`repos/${config.parentRepo || config.repository}/issues`, { + body: { + title, + body, + }, + }); + logger.info('Issue created'); + // reset issueList so that it will be fetched again as-needed + delete config.issueList; + return 'created'; } catch (err) /* istanbul ignore next */ { if (err.message.startsWith('Issues are disabled for this repo')) { logger.info( diff --git a/test/platform/github/index.spec.js b/test/platform/github/index.spec.js index 9545da9b62..7d07145af2 100644 --- a/test/platform/github/index.spec.js +++ b/test/platform/github/index.spec.js @@ -1077,6 +1077,30 @@ describe('platform/github', () => { const res = await github.ensureIssue('title-1', 'new-content', once); expect(res).toEqual(null); }); + it('closes others if ensuring only once', async () => { + get.mockImplementationOnce(() => ({ + body: [ + { + number: 1, + title: 'title-1', + state: 'closed', + }, + { + number: 2, + title: 'title-2', + state: 'open', + }, + { + number: 3, + title: 'title-1', + state: 'open', + }, + ], + })); + const once = true; + const res = await github.ensureIssue('title-1', 'new-content', once); + expect(res).toEqual(null); + }); it('updates issue', async () => { get.mockReturnValueOnce({ body: [ -- GitLab