Skip to content

Commit 5f16355

Browse files
fix(reconfigure/pr): find reconfigure pr separately (#25954)
Co-authored-by: Rhys Arkins <rhys@arkins.net>
1 parent 831fba0 commit 5f16355

File tree

12 files changed

+280
-7
lines changed

12 files changed

+280
-7
lines changed

lib/modules/platform/bitbucket-server/index.spec.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,50 @@ describe('modules/platform/bitbucket-server/index', () => {
13061306
}),
13071307
).toBeNull();
13081308
});
1309+
1310+
it('finds pr from other authors', async () => {
1311+
const scope = await initRepo();
1312+
scope
1313+
.get(
1314+
`${urlPath}/rest/api/1.0/projects/SOME/repos/repo/pull-requests?state=OPEN&direction=outgoing&at=refs/heads/branch&limit=1`,
1315+
)
1316+
.reply(200, {
1317+
isLastPage: true,
1318+
values: [prMock(url, 'SOME', 'repo')],
1319+
});
1320+
expect(
1321+
await bitbucket.findPr({
1322+
branchName: 'branch',
1323+
state: 'open',
1324+
includeOtherAuthors: true,
1325+
}),
1326+
).toMatchObject({
1327+
number: 5,
1328+
sourceBranch: 'userName1/pullRequest5',
1329+
targetBranch: 'master',
1330+
title: 'title',
1331+
state: 'open',
1332+
});
1333+
});
1334+
1335+
it('returns null if no pr found - (includeOtherAuthors)', async () => {
1336+
const scope = await initRepo();
1337+
scope
1338+
.get(
1339+
`${urlPath}/rest/api/1.0/projects/SOME/repos/repo/pull-requests?state=OPEN&direction=outgoing&at=refs/heads/branch&limit=1`,
1340+
)
1341+
.reply(200, {
1342+
isLastPage: true,
1343+
values: [],
1344+
});
1345+
1346+
const pr = await bitbucket.findPr({
1347+
branchName: 'branch',
1348+
state: 'open',
1349+
includeOtherAuthors: true,
1350+
});
1351+
expect(pr).toBeNull();
1352+
});
13091353
});
13101354

13111355
describe('createPr()', () => {

lib/modules/platform/bitbucket-server/index.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,34 @@ export async function findPr({
324324
prTitle,
325325
state = 'all',
326326
refreshCache,
327+
includeOtherAuthors,
327328
}: FindPRConfig): Promise<Pr | null> {
328329
logger.debug(`findPr(${branchName}, "${prTitle!}", "${state}")`);
330+
331+
if (includeOtherAuthors) {
332+
// PR might have been created by anyone, so don't use the cached Renovate PR list
333+
const searchParams: Record<string, string> = {
334+
state: 'OPEN',
335+
};
336+
searchParams['direction'] = 'outgoing';
337+
searchParams['at'] = `refs/heads/${branchName}`;
338+
339+
const query = getQueryString(searchParams);
340+
const prs = await utils.accumulateValues(
341+
`./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}/pull-requests?${query}`,
342+
'get',
343+
{},
344+
1, // only fetch the latest pr
345+
);
346+
347+
if (!prs.length) {
348+
logger.debug(`No PR found for branch ${branchName}`);
349+
return null;
350+
}
351+
352+
return utils.prInfo(prs[0]);
353+
}
354+
329355
const prList = await getPrList(refreshCache);
330356
const pr = prList.find(isRelevantPr(branchName, prTitle, state));
331357
if (pr) {

lib/modules/platform/bitbucket/index.spec.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,46 @@ describe('modules/platform/bitbucket/index', () => {
954954
});
955955
expect(pr?.number).toBe(5);
956956
});
957+
958+
it('finds pr from other authors', async () => {
959+
const scope = await initRepoMock();
960+
scope
961+
.get(
962+
'/2.0/repositories/some/repo/pullrequests?q=source.branch.name="branch"&state=open',
963+
)
964+
.reply(200, { values: [pr] });
965+
expect(
966+
await bitbucket.findPr({
967+
branchName: 'branch',
968+
state: 'open',
969+
includeOtherAuthors: true,
970+
}),
971+
).toMatchObject({
972+
number: 5,
973+
sourceBranch: 'branch',
974+
targetBranch: 'master',
975+
title: 'title',
976+
state: 'open',
977+
});
978+
});
979+
980+
it('returns null if no open pr exists - (includeOtherAuthors)', async () => {
981+
const scope = await initRepoMock();
982+
scope
983+
.get(
984+
'/2.0/repositories/some/repo/pullrequests?q=source.branch.name="branch"&state=open',
985+
)
986+
.reply(200, {
987+
values: [],
988+
});
989+
990+
const pr = await bitbucket.findPr({
991+
branchName: 'branch',
992+
state: 'open',
993+
includeOtherAuthors: true,
994+
});
995+
expect(pr).toBeNull();
996+
});
957997
});
958998

