diff --git a/lib/modules/platform/azure/__snapshots__/index.spec.ts.snap b/lib/modules/platform/azure/__snapshots__/index.spec.ts.snap index 2ca73528d8f0b9..dabb70a924d0c0 100644 --- a/lib/modules/platform/azure/__snapshots__/index.spec.ts.snap +++ b/lib/modules/platform/azure/__snapshots__/index.spec.ts.snap @@ -30,22 +30,15 @@ exports[`modules/platform/azure/index createPr() should create and return a PR o } `; -exports[`modules/platform/azure/index createPr() when usePlatformAutomerge is set should create and return a PR object with auto-complete set 1`] = ` +exports[`modules/platform/azure/index createPr() should create and return an approved PR object 1`] = ` { - "autoCompleteSetBy": { - "id": "123", - }, "bodyStruct": { "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", }, - "completionOptions": { - "deleteSourceBranch": true, - "mergeCommitMessage": "The Title", - "squashMerge": true, - }, "createdAt": undefined, "createdBy": { - "id": "123", + "id": 123, + "url": "user-url", }, "number": 456, "pullRequestId": 456, @@ -53,19 +46,25 @@ exports[`modules/platform/azure/index createPr() when usePlatformAutomerge is se "sourceRefName": undefined, "state": "open", "targetBranch": undefined, - "title": "The Title", } `; -exports[`modules/platform/azure/index createPr() should create and return an approved PR object 1`] = ` +exports[`modules/platform/azure/index createPr() when usePlatformAutomerge is set should create and return a PR object with auto-complete set 1`] = ` { + "autoCompleteSetBy": { + "id": "123", + }, "bodyStruct": { "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", }, + "completionOptions": { + "deleteSourceBranch": true, + "mergeCommitMessage": "The Title", + "squashMerge": true, + }, "createdAt": undefined, "createdBy": { - "id": 123, - "url": "user-url", + "id": "123", }, "number": 456, "pullRequestId": 456, @@ -73,6 +72,7 @@ exports[`modules/platform/azure/index createPr() should create and return an app "sourceRefName": undefined, "state": "open", "targetBranch": undefined, + "title": "The Title", } `; @@ -280,6 +280,7 @@ exports[`modules/platform/azure/index updatePr(prNo, title, body, platformOption { "description": "Hello world again", "status": 2, + "targetRefName": undefined, "title": "The New Title", }, "1", @@ -302,6 +303,7 @@ exports[`modules/platform/azure/index updatePr(prNo, title, body, platformOption [ { "description": "Hello world again", + "targetRefName": undefined, "title": "The New Title", }, "1", @@ -315,6 +317,7 @@ exports[`modules/platform/azure/index updatePr(prNo, title, body, platformOption [ { "description": "Hello world again", + "targetRefName": "refs/heads/new_base", "title": "The New Title", }, "1", @@ -327,6 +330,7 @@ exports[`modules/platform/azure/index updatePr(prNo, title, body, platformOption [ [ { + "targetRefName": undefined, "title": "The New Title - autoclose", }, "1", diff --git a/lib/modules/platform/azure/index.spec.ts b/lib/modules/platform/azure/index.spec.ts index 440bc9d1df7d82..8ea5ac8f83ff99 100644 --- a/lib/modules/platform/azure/index.spec.ts +++ b/lib/modules/platform/azure/index.spec.ts @@ -906,6 +906,7 @@ describe('modules/platform/azure/index', () => { number: 1234, prTitle: 'The New Title', prBody: 'Hello world again', + targetBranch: 'new_base', }); expect(updatePullRequest.mock.calls).toMatchSnapshot(); }); diff --git a/lib/modules/platform/azure/index.ts b/lib/modules/platform/azure/index.ts index 37091f45a63692..256097cebfac0f 100644 --- a/lib/modules/platform/azure/index.ts +++ b/lib/modules/platform/azure/index.ts @@ -514,12 +514,14 @@ export async function updatePr({ prBody: body, state, platformOptions, + targetBranch, }: UpdatePrConfig): Promise { logger.debug(`updatePr(${prNo}, ${title}, body)`); const azureApiGit = await azureApi.gitApi(); const objToUpdate: GitPullRequest = { title, + targetRefName: getNewBranchName(targetBranch), }; if (body) { @@ -528,7 +530,9 @@ export async function updatePr({ if (state === 'open') { await azureApiGit.updatePullRequest( - { status: PullRequestStatus.Active }, + { + status: PullRequestStatus.Active, + }, config.repoId, prNo ); diff --git a/lib/modules/platform/bitbucket-server/index.spec.ts b/lib/modules/platform/bitbucket-server/index.spec.ts index 763d837ecf1220..5ab4eb98b50a6c 100644 --- a/lib/modules/platform/bitbucket-server/index.spec.ts +++ b/lib/modules/platform/bitbucket-server/index.spec.ts @@ -1417,6 +1417,7 @@ describe('modules/platform/bitbucket-server/index', () => { number: 5, prTitle: 'title', prBody: 'body', + targetBranch: 'new_base', }) ).toResolve(); }); diff --git a/lib/modules/platform/bitbucket-server/index.ts b/lib/modules/platform/bitbucket-server/index.ts index 43c44bf84c21ea..ae3436d70742aa 100644 --- a/lib/modules/platform/bitbucket-server/index.ts +++ b/lib/modules/platform/bitbucket-server/index.ts @@ -37,7 +37,7 @@ import type { RepoResult, UpdatePrConfig, } from '../types'; -import { repoFingerprint } from '../util'; +import { getNewBranchName, repoFingerprint } from '../util'; import { smartTruncate } from '../utils/pr-body'; import type { BbsConfig, @@ -851,6 +851,7 @@ export async function updatePr({ prBody: rawDescription, state, bitbucketInvalidReviewers, + targetBranch, }: UpdatePrConfig & { bitbucketInvalidReviewers: string[] | undefined; }): Promise { @@ -878,6 +879,9 @@ export async function updatePr({ (name: string) => !bitbucketInvalidReviewers?.includes(name) ) .map((name: string) => ({ user: { name } })), + toRef: { + id: getNewBranchName(targetBranch), + }, }, } ); diff --git a/lib/modules/platform/bitbucket/index.spec.ts b/lib/modules/platform/bitbucket/index.spec.ts index 40a37e4bf1ad8b..44d4cc8afc6b48 100644 --- a/lib/modules/platform/bitbucket/index.spec.ts +++ b/lib/modules/platform/bitbucket/index.spec.ts @@ -1225,7 +1225,12 @@ describe('modules/platform/bitbucket/index', () => { .put('/2.0/repositories/some/repo/pullrequests/5') .reply(200); await expect( - bitbucket.updatePr({ number: 5, prTitle: 'title', prBody: 'body' }) + bitbucket.updatePr({ + number: 5, + prTitle: 'title', + prBody: 'body', + targetBranch: 'new_base', + }) ).toResolve(); }); diff --git a/lib/modules/platform/bitbucket/index.ts b/lib/modules/platform/bitbucket/index.ts index 3bfee11463da09..81bd8c2341f1d4 100644 --- a/lib/modules/platform/bitbucket/index.ts +++ b/lib/modules/platform/bitbucket/index.ts @@ -905,6 +905,7 @@ export async function updatePr({ prTitle: title, prBody: description, state, + targetBranch, }: UpdatePrConfig): Promise { logger.debug(`updatePr(${prNo}, ${title}, body)`); // Updating a PR in Bitbucket will clear the reviewers if reviewers is not present @@ -922,6 +923,11 @@ export async function updatePr({ title, description: sanitize(description), reviewers: pr.reviewers, + destination: { + branch: { + name: targetBranch, + }, + }, }, } ); diff --git a/lib/modules/platform/gitea/index.spec.ts b/lib/modules/platform/gitea/index.spec.ts index a306b76a7bf4aa..cb010cd7650225 100644 --- a/lib/modules/platform/gitea/index.spec.ts +++ b/lib/modules/platform/gitea/index.spec.ts @@ -1230,6 +1230,22 @@ describe('modules/platform/gitea/index', () => { }); }); + it('should update pull target branch', async () => { + helper.searchPRs.mockResolvedValueOnce(mockPRs); + await initFakeRepo(); + await gitea.updatePr({ + number: 1, + prTitle: 'New Title', + targetBranch: 'New Base', + }); + + expect(helper.updatePR).toHaveBeenCalledTimes(1); + expect(helper.updatePR).toHaveBeenCalledWith(mockRepo.full_name, 1, { + title: 'New Title', + base: 'New Base', + }); + }); + it('should update pull request with title and body', async () => { helper.searchPRs.mockResolvedValueOnce(mockPRs); await initFakeRepo(); diff --git a/lib/modules/platform/gitea/index.ts b/lib/modules/platform/gitea/index.ts index cc1fdfda04a188..32f23555b854a7 100644 --- a/lib/modules/platform/gitea/index.ts +++ b/lib/modules/platform/gitea/index.ts @@ -622,6 +622,7 @@ const platform: Platform = { prTitle, prBody: body, state, + targetBranch, }: UpdatePrConfig): Promise { let title = prTitle; if ((await getPrList()).find((pr) => pr.number === number)?.isDraft) { @@ -630,6 +631,7 @@ const platform: Platform = { await helper.updatePR(config.repository, number, { title, + base: targetBranch, ...(body && { body }), ...(state && { state }), }); diff --git a/lib/modules/platform/gitea/types.ts b/lib/modules/platform/gitea/types.ts index de89f4f46a8765..bc6d78fc8cab8d 100644 --- a/lib/modules/platform/gitea/types.ts +++ b/lib/modules/platform/gitea/types.ts @@ -169,7 +169,6 @@ export interface IssueSearchParams { } export interface PRCreateParams extends PRUpdateParams { - base?: string; head?: string; } @@ -179,6 +178,7 @@ export interface PRUpdateParams { assignees?: string[]; labels?: number[]; state?: PRState; + base?: string; } export interface PRSearchParams { diff --git a/lib/modules/platform/gitlab/index.spec.ts b/lib/modules/platform/gitlab/index.spec.ts index 0530d65e250683..bc2cf66c4755a7 100644 --- a/lib/modules/platform/gitlab/index.spec.ts +++ b/lib/modules/platform/gitlab/index.spec.ts @@ -2190,6 +2190,35 @@ describe('modules/platform/gitlab/index', () => { ).toResolve(); }); + it('updates target branch of the PR', async () => { + await initPlatform('13.3.6-ee'); + httpMock + .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me' + ) + .reply(200, [ + { + iid: 1, + source_branch: 'branch-a', + title: 'branch a pr', + state: 'open', + target_branch: 'branch-b', + }, + ]) + .put('/api/v4/projects/undefined/merge_requests/1') + .reply(200); + await expect( + gitlab.updatePr({ + number: 1, + prTitle: 'title', + prBody: 'body', + state: 'closed', + targetBranch: 'branch-b', + }) + ).toResolve(); + }); + it('closes the PR', async () => { await initPlatform('13.3.6-ee'); httpMock diff --git a/lib/modules/platform/gitlab/index.ts b/lib/modules/platform/gitlab/index.ts index 88fbf9f1f0ce22..0580175deabe3f 100644 --- a/lib/modules/platform/gitlab/index.ts +++ b/lib/modules/platform/gitlab/index.ts @@ -701,6 +701,7 @@ export async function updatePr({ prBody: description, state, platformOptions, + targetBranch, }: UpdatePrConfig): Promise { let title = prTitle; if ((await getPrList()).find((pr) => pr.number === iid)?.isDraft) { @@ -718,6 +719,7 @@ export async function updatePr({ title, description: sanitize(description), ...(newState && { state_event: newState }), + target_branch: targetBranch, }, } );