From 98690d92b54b8f0a86fa00d7fc6bb2ea71af93f8 Mon Sep 17 00:00:00 2001 From: Sam Bostock Date: Sat, 14 Mar 2020 00:44:33 -0400 Subject: [PATCH 1/4] Make getStale function async --- lib/stale.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/stale.js b/lib/stale.js index 786a93d..7de2bee 100644 --- a/lib/stale.js +++ b/lib/stale.js @@ -62,7 +62,7 @@ module.exports = class Stale { } } - getStale (type) { + async getStale (type) { const onlyLabels = this.getConfigValue(type, 'onlyLabels') const staleLabel = this.getConfigValue(type, 'staleLabel') const exemptLabels = this.getConfigValue(type, 'exemptLabels') @@ -80,7 +80,9 @@ module.exports = class Stale { const query = queryParts.join(' ') const days = this.getConfigValue(type, 'days') || this.getConfigValue(type, 'daysUntilStale') - return this.search(type, days, query) + const results = await this.search(type, days, query) + + return results } getClosable (type) { From 37a48811e361301287c024883afa3b2cb552436b Mon Sep 17 00:00:00 2001 From: Sam Bostock Date: Sat, 14 Mar 2020 00:45:47 -0400 Subject: [PATCH 2/4] Add getPinnedNumbers function --- lib/stale.js | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/lib/stale.js b/lib/stale.js index 7de2bee..fb1c44f 100644 --- a/lib/stale.js +++ b/lib/stale.js @@ -85,6 +85,56 @@ module.exports = class Stale { return results } + async getPinnedNumbers(type) { + if (type === 'pulls') { + // Pull Requests cannot be pinned + return [] + } else if (type !== 'issues') { + throw new Error(`Unknown type: ${type}. Valid types are 'pulls' and 'issues'`) + } + + const { owner, repo } = this.config + + try { + // GitHub's v3 REST API doesn't support Pinned Issues; v4 GraphQL API does + const {data, errors} = await this.github.graphql( + ` + query Issues($owner: String!, $repo: String!) { + repository(owner: $owner, name: $repo) { + pinnedIssues(first: 100) { + nodes { + number + } + pageInfo { + # This should always be false, as only 3 issues can be pinned at the same time + hasNextPage + } + } + } + } + `, + { + owner, + repo, + headers: { + // Opt-in to Pinned Issues API preview + accept: 'application/vnd.github.elektra-preview+json' + }, + }, + ) + + if (errors && errors.length) { + throw new Error(errors[0].message) + } + + return data.repository.pinnedIssues.nodes.map(issue => issue.number) + } catch (error) { + this.logger.error(`Encountered an error while excluding pinned items for ${owner}/${repo}: ${error}`) + // In the event of an error, proceed as if no pinned issues found + return [] + } + } + getClosable (type) { const staleLabel = this.getConfigValue(type, 'staleLabel') const queryTypeRestriction = Stale.getQueryTypeRestriction(type) From 35083ee1c2c30e164a2703c8e494d90dd6dd989e Mon Sep 17 00:00:00 2001 From: Sam Bostock Date: Sat, 14 Mar 2020 00:46:43 -0400 Subject: [PATCH 3/4] Ignore pinned issues --- lib/stale.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/stale.js b/lib/stale.js index fb1c44f..ac45b83 100644 --- a/lib/stale.js +++ b/lib/stale.js @@ -82,7 +82,16 @@ module.exports = class Stale { const days = this.getConfigValue(type, 'days') || this.getConfigValue(type, 'daysUntilStale') const results = await this.search(type, days, query) - return results + const pinned = await this.getPinnedNumbers(type) + const nonPinned = results.data.items.filter(issue => pinned.includes(issue.number)) + return { + ...results, + data: { + ...results.data, + total_count: nonPinned.length, + items: nonPinned, + } + } } async getPinnedNumbers(type) { From d272cd661b730e1ab73dc714984e0160189e0ff0 Mon Sep 17 00:00:00 2001 From: Sam Bostock Date: Sat, 14 Mar 2020 00:58:08 -0400 Subject: [PATCH 4/4] [WIP] Add pending tests --- test/stale.test.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/stale.test.js b/test/stale.test.js index 40d2a9b..50ce87e 100644 --- a/test/stale.test.js +++ b/test/stale.test.js @@ -195,4 +195,12 @@ describe('stale', () => { expect(stale.getClosable).not.toHaveBeenCalled() } ) + + test('should ignore pinned issues', () => { + expect('Test implementation pending').toStrictEqual('Test implemented') + }) + + test('should log, but ignore errors fetching pinned issues', () => { + expect('Test implementation pending').toStrictEqual('Test implemented') + }) })