959999
describe('createPr()', () => {

lib/modules/platform/bitbucket/index.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,26 @@ export async function findPr({
301301
branchName,
302302
prTitle,
303303
state = 'all',
304+
includeOtherAuthors,
304305
}: FindPRConfig): Promise<Pr | null> {
305306
logger.debug(`findPr(${branchName}, ${prTitle}, ${state})`);
307+
308+
if (includeOtherAuthors) {
309+
// PR might have been created by anyone, so don't use the cached Renovate PR list
310+
const prs = (
311+
await bitbucketHttp.getJson<PagedResult<PrResponse>>(
312+
`/2.0/repositories/${config.repository}/pullrequests?q=source.branch.name="${branchName}"&state=open`,
313+
)
314+
).body.values;
315+
316+
if (prs.length === 0) {
317+
logger.debug(`No PR found for branch ${branchName}`);
318+
return null;
319+
}
320+
321+
return utils.prInfo(prs[0]);
322+
}
323+
306324
const prList = await getPrList();
307325
const pr = prList.find(
308326
(p) =>

lib/modules/platform/gitea/index.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type { BranchStatus } from '../../../types';
1313
import { parseJson } from '../../../util/common';
1414
import * as git from '../../../util/git';
1515
import { setBaseUrl } from '../../../util/http/gitea';
16+
import { regEx } from '../../../util/regex';
1617
import { sanitize } from '../../../util/sanitize';
1718
import { ensureTrailingSlash } from '../../../util/url';
1819
import { getPrBodyStruct, hashBody } from '../pr-body';
@@ -70,6 +71,7 @@ interface GiteaRepoConfig {
7071
export const id = 'gitea';
7172

7273
const DRAFT_PREFIX = 'WIP: ';
74+
const reconfigurePrRegex = regEx(/reconfigure$/g);
7375

7476
const defaults = {
7577
hostType: 'gitea',
@@ -109,7 +111,12 @@ function toRenovatePR(data: PR): Pr | null {
109111
}
110112

111113
const createdBy = data.user?.username;
112-
if (createdBy && botUserName && createdBy !== botUserName) {
114+
if (
115+
createdBy &&
116+
botUserName &&
117+
!reconfigurePrRegex.test(data.head.label) &&
118+
createdBy !== botUserName
119+
) {
113120
return null;
114121
}
115122

@@ -493,6 +500,7 @@ const platform: Platform = {
493500
branchName,
494501
prTitle: title,
495502
state = 'all',
503+
includeOtherAuthors,
496504
}: FindPRConfig): Promise<Pr | null> {
497505
logger.debug(`findPr(${branchName}, ${title!}, ${state})`);
498506
const prList = await platform.getPrList();

lib/modules/platform/github/index.spec.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2428,6 +2428,51 @@ describe('modules/platform/github/index', () => {
24282428
res = await github.findPr({ branchName: 'branch-b' });
24292429
expect(res).toBeNull();
24302430
});
2431+
2432+
it('finds pr from other authors', async () => {
2433+
const scope = httpMock.scope(githubApiHost);
2434+
initRepoMock(scope, 'some/repo');
2435+
scope
2436+
.get('/repos/some/repo/pulls?head=some/repo:branch&state=open')
2437+
.reply(200, [
2438+
{
2439+
number: 1,
2440+
head: { ref: 'branch-a', repo: { full_name: 'some/repo' } },
2441+
title: 'branch a pr',
2442+
state: 'open',
2443+
},
2444+
]);
2445+
await github.initRepo({ repository: 'some/repo' });
2446+
expect(
2447+
await github.findPr({
2448+
branchName: 'branch',
2449+
state: 'open',
2450+
includeOtherAuthors: true,
2451+
}),
2452+
).toMatchObject({
2453+
number: 1,
2454+
sourceBranch: 'branch-a',
2455+
sourceRepo: 'some/repo',
2456+
state: 'open',
2457+
title: 'branch a pr',
2458+
updated_at: undefined,
2459+
});
2460+
});
2461+
2462+
it('returns null if no pr found - (includeOtherAuthors)', async () => {
2463+
const scope = httpMock.scope(githubApiHost);
2464+
initRepoMock(scope, 'some/repo');
2465+
scope
2466+
.get('/repos/some/repo/pulls?head=some/repo:branch&state=open')
2467+
.reply(200, []);
2468+
await github.initRepo({ repository: 'some/repo' });
2469+
const pr = await github.findPr({
2470+
branchName: 'branch',
2471+
state: 'open',
2472+
includeOtherAuthors: true,
2473+
});
2474+
expect(pr).toBeNull();
2475+
});
24312476
});
24322477

24332478
describe('createPr()', () => {

lib/modules/platform/github/index.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,8 +798,26 @@ export async function findPr({
798798
branchName,
799799
prTitle,
800800
state = 'all',
801+
includeOtherAuthors,
801802
}: FindPRConfig): Promise<GhPr | null> {
802803
logger.debug(`findPr(${branchName}, ${prTitle}, ${state})`);
804+
805+
if (includeOtherAuthors) {
806+
const repo = config.parentRepo ?? config.repository;
807+
// PR might have been created by anyone, so don't use the cached Renovate PR list
808+
const response = await githubApi.getJson<GhRestPr[]>(
809+
`repos/${repo}/pulls?head=${repo}:${branchName}&state=open`,
810+
);
811+
812+
const { body: prList } = response;
813+
if (!prList.length) {
814+
logger.debug(`No PR found for branch ${branchName}`);
815+
return null;
816+
}
817+
818+
return coerceRestPr(prList[0]);
819+
}
820+
803821
const prList = await getPrList();
804822
const pr = prList.find((p) => {
805823
if (p.sourceBranch !== branchName) {

lib/modules/platform/gitlab/index.spec.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,6 +1678,49 @@ describe('modules/platform/gitlab/index', () => {
16781678
});
16791679
expect(res).toBeDefined();
16801680
});
1681+
1682+
it('finds pr from other authors', async () => {
1683+
httpMock
1684+
.scope(gitlabApiHost)
1685+
.get(
1686+
'/api/v4/projects/undefined/merge_requests?source_branch=branch&state=opened',
1687+
)
1688+
.reply(200, [
1689+
{
1690+
iid: 1,
1691+
source_branch: 'branch',
1692+
title: 'branch a pr',
1693+
state: 'opened',
1694+
},
1695+
]);
1696+
expect(
1697+
await gitlab.findPr({
1698+
branchName: 'branch',
1699+
state: 'open',
1700+
includeOtherAuthors: true,
1701+
}),
1702+
).toMatchObject({
1703+
number: 1,
1704+
sourceBranch: 'branch',
1705+
state: 'open',
1706+
title: 'branch a pr',
1707+
});
1708+
});
1709+
1710+
it('returns null if no pr found - (includeOtherAuthors)', async () => {
1711+
httpMock
1712+
.scope(gitlabApiHost)
1713+
.get(
1714+
'/api/v4/projects/undefined/merge_requests?source_branch=branch&state=opened',
1715+
)
1716+
.reply(200, []);
1717+
const pr = await gitlab.findPr({
1718+
branchName: 'branch',
1719+
state: 'open',
1720+
includeOtherAuthors: true,
1721+
});
1722+
expect(pr).toBeNull();
1723+
});
16811724
});
16821725

16831726
async function initPlatform(gitlabVersion: string) {

lib/modules/platform/gitlab/index.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,8 +863,36 @@ export async function findPr({
863863
branchName,
864864
prTitle,
865865
state = 'all',
866+
includeOtherAuthors,
866867
}: FindPRConfig): Promise<Pr | null> {
867868
logger.debug(`findPr(${branchName}, ${prTitle!}, ${state})`);
869+
870+
if (includeOtherAuthors) {
871+
// PR might have been created by anyone, so don't use the cached Renovate MR list
872+
const response = await gitlabApi.getJson<GitLabMergeRequest[]>(
873+
`projects/${config.repository}/merge_requests?source_branch=${branchName}&state=opened`,
874+
);
875+
876+
const { body: mrList } = response;
877+
if (!mrList.length) {
878+
logger.debug(`No MR found for branch ${branchName}`);
879+
return null;
880+
}
881+
882+
// return the latest merge request
883+
const mr = mrList[0];
884+
885+
// only pass necessary info
886+
const pr: GitlabPr = {
887+
sourceBranch: mr.source_branch,
888+
number: mr.iid,
889+
state: 'open',
890+
title: mr.title,
891+
};
892+
893+
return massagePr(pr);
894+
}
895+
868896
const prList = await getPrList();
869897
return (
870898
prList.find(

lib/modules/platform/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ export interface FindPRConfig {
143143
state?: 'open' | 'closed' | '!open' | 'all';
144144
refreshCache?: boolean;
145145
targetBranch?: string | null;
146+
includeOtherAuthors?: boolean;
146147
}
147148
export interface MergePRConfig {
148149
branchName?: string;

0 commit comments

Comments
 (0)