Skip to content

Commit

Permalink
feat(github): Time threshold for PR reopening (#9392)
Browse files Browse the repository at this point in the history
  • Loading branch information
zharinov committed Apr 4, 2021
1 parent 5da6949 commit 3e9bfa2
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 2 deletions.
51 changes: 51 additions & 0 deletions lib/platform/github/__snapshots__/index.spec.ts.snap
Expand Up @@ -1873,6 +1873,57 @@ Array [
]
`;

exports[`platform/github getBranchPr(branchName) aborts reopen if PR is too old 1`] = `
Array [
Object {
"graphql": Object {
"query": Object {
"repository": Object {
"__args": Object {
"name": "repo",
"owner": "some",
},
"defaultBranchRef": Object {
"name": null,
"target": Object {
"oid": null,
},
},
"isArchived": null,
"isFork": null,
"mergeCommitAllowed": null,
"nameWithOwner": null,
"rebaseMergeAllowed": null,
"squashMergeAllowed": null,
},
},
},
"headers": Object {
"accept": "application/vnd.github.v3+json",
"accept-encoding": "gzip, deflate",
"authorization": "token abc123",
"content-length": "330",
"content-type": "application/json",
"host": "api.github.com",
"user-agent": "https://github.com/renovatebot/renovate",
},
"method": "POST",
"url": "https://api.github.com/graphql",
},
Object {
"headers": Object {
"accept": "application/vnd.github.v3+json",
"accept-encoding": "gzip, deflate",
"authorization": "token abc123",
"host": "api.github.com",
"user-agent": "https://github.com/renovatebot/renovate",
},
"method": "GET",
"url": "https://api.github.com/repos/some/repo/pulls?per_page=100&state=all",
},
]
`;

exports[`platform/github getBranchPr(branchName) aborts reopening if PR reopening fails 1`] = `
Array [
Object {
Expand Down
31 changes: 31 additions & 0 deletions lib/platform/github/index.spec.ts
@@ -1,4 +1,5 @@
import fs from 'fs-extra';
import { DateTime } from 'luxon';
import * as httpMock from '../../../test/http-mock';
import { mocked } from '../../../test/util';
import {
Expand Down Expand Up @@ -540,6 +541,9 @@ describe('platform/github', () => {
head: { ref: 'somebranch', repo: { full_name: 'some/repo' } },
title: 'old title - autoclosed',
state: PrState.Closed,
closed_at: DateTime.now()
.minus({ days: 6, hours: 23, minutes: 59, seconds: 59 })
.toISO(),
},
])
.post('/repos/some/repo/git/refs')
Expand All @@ -566,6 +570,31 @@ describe('platform/github', () => {
expect(pr).toMatchSnapshot();
expect(httpMock.getTrace()).toMatchSnapshot();
});
it('aborts reopen if PR is too old', async () => {
const scope = httpMock.scope(githubApiHost);
initRepoMock(scope, 'some/repo');
scope.get('/repos/some/repo/pulls?per_page=100&state=all').reply(200, [
{
number: 90,
head: { ref: 'somebranch', repo: { full_name: 'other/repo' } },
state: PrState.Open,
},
{
number: 91,
head: { ref: 'somebranch', repo: { full_name: 'some/repo' } },
title: 'old title - autoclosed',
state: PrState.Closed,
closed_at: DateTime.now().minus({ days: 7 }).toISO(),
},
]);

await github.initRepo({
repository: 'some/repo',
} as any);
const pr = await github.getBranchPr('somebranch');
expect(pr).toBeNull();
expect(httpMock.getTrace()).toMatchSnapshot();
});
it('aborts reopening if branch recreation fails', async () => {
const scope = httpMock.scope(githubApiHost);
initRepoMock(scope, 'some/repo');
Expand All @@ -577,6 +606,7 @@ describe('platform/github', () => {
head: { ref: 'somebranch', repo: { full_name: 'some/repo' } },
title: 'old title - autoclosed',
state: PrState.Closed,
closed_at: DateTime.now().minus({ minutes: 10 }).toISO(),
},
])
.post('/repos/some/repo/git/refs')
Expand All @@ -602,6 +632,7 @@ describe('platform/github', () => {
head: { ref: 'somebranch', repo: { full_name: 'some/repo' } },
title: 'old title - autoclosed',
state: PrState.Closed,
closed_at: DateTime.now().minus({ minutes: 10 }).toISO(),
},
])
.post('/repos/some/repo/git/refs')
Expand Down
17 changes: 15 additions & 2 deletions lib/platform/github/index.ts
@@ -1,6 +1,7 @@
import URL from 'url';
import is from '@sindresorhus/is';
import delay from 'delay';
import { DateTime } from 'luxon';
import {
PLATFORM_INTEGRATION_UNAUTHORIZED,
REPOSITORY_ACCESS_FORBIDDEN,
Expand Down Expand Up @@ -759,7 +760,7 @@ export async function getPrList(): Promise<Pr[]> {
? /* istanbul ignore next */ PrState.Merged
: pr.state,
createdAt: pr.created_at,
closed_at: pr.closed_at,
closedAt: pr.closed_at,
sourceRepo: pr.head?.repo?.full_name,
} as never)
);
Expand Down Expand Up @@ -788,6 +789,8 @@ export async function findPr({
return pr;
}

const REOPEN_THRESHOLD_MILLIS = 1000 * 60 * 60 * 24 * 7;

// Returns the Pull Request for a branch. Null if not exists.
export async function getBranchPr(branchName: string): Promise<Pr | null> {
// istanbul ignore if
Expand All @@ -807,7 +810,17 @@ export async function getBranchPr(branchName: string): Promise<Pr | null> {
branchName,
state: PrState.Closed,
});
if (autoclosedPr?.title?.endsWith(' - autoclosed')) {
if (
autoclosedPr?.title?.endsWith(' - autoclosed') &&
autoclosedPr?.closedAt
) {
const closedMillisAgo = DateTime.fromISO(autoclosedPr.closedAt)
.diffNow()
.negate()
.toMillis();
if (closedMillisAgo > REOPEN_THRESHOLD_MILLIS) {
return null;
}
logger.debug({ autoclosedPr }, 'Found autoclosed PR for branch');
const { sha, number } = autoclosedPr;
try {
Expand Down
1 change: 1 addition & 0 deletions lib/platform/types.ts
Expand Up @@ -47,6 +47,7 @@ export interface Pr {
canMerge?: boolean;
canMergeReason?: string;
createdAt?: string;
closedAt?: string;
displayNumber?: string;
hasAssignees?: boolean;
hasReviewers?: boolean;
Expand Down

0 comments on commit 3e9bfa2

Please sign in to comment.