From f20953b561b1f8be87a2e3b8bb726fce81c1b303 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Thu, 17 Aug 2023 17:21:21 +0545 Subject: [PATCH 01/60] implement update labels logic in github, gitlab, gitea --- lib/modules/platform/azure/index.spec.ts | 3 +- lib/modules/platform/azure/index.ts | 3 +- .../__snapshots__/index.spec.ts.snap | 2 + .../platform/bitbucket-server/index.spec.ts | 1 + .../platform/bitbucket-server/index.ts | 3 +- lib/modules/platform/bitbucket/index.spec.ts | 4 +- lib/modules/platform/bitbucket/index.ts | 3 +- lib/modules/platform/codecommit/index.spec.ts | 3 +- lib/modules/platform/codecommit/index.ts | 3 +- .../platform/gitea/gitea-helper.spec.ts | 17 +++++++ lib/modules/platform/gitea/gitea-helper.ts | 15 ++++++ lib/modules/platform/gitea/index.spec.ts | 35 +++++++++++++ lib/modules/platform/gitea/index.ts | 27 +++++++++- lib/modules/platform/github/index.spec.ts | 38 ++++++++++++++ lib/modules/platform/github/index.ts | 16 ++++++ lib/modules/platform/gitlab/index.spec.ts | 35 +++++++++++++ lib/modules/platform/gitlab/index.ts | 9 ++++ lib/modules/platform/pr-body.ts | 13 +++++ lib/modules/platform/types.ts | 4 ++ .../repository/update/pr/body/index.ts | 5 ++ lib/workers/repository/update/pr/index.ts | 51 ++++++++++++++++++- 21 files changed, 280 insertions(+), 10 deletions(-) diff --git a/lib/modules/platform/azure/index.spec.ts b/lib/modules/platform/azure/index.spec.ts index 28c9879836b6d1..bfe33ce23806c8 100644 --- a/lib/modules/platform/azure/index.spec.ts +++ b/lib/modules/platform/azure/index.spec.ts @@ -1223,7 +1223,8 @@ describe('modules/platform/azure/index', () => { it('returns updated pr body', () => { const prBody = '\n---\n\n - [ ] rebase\n' + - 'plus also [a link](https://github.com/foo/bar/issues/5)'; + 'plus also [a link](https://github.com/foo/bar/issues/5)' + + ``; expect(azure.massageMarkdown(prBody)).toBe( 'plus also [a link](https://github.com/foo/bar/issues/5)' ); diff --git a/lib/modules/platform/azure/index.ts b/lib/modules/platform/azure/index.ts index 6080912f68a6d8..41321acb00b6c2 100644 --- a/lib/modules/platform/azure/index.ts +++ b/lib/modules/platform/azure/index.ts @@ -782,7 +782,8 @@ export function massageMarkdown(input: string): string { 'renaming the PR to start with "rebase!"' ) .replace(regEx(`\n---\n\n.*?.*?\n`), '') - .replace(regEx(//g), ''); + .replace(regEx(//g), '') + .replace(regEx(//g), ''); } /* istanbul ignore next */ diff --git a/lib/modules/platform/bitbucket-server/__snapshots__/index.spec.ts.snap b/lib/modules/platform/bitbucket-server/__snapshots__/index.spec.ts.snap index 76d488bcf8bbf9..6953dafe479665 100644 --- a/lib/modules/platform/bitbucket-server/__snapshots__/index.spec.ts.snap +++ b/lib/modules/platform/bitbucket-server/__snapshots__/index.spec.ts.snap @@ -198,6 +198,7 @@ exports[`modules/platform/bitbucket-server/index endpoint with no path massageMa Empty comment. + Followed by some information. " `; @@ -402,6 +403,7 @@ exports[`modules/platform/bitbucket-server/index endpoint with path massageMarkd Empty comment. + Followed by some information. " `; diff --git a/lib/modules/platform/bitbucket-server/index.spec.ts b/lib/modules/platform/bitbucket-server/index.spec.ts index f2b5f4357a2b8d..e09dd61526362e 100644 --- a/lib/modules/platform/bitbucket-server/index.spec.ts +++ b/lib/modules/platform/bitbucket-server/index.spec.ts @@ -1724,6 +1724,7 @@ describe('modules/platform/bitbucket-server/index', () => { Empty comment. + Followed by some information. `); expect(prBody).toMatchSnapshot(); diff --git a/lib/modules/platform/bitbucket-server/index.ts b/lib/modules/platform/bitbucket-server/index.ts index f82d891865b292..32c17e8e66c400 100644 --- a/lib/modules/platform/bitbucket-server/index.ts +++ b/lib/modules/platform/bitbucket-server/index.ts @@ -983,5 +983,6 @@ export function massageMarkdown(input: string): string { .replace(regEx(/<\/?summary>/g), '**') .replace(regEx(/<\/?details>/g), '') .replace(regEx(`\n---\n\n.*?.*?(\n|$)`), '') - .replace(regEx('', 'g'), ''); + .replace(regEx('', 'g'), '') + .replace(regEx(//g), ''); } diff --git a/lib/modules/platform/bitbucket/index.spec.ts b/lib/modules/platform/bitbucket/index.spec.ts index 603bb2b5e91c86..cff09dfd558618 100644 --- a/lib/modules/platform/bitbucket/index.spec.ts +++ b/lib/modules/platform/bitbucket/index.spec.ts @@ -1370,8 +1370,8 @@ describe('modules/platform/bitbucket/index', () => { const prBody = '
foo\n
\n\n
text' + '\n---\n\n - [ ] rebase\n' + - '\n\n
\n\n
\n
'; - + '\n\n\n\n\n' + + ``; expect(bitbucket.massageMarkdown(prBody)).toMatchSnapshot(); }); }); diff --git a/lib/modules/platform/bitbucket/index.ts b/lib/modules/platform/bitbucket/index.ts index f57c625b029e81..8886cf46ccfc11 100644 --- a/lib/modules/platform/bitbucket/index.ts +++ b/lib/modules/platform/bitbucket/index.ts @@ -564,7 +564,8 @@ export function massageMarkdown(input: string): string { .replace(regEx(/<\/?(details|blockquote)>/g), '') .replace(regEx(`\n---\n\n.*?.*?\n`), '') .replace(regEx(/\]\(\.\.\/pull\//g), '](../../pull-requests/') - .replace(regEx(//g), ''); + .replace(regEx(//g), '') + .replace(regEx(//g), ''); } export async function ensureIssue({ diff --git a/lib/modules/platform/codecommit/index.spec.ts b/lib/modules/platform/codecommit/index.spec.ts index 6dfc43483ab9df..a9a28826d34851 100644 --- a/lib/modules/platform/codecommit/index.spec.ts +++ b/lib/modules/platform/codecommit/index.spec.ts @@ -49,7 +49,8 @@ describe('modules/platform/codecommit/index', () => { it('validates massageMarkdown functionality', () => { const newStr = codeCommit.massageMarkdown( - '
foobar
text
\n' + '
foobar
text
\n' + + '' ); expect(newStr).toBe( '**foo**bartext\n[//]: # ()' diff --git a/lib/modules/platform/codecommit/index.ts b/lib/modules/platform/codecommit/index.ts index dbc6b4109a961d..f60c550e799f2c 100644 --- a/lib/modules/platform/codecommit/index.ts +++ b/lib/modules/platform/codecommit/index.ts @@ -320,7 +320,8 @@ export function massageMarkdown(input: string): string { .replace( regEx(/(?)/g), '[//]: # ($)' - ); + ) + .replace(regEx(//g), ''); } export async function getJsonFile( diff --git a/lib/modules/platform/gitea/gitea-helper.spec.ts b/lib/modules/platform/gitea/gitea-helper.spec.ts index 098699d88a977e..cb289ec43058d2 100644 --- a/lib/modules/platform/gitea/gitea-helper.spec.ts +++ b/lib/modules/platform/gitea/gitea-helper.spec.ts @@ -2,6 +2,7 @@ import * as httpMock from '../../../../test/http-mock'; import { setBaseUrl } from '../../../util/http/gitea'; import { toBase64 } from '../../../util/string'; import { + assignLabel, closeIssue, closePR, createComment, @@ -603,6 +604,22 @@ describe('modules/platform/gitea/gitea-helper', () => { }); }); + describe('assignLabel', () => { + it('should call /api/v1/repos/[repo]/issues/[issue]/labels endpoint', async () => { + httpMock + .scope(baseUrl) + .patch(`/repos/${mockRepo.full_name}/issues/${mockIssue.number}/labels`) + .reply(200); + + const res = await assignLabel( + mockRepo.full_name, + mockIssue.number, + mockLabel.id + ); + expect(res).toBeUndefined(); + }); + }); + describe('createComment', () => { it('should call /api/v1/repos/[repo]/issues/[issue]/comments endpoint', async () => { httpMock diff --git a/lib/modules/platform/gitea/gitea-helper.ts b/lib/modules/platform/gitea/gitea-helper.ts index 188211d6028685..86d37752a72c90 100644 --- a/lib/modules/platform/gitea/gitea-helper.ts +++ b/lib/modules/platform/gitea/gitea-helper.ts @@ -306,6 +306,21 @@ export async function unassignLabel( await giteaHttp.deleteJson(url, options); } +export async function assignLabel( + repoPath: string, + issue: number, + label: number, + options?: GiteaHttpOptions +): Promise { + const url = `${API_PATH}/repos/${repoPath}/issues/${issue}/labels`; + await giteaHttp.patchJson(url, { + ...options, + body: { + labels: [label], + }, + }); +} + export async function createComment( repoPath: string, issue: number, diff --git a/lib/modules/platform/gitea/index.spec.ts b/lib/modules/platform/gitea/index.spec.ts index ce8604ed61ebec..c69ac11cfcc7d7 100644 --- a/lib/modules/platform/gitea/index.spec.ts +++ b/lib/modules/platform/gitea/index.spec.ts @@ -1290,6 +1290,41 @@ describe('modules/platform/gitea/index', () => { state: 'closed', }); }); + + it('should add and remove labels', async () => { + helper.getRepoLabels.mockResolvedValueOnce([ + { id: 1, name: 'old_label', description: 'its a me', color: '#000000' }, + { + id: 2, + name: 'new_label', + description: 'labelario', + color: '#ffffff', + }, + ]); + helper.getOrgLabels.mockResolvedValueOnce([]); + helper.searchPRs.mockResolvedValueOnce(mockPRs); + await initFakeRepo(); + await gitea.updatePr({ + number: 1, + prTitle: 'New Title', + prBody: 'New Body', + state: 'closed', + addLabels: ['new_label'], + removeLabels: ['new_label'], + }); + + expect(helper.updatePR).toHaveBeenCalledWith(mockRepo.full_name, 1, { + title: 'New Title', + body: 'New Body', + state: 'closed', + }); + expect(logger.debug).toHaveBeenCalledWith( + 'Deleting label old_label from Issue #1' + ); + expect(logger.debug).toHaveBeenCalledWith( + 'Adding label new_label to Issue #1' + ); + }); }); describe('mergePr', () => { diff --git a/lib/modules/platform/gitea/index.ts b/lib/modules/platform/gitea/index.ts index a07fccbbed4ebc..2ef8fd054f0cc5 100644 --- a/lib/modules/platform/gitea/index.ts +++ b/lib/modules/platform/gitea/index.ts @@ -622,11 +622,14 @@ const platform: Platform = { number, prTitle, prBody: body, + addLabels, + removeLabels, state, targetBranch, }: UpdatePrConfig): Promise { let title = prTitle; - if ((await getPrList()).find((pr) => pr.number === number)?.isDraft) { + const pr = (await getPrList()).find((pr) => pr.number === number); + if (pr?.isDraft) { title = DRAFT_PREFIX + title; } @@ -639,6 +642,17 @@ const platform: Platform = { prUpdateParams.base = targetBranch; } + if (is.nonEmptyArray(addLabels)) { + for (const label of addLabels) { + await addLabel!(number, label); + } + } + + if (is.nonEmptyArray(removeLabels)) { + for (const label of removeLabels) { + await deleteLabel(number, label); + } + } await helper.updatePR(config.repository, number, prUpdateParams); }, @@ -839,6 +853,16 @@ const platform: Platform = { } }, + async addLabel(issue: number, labelName: string): Promise { + logger.debug(`Adding label ${labelName} to Issue #${issue}`); + const label = await lookupLabelByName(labelName); + if (label) { + await helper.assignLabel(config.repository, issue, label); + } else { + logger.warn({ issue, labelName }, 'Failed to lookup label for addition'); + } + }, + getRepoForceRebase(): Promise { return Promise.resolve(false); }, @@ -959,6 +983,7 @@ const platform: Platform = { /* eslint-disable @typescript-eslint/unbound-method */ export const { addAssignees, + addLabel, addReviewers, createPr, deleteLabel, diff --git a/lib/modules/platform/github/index.spec.ts b/lib/modules/platform/github/index.spec.ts index c4f0cd59d93578..b33accbe5d9165 100644 --- a/lib/modules/platform/github/index.spec.ts +++ b/lib/modules/platform/github/index.spec.ts @@ -2868,6 +2868,44 @@ describe('modules/platform/github/index', () => { await expect(github.updatePr(pr)).toResolve(); }); + + it('should add and remove labels', async () => { + const pr: UpdatePrConfig = { + number: 1234, + prTitle: 'The New Title', + prBody: 'Hello world again', + state: 'closed', + targetBranch: 'new_base', + addLabels: ['new_label'], + removeLabels: ['old_label'], + }; + const scope = httpMock.scope(githubApiHost); + initRepoMock(scope, 'some/repo'); + await github.initRepo({ repository: 'some/repo' }); + scope + .patch('/repos/some/repo/pulls/1234') + .reply(200, { + number: 91, + base: { sha: '1234' }, + head: { ref: 'somebranch', repo: { full_name: 'some/repo' } }, + state: 'open', + title: 'old title', + updated_at: '01-09-2022', + body: '', // equivalent to labels array : ['old_label] + }) + .post('/repos/some/repo/issues/1234/labels') + .reply(200, pr) + .delete('/repos/some/repo/issues/1234/labels/old_label') + .reply(200, pr); + + await expect(github.updatePr(pr)).toResolve(); + expect(logger.logger.debug).toHaveBeenCalledWith( + `Adding labels 'new_label' to #1234` + ); + expect(logger.logger.debug).toHaveBeenCalledWith( + `Deleting label old_label from #1234` + ); + }); }); describe('mergePr(prNo)', () => { diff --git a/lib/modules/platform/github/index.ts b/lib/modules/platform/github/index.ts index 29db5631d98758..d2a95254a91623 100644 --- a/lib/modules/platform/github/index.ts +++ b/lib/modules/platform/github/index.ts @@ -1600,6 +1600,8 @@ export async function updatePr({ number: prNo, prTitle: title, prBody: rawBody, + addLabels: labelsToAdd, + removeLabels, state, targetBranch, }: UpdatePrConfig): Promise { @@ -1622,12 +1624,26 @@ export async function updatePr({ if (config.forkToken) { options.token = config.forkToken; } + try { + // add and remove labels before updating pr body because if by some mishap + // labels aren't changed then pr body will have wrong labelsHash + if (labelsToAdd) { + await addLabels(prNo, labelsToAdd); + } + + if (removeLabels) { + for (const label of removeLabels) { + await deleteLabel(prNo, label); + } + } + const { body: ghPr } = await githubApi.patchJson( `repos/${config.parentRepo ?? config.repository}/pulls/${prNo}`, options ); const result = coerceRestPr(ghPr); + cachePr(result); logger.debug(`PR updated...prNo: ${prNo}`); } catch (err) /* istanbul ignore next */ { diff --git a/lib/modules/platform/gitlab/index.spec.ts b/lib/modules/platform/gitlab/index.spec.ts index 03157d7b30ed08..001de257ad74b0 100644 --- a/lib/modules/platform/gitlab/index.spec.ts +++ b/lib/modules/platform/gitlab/index.spec.ts @@ -2431,6 +2431,41 @@ describe('modules/platform/gitlab/index', () => { }) ).toResolve(); }); + + it('adds and removes labels', 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', + description: ``, // equivallent to labels array : ['old_label'] + }, + ]) + .put('/api/v4/projects/undefined/merge_requests/1') + .reply(200); + await expect( + gitlab.updatePr({ + number: 1, + prTitle: 'title', + prBody: 'body', + state: 'closed', + labels: ['new_label'], + }) + ).toResolve(); + expect(logger.debug).toHaveBeenCalledWith( + `Assigning labels 'new_label' to #1` + ); + expect(logger.debug).toHaveBeenCalledWith( + `Unassigning labels 'old_label' from #1` + ); + }); }); describe('mergePr(pr)', () => { diff --git a/lib/modules/platform/gitlab/index.ts b/lib/modules/platform/gitlab/index.ts index ae5ffaab111b42..ccd9047ab73c10 100644 --- a/lib/modules/platform/gitlab/index.ts +++ b/lib/modules/platform/gitlab/index.ts @@ -719,6 +719,8 @@ export async function updatePr({ number: iid, prTitle, prBody: description, + addLabels, + removeLabels, state, platformOptions, targetBranch, @@ -741,6 +743,13 @@ export async function updatePr({ if (targetBranch) { body.target_branch = targetBranch; } + if (addLabels) { + body.add_labels = addLabels; + } + + if (removeLabels) { + body.remove_labels = removeLabels; + } await gitlabApi.putJson( `projects/${config.repository}/merge_requests/${iid}`, diff --git a/lib/modules/platform/pr-body.ts b/lib/modules/platform/pr-body.ts index 97dc74b0282c44..3bc41a02e6dd61 100644 --- a/lib/modules/platform/pr-body.ts +++ b/lib/modules/platform/pr-body.ts @@ -15,6 +15,7 @@ const renovateConfigHashRe = regEx( ); const prCheckboxRe = regEx(/- (?\[[\sx]]) /); +const prLabelsRe = regEx(/\n?\n?/); function noWhitespaceOrHeadings(input: string): string { return input.replace(regEx(/\r?\n|\r|\s|#/g), ''); @@ -43,6 +44,14 @@ function isRebaseRequested(body: string): boolean | undefined { return match.groups?.checkbox === '[x]'; } +function getLabels(body: string): string | undefined { + const match = prLabelsRe.exec(body); + if (!match) { + return undefined; + } + return match.groups?.labels; +} + export function getRenovateDebugPayload(body: string): string | undefined { const match = prDebugDataRe.exec(body); return match?.groups?.payload; @@ -61,6 +70,10 @@ export function getPrBodyStruct( const result: PrBodyStruct = { hash }; const rebaseRequested = isRebaseRequested(body); + const labelsHash = getLabels(body); + if (labelsHash) { + result.labelsHash = labelsHash; + } if (!is.undefined(rebaseRequested)) { result.rebaseRequested = rebaseRequested; diff --git a/lib/modules/platform/types.ts b/lib/modules/platform/types.ts index 3962a08b8dee2a..5dff4ce87f0dad 100644 --- a/lib/modules/platform/types.ts +++ b/lib/modules/platform/types.ts @@ -58,6 +58,7 @@ export interface PrBodyStruct { rawConfigHash?: string; rebaseRequested?: boolean; debugData?: PrDebugData; + labelsHash?: string; } /** @@ -115,6 +116,8 @@ export interface UpdatePrConfig { prBody?: string; state?: 'open' | 'closed'; targetBranch?: string; + addLabels?: string[] | null; + removeLabels?: string[] | null; } export interface EnsureIssueConfig { title: string; @@ -200,6 +203,7 @@ export interface Platform { getRepos(config?: AutodiscoverConfig): Promise; getRepoForceRebase(): Promise; deleteLabel(number: number, label: string): Promise; + addLabel?(number: number, label: string): Promise; setBranchStatus(branchStatusConfig: BranchStatusConfig): Promise; getBranchStatusCheck( branchName: string, diff --git a/lib/workers/repository/update/pr/body/index.ts b/lib/workers/repository/update/pr/body/index.ts index ee8d89e99bfccf..f4c50613c737b2 100644 --- a/lib/workers/repository/update/pr/body/index.ts +++ b/lib/workers/repository/update/pr/body/index.ts @@ -6,6 +6,7 @@ import * as template from '../../../../../util/template'; import { joinUrlParts } from '../../../../../util/url'; import type { BranchConfig } from '../../../../types'; import { getDepWarningsPR, getWarnings } from '../../../errors-warnings'; +import { prepareLabels } from '../labels'; import { getChangelogs } from './changelogs'; import { getPrConfigDescription } from './config-description'; import { getControls } from './controls'; @@ -100,6 +101,10 @@ export function getPrBody( prBody = prBody.replace(regEx(/\n\n\n+/g), '\n\n'); const prDebugData64 = toBase64(JSON.stringify(prBodyConfig.debugData)); prBody += `\n\n`; + + const prLabelsHash = toBase64(JSON.stringify(prepareLabels(config))); + prBody += `\n\n`; + prBody = platform.massageMarkdown(prBody); if (prBodyConfig?.rebasingNotice) { diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index 28cf9b2b6a40d1..7603e75f2a41e4 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -43,6 +43,8 @@ import { generatePrBodyFingerprintConfig, validatePrCache, } from './pr-fingerprint'; +import { fromBase64, toBase64 } from '../../../../util/string'; +import { regEx } from '../../../../util/regex'; export function getPlatformPrOptions( config: RenovateConfig & PlatformPrOptions @@ -316,7 +318,7 @@ export async function ensurePr( } } - const prBody = getPrBody( + let prBody = getPrBody( config, { debugData: updatePrDebugData( @@ -331,6 +333,16 @@ export async function ensurePr( if (existingPr) { logger.debug('Processing existing PR'); + const existingLabelsHash = existingPr.bodyStruct?.labelsHash; + // eslint-disable-next-line + console.log(existingPr.bodyStruct); + // remove labels hash from pr body if existing pr doesn't have one + if (!existingLabelsHash) { + // eslint-disable-next-line + console.log('mast kaam kiya rahul'); + prBody = prBody.replace(regEx(//g), ''); + } + if ( !existingPr.hasAssignees && !hasNotIgnoredReviewers(existingPr, config) && @@ -341,6 +353,7 @@ export async function ensurePr( logger.debug(`Setting assignees and reviewers as status checks failed`); await addParticipants(config, existingPr); } + // Check if existing PR needs updating const existingPrTitle = stripEmojis(existingPr.title); const existingPrBodyHash = existingPr.bodyStruct?.hash; @@ -377,6 +390,27 @@ export async function ensurePr( ); updatePrConfig.targetBranch = config.baseBranch; } + if (existingLabelsHash) { + const newLabelsHash = toBase64(JSON.stringify(prepareLabels(config))); + if (existingLabelsHash !== newLabelsHash) { + logger.debug( + { + branchName, + oldLabels: existingLabelsHash + ? JSON.parse(fromBase64(existingLabelsHash)) + : [], + newLabels: prepareLabels(config), + }, + 'PR labels have changed' + ); + const [addLabels, removeLabels] = getChangedLabels( + existingLabelsHash, + newLabelsHash + ); + updatePrConfig.addLabels = addLabels; + updatePrConfig.removeLabels = removeLabels; + } + } if (existingPrTitle !== newPrTitle) { logger.debug( { @@ -522,3 +556,18 @@ export async function ensurePr( } return { type: 'without-pr', prBlockedBy: 'Error' }; } + +function getChangedLabels( + oldLabelsHash: string, + newLabelsHash: string +): [string[] | null, string[] | null] { + const existingLabels: string[] = JSON.parse(fromBase64(oldLabelsHash)); + const newLabels: string[] = JSON.parse(fromBase64(newLabelsHash)); + + const labelsToAdd = + newLabels?.filter((l) => !existingLabels?.includes(l)) ?? null; + const labelsToRemove = + existingLabels?.filter((l) => !newLabels?.includes(l)) ?? null; + + return [labelsToAdd, labelsToRemove]; +} From 33a10d2f295754fb6900801fdc82d62014587ff5 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Sun, 22 Oct 2023 21:13:56 +0545 Subject: [PATCH 02/60] skip if pr-labels are modified --- lib/workers/repository/update/pr/index.ts | 26 ++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index 53c32d48b3d0d7..02fce673fa85b6 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -27,6 +27,8 @@ import { stripEmojis } from '../../../../util/emoji'; import { fingerprint } from '../../../../util/fingerprint'; import { getBranchLastCommitTime } from '../../../../util/git'; import { memoize } from '../../../../util/memoize'; +import { regEx } from '../../../../util/regex'; +import { fromBase64, toBase64 } from '../../../../util/string'; import { incLimitedValue, isLimitReached } from '../../../global/limits'; import type { BranchConfig, @@ -43,8 +45,6 @@ import { generatePrBodyFingerprintConfig, validatePrCache, } from './pr-fingerprint'; -import { fromBase64, toBase64 } from '../../../../util/string'; -import { regEx } from '../../../../util/regex'; export function getPlatformPrOptions( config: RenovateConfig & PlatformPrOptions @@ -392,15 +392,19 @@ export async function ensurePr( updatePrConfig.targetBranch = config.baseBranch; } if (existingLabelsHash) { - const newLabelsHash = toBase64(JSON.stringify(prepareLabels(config))); - if (existingLabelsHash !== newLabelsHash) { + const newLabels = prepareLabels(config); + const newLabelsHash = toBase64(JSON.stringify(newLabels)); + if ( + !areLabelsModified(existingLabelsHash, existingPr.labels) && + existingLabelsHash !== newLabelsHash + ) { logger.debug( { branchName, oldLabels: existingLabelsHash ? JSON.parse(fromBase64(existingLabelsHash)) : [], - newLabels: prepareLabels(config), + newLabels, }, 'PR labels have changed' ); @@ -572,3 +576,15 @@ function getChangedLabels( return [labelsToAdd, labelsToRemove]; } + +function areLabelsModified( + oldLabelsHash: string, + existingLabels?: string[] +): boolean { + if (!existingLabels) { + return false; + } + + const existingLabelsHash = toBase64(JSON.stringify(existingLabels)); + return existingLabelsHash !== oldLabelsHash; +} From 472f4a3b54aa05efe31eb6f9b37ba4750619efe7 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Mon, 23 Oct 2023 03:30:42 +0545 Subject: [PATCH 03/60] fix tests --- lib/modules/platform/gitlab/index.spec.ts | 16 ++++++++-------- lib/modules/platform/gitlab/index.ts | 8 ++++++++ lib/workers/repository/update/pr/index.ts | 13 ++++++++----- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/lib/modules/platform/gitlab/index.spec.ts b/lib/modules/platform/gitlab/index.spec.ts index 9b0f9eb1192749..78d28dd74f2e0a 100644 --- a/lib/modules/platform/gitlab/index.spec.ts +++ b/lib/modules/platform/gitlab/index.spec.ts @@ -2540,7 +2540,8 @@ describe('modules/platform/gitlab/index', () => { ).toResolve(); }); - it('adds and removes labels', async () => { + // eslint-disable-next-line + it.only('adds and removes labels', async () => { await initPlatform('13.3.6-ee'); httpMock .scope(gitlabApiHost) @@ -2564,15 +2565,14 @@ describe('modules/platform/gitlab/index', () => { prTitle: 'title', prBody: 'body', state: 'closed', - labels: ['new_label'], + addLabels: ['new_label'], + removeLabels: ['old_label'], }) ).toResolve(); - expect(logger.debug).toHaveBeenCalledWith( - `Assigning labels 'new_label' to #1` - ); - expect(logger.debug).toHaveBeenCalledWith( - `Unassigning labels 'old_label' from #1` - ); + expect(logger.debug).toHaveBeenCalledWith([ + `Assigning labels new_label to #1`, + `Unassigning labels old_label from #1`, + ]); }); }); diff --git a/lib/modules/platform/gitlab/index.ts b/lib/modules/platform/gitlab/index.ts index 3975f7909281cd..2284173212eecc 100644 --- a/lib/modules/platform/gitlab/index.ts +++ b/lib/modules/platform/gitlab/index.ts @@ -771,14 +771,22 @@ export async function updatePr({ description: sanitize(description), ...(newState && { state_event: newState }), }; + // eslint-disable-next-line + console.log(addLabels, removeLabels); if (targetBranch) { body.target_branch = targetBranch; } if (addLabels) { + // eslint-disable-next-line + console.log(1); + logger.debug(`Assigning labels ${addLabels.join(',')} to ${iid}`); body.add_labels = addLabels; } if (removeLabels) { + // eslint-disable-next-line + console.log(2); + logger.debug(`Unassigning labels ${removeLabels.join(',')} to ${iid}`); body.remove_labels = removeLabels; } diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index 02fce673fa85b6..d847a6fc763323 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -335,12 +335,8 @@ export async function ensurePr( logger.debug('Processing existing PR'); const existingLabelsHash = existingPr.bodyStruct?.labelsHash; - // eslint-disable-next-line - console.log(existingPr.bodyStruct); // remove labels hash from pr body if existing pr doesn't have one if (!existingLabelsHash) { - // eslint-disable-next-line - console.log('mast kaam kiya rahul'); prBody = prBody.replace(regEx(//g), ''); } @@ -586,5 +582,12 @@ function areLabelsModified( } const existingLabelsHash = toBase64(JSON.stringify(existingLabels)); - return existingLabelsHash !== oldLabelsHash; + if (existingLabelsHash !== oldLabelsHash) { + logger.debug( + 'PR labels have been modified by user, skipping labels update' + ); + return true; + } + + return false; } From 18bca708ca1ffd386b97aec01951c805eef37120 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Mon, 23 Oct 2023 04:42:34 +0545 Subject: [PATCH 04/60] fix gitea label update logic --- lib/modules/platform/gitea/index.ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/modules/platform/gitea/index.ts b/lib/modules/platform/gitea/index.ts index 97a773ba064db2..3fb350fa6db789 100644 --- a/lib/modules/platform/gitea/index.ts +++ b/lib/modules/platform/gitea/index.ts @@ -642,17 +642,13 @@ const platform: Platform = { prUpdateParams.base = targetBranch; } - if (is.nonEmptyArray(addLabels)) { - for (const label of addLabels) { - await addLabel!(number, label); - } + if (addLabels) { + const labels = Array.isArray(addLabels) + ? await Promise.all(addLabels.map(lookupLabelByName)) + : []; + prUpdateParams.labels = labels.filter(is.number); } - if (is.nonEmptyArray(removeLabels)) { - for (const label of removeLabels) { - await deleteLabel(number, label); - } - } await helper.updatePR(config.repository, number, prUpdateParams); }, From 3af757b92f845625d14c31b1df5c96bf68f76c77 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Sun, 22 Oct 2023 18:18:16 -0700 Subject: [PATCH 05/60] Apply suggestions from code review --- lib/modules/platform/azure/index.spec.ts | 2 +- .../bitbucket-server/__snapshots__/index.spec.ts.snap | 2 -- lib/modules/platform/bitbucket-server/index.spec.ts | 2 +- lib/modules/platform/bitbucket/index.spec.ts | 2 +- lib/modules/platform/codecommit/index.spec.ts | 2 +- lib/modules/platform/gitea/index.spec.ts | 2 +- lib/modules/platform/gitea/index.ts | 11 ----------- lib/modules/platform/github/index.ts | 1 - lib/modules/platform/gitlab/index.spec.ts | 3 +-- lib/modules/platform/gitlab/index.ts | 6 ------ 10 files changed, 6 insertions(+), 27 deletions(-) diff --git a/lib/modules/platform/azure/index.spec.ts b/lib/modules/platform/azure/index.spec.ts index 17c2e3cd899ff3..9ef1fdb38afdf8 100644 --- a/lib/modules/platform/azure/index.spec.ts +++ b/lib/modules/platform/azure/index.spec.ts @@ -1411,7 +1411,7 @@ describe('modules/platform/azure/index', () => { const prBody = '\n---\n\n - [ ] rebase\n' + 'plus also [a link](https://github.com/foo/bar/issues/5)' + - ``; + ``; expect(azure.massageMarkdown(prBody)).toBe( 'plus also [a link](https://github.com/foo/bar/issues/5)' ); diff --git a/lib/modules/platform/bitbucket-server/__snapshots__/index.spec.ts.snap b/lib/modules/platform/bitbucket-server/__snapshots__/index.spec.ts.snap index 6953dafe479665..76d488bcf8bbf9 100644 --- a/lib/modules/platform/bitbucket-server/__snapshots__/index.spec.ts.snap +++ b/lib/modules/platform/bitbucket-server/__snapshots__/index.spec.ts.snap @@ -198,7 +198,6 @@ exports[`modules/platform/bitbucket-server/index endpoint with no path massageMa Empty comment. - Followed by some information. " `; @@ -403,7 +402,6 @@ exports[`modules/platform/bitbucket-server/index endpoint with path massageMarkd Empty comment. - Followed by some information. " `; diff --git a/lib/modules/platform/bitbucket-server/index.spec.ts b/lib/modules/platform/bitbucket-server/index.spec.ts index 04393c300f1c84..30fed25a30ea70 100644 --- a/lib/modules/platform/bitbucket-server/index.spec.ts +++ b/lib/modules/platform/bitbucket-server/index.spec.ts @@ -1743,7 +1743,7 @@ describe('modules/platform/bitbucket-server/index', () => { Empty comment. - + Followed by some information. `); expect(prBody).toMatchSnapshot(); diff --git a/lib/modules/platform/bitbucket/index.spec.ts b/lib/modules/platform/bitbucket/index.spec.ts index 82e7da668547ac..03023f2a01c564 100644 --- a/lib/modules/platform/bitbucket/index.spec.ts +++ b/lib/modules/platform/bitbucket/index.spec.ts @@ -1371,7 +1371,7 @@ describe('modules/platform/bitbucket/index', () => { '
foo\n
\n\n
text' + '\n---\n\n - [ ] rebase\n' + '\n\n
\n\n
\n
' + - ``; + ``; expect(bitbucket.massageMarkdown(prBody)).toMatchSnapshot(); }); }); diff --git a/lib/modules/platform/codecommit/index.spec.ts b/lib/modules/platform/codecommit/index.spec.ts index eeed9dd6ce066f..e571761ba9519e 100644 --- a/lib/modules/platform/codecommit/index.spec.ts +++ b/lib/modules/platform/codecommit/index.spec.ts @@ -55,7 +55,7 @@ describe('modules/platform/codecommit/index', () => { it('validates massageMarkdown functionality', () => { const newStr = codeCommit.massageMarkdown( '
foobar
text
\n' + - '' + '' ); expect(newStr).toBe( '**foo**bartext\n[//]: # ()' diff --git a/lib/modules/platform/gitea/index.spec.ts b/lib/modules/platform/gitea/index.spec.ts index abc1a9e6ebca0e..e419e42034513f 100644 --- a/lib/modules/platform/gitea/index.spec.ts +++ b/lib/modules/platform/gitea/index.spec.ts @@ -1310,7 +1310,7 @@ describe('modules/platform/gitea/index', () => { prBody: 'New Body', state: 'closed', addLabels: ['new_label'], - removeLabels: ['new_label'], + removeLabels: ['old_label'], }); expect(helper.updatePR).toHaveBeenCalledWith(mockRepo.full_name, 1, { diff --git a/lib/modules/platform/gitea/index.ts b/lib/modules/platform/gitea/index.ts index 3fb350fa6db789..d8d1415fbac285 100644 --- a/lib/modules/platform/gitea/index.ts +++ b/lib/modules/platform/gitea/index.ts @@ -849,16 +849,6 @@ const platform: Platform = { } }, - async addLabel(issue: number, labelName: string): Promise { - logger.debug(`Adding label ${labelName} to Issue #${issue}`); - const label = await lookupLabelByName(labelName); - if (label) { - await helper.assignLabel(config.repository, issue, label); - } else { - logger.warn({ issue, labelName }, 'Failed to lookup label for addition'); - } - }, - getRepoForceRebase(): Promise { return Promise.resolve(false); }, @@ -979,7 +969,6 @@ const platform: Platform = { /* eslint-disable @typescript-eslint/unbound-method */ export const { addAssignees, - addLabel, addReviewers, createPr, deleteLabel, diff --git a/lib/modules/platform/github/index.ts b/lib/modules/platform/github/index.ts index 67414154747ba2..3478c04a99d74b 100644 --- a/lib/modules/platform/github/index.ts +++ b/lib/modules/platform/github/index.ts @@ -1713,7 +1713,6 @@ export async function updatePr({ options ); const result = coerceRestPr(ghPr); - cachePr(result); logger.debug(`PR updated...prNo: ${prNo}`); } catch (err) /* istanbul ignore next */ { diff --git a/lib/modules/platform/gitlab/index.spec.ts b/lib/modules/platform/gitlab/index.spec.ts index 78d28dd74f2e0a..cc9aea89568eb4 100644 --- a/lib/modules/platform/gitlab/index.spec.ts +++ b/lib/modules/platform/gitlab/index.spec.ts @@ -2540,8 +2540,7 @@ describe('modules/platform/gitlab/index', () => { ).toResolve(); }); - // eslint-disable-next-line - it.only('adds and removes labels', async () => { + it('adds and removes labels', async () => { await initPlatform('13.3.6-ee'); httpMock .scope(gitlabApiHost) diff --git a/lib/modules/platform/gitlab/index.ts b/lib/modules/platform/gitlab/index.ts index 2284173212eecc..9037e6b0b5e9dd 100644 --- a/lib/modules/platform/gitlab/index.ts +++ b/lib/modules/platform/gitlab/index.ts @@ -771,21 +771,15 @@ export async function updatePr({ description: sanitize(description), ...(newState && { state_event: newState }), }; - // eslint-disable-next-line - console.log(addLabels, removeLabels); if (targetBranch) { body.target_branch = targetBranch; } if (addLabels) { - // eslint-disable-next-line - console.log(1); logger.debug(`Assigning labels ${addLabels.join(',')} to ${iid}`); body.add_labels = addLabels; } if (removeLabels) { - // eslint-disable-next-line - console.log(2); logger.debug(`Unassigning labels ${removeLabels.join(',')} to ${iid}`); body.remove_labels = removeLabels; } From fa29bc8f415ab25b5ec3cf707c0c5bde2707d508 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Mon, 23 Oct 2023 16:37:33 +0545 Subject: [PATCH 06/60] add tests --- lib/modules/platform/gitea/index.spec.ts | 8 +--- lib/modules/platform/gitea/index.ts | 1 + lib/modules/platform/gitlab/index.spec.ts | 4 -- lib/modules/platform/gitlab/index.ts | 3 -- lib/workers/repository/update/pr/index.ts | 36 +---------------- .../repository/update/pr/labels.spec.ts | 33 +++++++++++++++- lib/workers/repository/update/pr/labels.ts | 39 ++++++++++++++++++- 7 files changed, 73 insertions(+), 51 deletions(-) diff --git a/lib/modules/platform/gitea/index.spec.ts b/lib/modules/platform/gitea/index.spec.ts index e419e42034513f..ceac0df4b4c5be 100644 --- a/lib/modules/platform/gitea/index.spec.ts +++ b/lib/modules/platform/gitea/index.spec.ts @@ -1310,20 +1310,14 @@ describe('modules/platform/gitea/index', () => { prBody: 'New Body', state: 'closed', addLabels: ['new_label'], - removeLabels: ['old_label'], }); expect(helper.updatePR).toHaveBeenCalledWith(mockRepo.full_name, 1, { title: 'New Title', body: 'New Body', state: 'closed', + labels: [2], }); - expect(logger.debug).toHaveBeenCalledWith( - 'Deleting label old_label from Issue #1' - ); - expect(logger.debug).toHaveBeenCalledWith( - 'Adding label new_label to Issue #1' - ); }); }); diff --git a/lib/modules/platform/gitea/index.ts b/lib/modules/platform/gitea/index.ts index d8d1415fbac285..1b3843aeb10883 100644 --- a/lib/modules/platform/gitea/index.ts +++ b/lib/modules/platform/gitea/index.ts @@ -642,6 +642,7 @@ const platform: Platform = { prUpdateParams.base = targetBranch; } + // no need to do extra call for removing labels as gitea API replaces labels array if (addLabels) { const labels = Array.isArray(addLabels) ? await Promise.all(addLabels.map(lookupLabelByName)) diff --git a/lib/modules/platform/gitlab/index.spec.ts b/lib/modules/platform/gitlab/index.spec.ts index cc9aea89568eb4..7a7f8de65f01ba 100644 --- a/lib/modules/platform/gitlab/index.spec.ts +++ b/lib/modules/platform/gitlab/index.spec.ts @@ -2568,10 +2568,6 @@ describe('modules/platform/gitlab/index', () => { removeLabels: ['old_label'], }) ).toResolve(); - expect(logger.debug).toHaveBeenCalledWith([ - `Assigning labels new_label to #1`, - `Unassigning labels old_label from #1`, - ]); }); }); diff --git a/lib/modules/platform/gitlab/index.ts b/lib/modules/platform/gitlab/index.ts index 9037e6b0b5e9dd..56de8e8381979f 100644 --- a/lib/modules/platform/gitlab/index.ts +++ b/lib/modules/platform/gitlab/index.ts @@ -775,12 +775,9 @@ export async function updatePr({ body.target_branch = targetBranch; } if (addLabels) { - logger.debug(`Assigning labels ${addLabels.join(',')} to ${iid}`); body.add_labels = addLabels; } - if (removeLabels) { - logger.debug(`Unassigning labels ${removeLabels.join(',')} to ${iid}`); body.remove_labels = removeLabels; } diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index d847a6fc763323..b20c73b4c625bf 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -38,7 +38,7 @@ import type { import { embedChangelogs } from '../../changelog'; import { resolveBranchStatus } from '../branch/status-checks'; import { getPrBody } from './body'; -import { prepareLabels } from './labels'; +import { areLabelsModified, getChangedLabels, prepareLabels } from './labels'; import { addParticipants } from './participants'; import { getPrCache, setPrCache } from './pr-cache'; import { @@ -557,37 +557,3 @@ export async function ensurePr( } return { type: 'without-pr', prBlockedBy: 'Error' }; } - -function getChangedLabels( - oldLabelsHash: string, - newLabelsHash: string -): [string[] | null, string[] | null] { - const existingLabels: string[] = JSON.parse(fromBase64(oldLabelsHash)); - const newLabels: string[] = JSON.parse(fromBase64(newLabelsHash)); - - const labelsToAdd = - newLabels?.filter((l) => !existingLabels?.includes(l)) ?? null; - const labelsToRemove = - existingLabels?.filter((l) => !newLabels?.includes(l)) ?? null; - - return [labelsToAdd, labelsToRemove]; -} - -function areLabelsModified( - oldLabelsHash: string, - existingLabels?: string[] -): boolean { - if (!existingLabels) { - return false; - } - - const existingLabelsHash = toBase64(JSON.stringify(existingLabels)); - if (existingLabelsHash !== oldLabelsHash) { - logger.debug( - 'PR labels have been modified by user, skipping labels update' - ); - return true; - } - - return false; -} diff --git a/lib/workers/repository/update/pr/labels.spec.ts b/lib/workers/repository/update/pr/labels.spec.ts index 1c090ba3e96868..704bbdaaf4ccfd 100644 --- a/lib/workers/repository/update/pr/labels.spec.ts +++ b/lib/workers/repository/update/pr/labels.spec.ts @@ -1,4 +1,4 @@ -import { prepareLabels } from './labels'; +import { areLabelsModified, getChangedLabels, prepareLabels } from './labels'; describe('workers/repository/update/pr/labels', () => { describe('prepareLabels(config)', () => { @@ -78,4 +78,35 @@ describe('workers/repository/update/pr/labels', () => { expect(result).toEqual([]); }); }); + + describe('getChangedLabels', () => { + it('adds new labels', () => { + expect(getChangedLabels('WyJucG0iXQ==', 'WyJub2RlIiwibnBtIl0=')).toEqual([ + ['node'], + [], + ]); + }); + + it('removes old labels', () => { + expect(getChangedLabels('WyJub2RlIiwibnBtIl0=', 'WyJucG0iXQ==')).toEqual([ + [], + ['node'], + ]); + }); + }); + + describe('areLabelsModified', () => { + it('returns true', () => { + expect(areLabelsModified('WyJub2RlIiwibnBtIl0=', ['npm'])).toBeTrue(); + }); + + it('returns false', () => { + expect( + areLabelsModified('WyJub2RlIiwibnBtIl0=', ['npm', 'node']) + ).toBeFalse(); + expect( + areLabelsModified('WyJub2RlIiwibnBtIl0=', ['node', 'npm']) + ).toBeFalse(); + }); + }); }); diff --git a/lib/workers/repository/update/pr/labels.ts b/lib/workers/repository/update/pr/labels.ts index df04f801259346..8b606add0b5d10 100644 --- a/lib/workers/repository/update/pr/labels.ts +++ b/lib/workers/repository/update/pr/labels.ts @@ -1,5 +1,7 @@ import is from '@sindresorhus/is'; import type { RenovateConfig } from '../../../../config/types'; +import { logger } from '../../../../logger'; +import { fromBase64, toBase64 } from '../../../../util/string'; import * as template from '../../../../util/template'; export function prepareLabels(config: RenovateConfig): string[] { @@ -8,5 +10,40 @@ export function prepareLabels(config: RenovateConfig): string[] { return [...new Set([...labels, ...addLabels])] .filter(is.nonEmptyStringAndNotWhitespace) .map((label) => template.compile(label, config)) - .filter(is.nonEmptyStringAndNotWhitespace); + .filter(is.nonEmptyStringAndNotWhitespace) + .sort(); +} + +export function getChangedLabels( + oldLabelsHash: string, + newLabelsHash: string +): [string[] | null, string[] | null] { + const existingLabels: string[] = JSON.parse(fromBase64(oldLabelsHash)); + const newLabels: string[] = JSON.parse(fromBase64(newLabelsHash)); + + const labelsToAdd = + newLabels?.filter((l) => !existingLabels?.includes(l)) ?? null; + const labelsToRemove = + existingLabels?.filter((l) => !newLabels?.includes(l)) ?? null; + + return [labelsToAdd, labelsToRemove]; +} + +export function areLabelsModified( + oldLabelsHash: string, + existingLabels?: string[] +): boolean { + if (!existingLabels?.length) { + return false; + } + + const existingLabelsHash = toBase64(JSON.stringify(existingLabels.sort())); + if (existingLabelsHash !== oldLabelsHash) { + logger.debug( + 'PR labels have been modified by user, skipping labels update' + ); + return true; + } + + return false; } From 9b18b660230df95c2788038638d7de2a6d10da71 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Mon, 23 Oct 2023 17:16:51 +0545 Subject: [PATCH 07/60] update snap[s --- .../platform/bitbucket-server/__snapshots__/index.spec.ts.snap | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/modules/platform/bitbucket-server/__snapshots__/index.spec.ts.snap b/lib/modules/platform/bitbucket-server/__snapshots__/index.spec.ts.snap index 76d488bcf8bbf9..6953dafe479665 100644 --- a/lib/modules/platform/bitbucket-server/__snapshots__/index.spec.ts.snap +++ b/lib/modules/platform/bitbucket-server/__snapshots__/index.spec.ts.snap @@ -198,6 +198,7 @@ exports[`modules/platform/bitbucket-server/index endpoint with no path massageMa Empty comment. + Followed by some information. " `; @@ -402,6 +403,7 @@ exports[`modules/platform/bitbucket-server/index endpoint with path massageMarkd Empty comment. + Followed by some information. " `; From 3a7f427a9ce67db5a4e3e15c622e69885d170c34 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Tue, 24 Oct 2023 06:41:17 +0545 Subject: [PATCH 08/60] fix labels order in tests --- lib/workers/repository/onboarding/pr/index.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/workers/repository/onboarding/pr/index.spec.ts b/lib/workers/repository/onboarding/pr/index.spec.ts index 24095e9ec05ca0..78cc72c41a9754 100644 --- a/lib/workers/repository/onboarding/pr/index.spec.ts +++ b/lib/workers/repository/onboarding/pr/index.spec.ts @@ -89,8 +89,8 @@ describe('workers/repository/onboarding/pr/index', () => { ); expect(platform.createPr).toHaveBeenCalledTimes(1); expect(platform.createPr.mock.calls[0][0].labels).toEqual([ - 'label', 'additional-label', + 'label', ]); }); From ce6777f072be82179600a7598e575820862a81b3 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Tue, 24 Oct 2023 07:23:22 +0545 Subject: [PATCH 09/60] revert ordering the labels --- lib/workers/repository/onboarding/pr/index.spec.ts | 2 +- lib/workers/repository/update/pr/labels.spec.ts | 3 --- lib/workers/repository/update/pr/labels.ts | 5 ++--- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/workers/repository/onboarding/pr/index.spec.ts b/lib/workers/repository/onboarding/pr/index.spec.ts index 78cc72c41a9754..24095e9ec05ca0 100644 --- a/lib/workers/repository/onboarding/pr/index.spec.ts +++ b/lib/workers/repository/onboarding/pr/index.spec.ts @@ -89,8 +89,8 @@ describe('workers/repository/onboarding/pr/index', () => { ); expect(platform.createPr).toHaveBeenCalledTimes(1); expect(platform.createPr.mock.calls[0][0].labels).toEqual([ - 'additional-label', 'label', + 'additional-label', ]); }); diff --git a/lib/workers/repository/update/pr/labels.spec.ts b/lib/workers/repository/update/pr/labels.spec.ts index 704bbdaaf4ccfd..e002ae05537ed9 100644 --- a/lib/workers/repository/update/pr/labels.spec.ts +++ b/lib/workers/repository/update/pr/labels.spec.ts @@ -101,9 +101,6 @@ describe('workers/repository/update/pr/labels', () => { }); it('returns false', () => { - expect( - areLabelsModified('WyJub2RlIiwibnBtIl0=', ['npm', 'node']) - ).toBeFalse(); expect( areLabelsModified('WyJub2RlIiwibnBtIl0=', ['node', 'npm']) ).toBeFalse(); diff --git a/lib/workers/repository/update/pr/labels.ts b/lib/workers/repository/update/pr/labels.ts index 8b606add0b5d10..300069acee5343 100644 --- a/lib/workers/repository/update/pr/labels.ts +++ b/lib/workers/repository/update/pr/labels.ts @@ -10,8 +10,7 @@ export function prepareLabels(config: RenovateConfig): string[] { return [...new Set([...labels, ...addLabels])] .filter(is.nonEmptyStringAndNotWhitespace) .map((label) => template.compile(label, config)) - .filter(is.nonEmptyStringAndNotWhitespace) - .sort(); + .filter(is.nonEmptyStringAndNotWhitespace); } export function getChangedLabels( @@ -37,7 +36,7 @@ export function areLabelsModified( return false; } - const existingLabelsHash = toBase64(JSON.stringify(existingLabels.sort())); + const existingLabelsHash = toBase64(JSON.stringify(existingLabels)); if (existingLabelsHash !== oldLabelsHash) { logger.debug( 'PR labels have been modified by user, skipping labels update' From d306847a6104e5c31f5c5bb1f9980af7429c5b3c Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Tue, 24 Oct 2023 17:29:23 +0545 Subject: [PATCH 10/60] change gitae logic --- lib/modules/platform/gitea/index.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/modules/platform/gitea/index.ts b/lib/modules/platform/gitea/index.ts index 1b3843aeb10883..6b18d343198ac8 100644 --- a/lib/modules/platform/gitea/index.ts +++ b/lib/modules/platform/gitea/index.ts @@ -622,8 +622,7 @@ const platform: Platform = { number, prTitle, prBody: body, - addLabels, - removeLabels, + labels, state, targetBranch, }: UpdatePrConfig): Promise { @@ -643,11 +642,10 @@ const platform: Platform = { } // no need to do extra call for removing labels as gitea API replaces labels array - if (addLabels) { - const labels = Array.isArray(addLabels) - ? await Promise.all(addLabels.map(lookupLabelByName)) - : []; - prUpdateParams.labels = labels.filter(is.number); + if (Array.isArray(labels)) { + prUpdateParams.labels = ( + await Promise.all(labels.map(lookupLabelByName)) + ).filter(is.number); } await helper.updatePR(config.repository, number, prUpdateParams); From d4bad42c1dd791790fecb0a8f247664f85447042 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Tue, 24 Oct 2023 17:29:57 +0545 Subject: [PATCH 11/60] update PrUpdateConfig interface --- lib/modules/platform/gitea/index.spec.ts | 25 ++++++++++++++++++- lib/modules/platform/types.ts | 2 ++ .../repository/update/pr/body/index.ts | 6 +++-- lib/workers/repository/update/pr/index.ts | 14 +++++++++-- lib/workers/repository/update/pr/labels.ts | 8 +++--- 5 files changed, 45 insertions(+), 10 deletions(-) diff --git a/lib/modules/platform/gitea/index.spec.ts b/lib/modules/platform/gitea/index.spec.ts index ceac0df4b4c5be..c0e958e3da32c9 100644 --- a/lib/modules/platform/gitea/index.spec.ts +++ b/lib/modules/platform/gitea/index.spec.ts @@ -1291,7 +1291,7 @@ describe('modules/platform/gitea/index', () => { }); }); - it('should add and remove labels', async () => { + it('should add new labels', async () => { helper.getRepoLabels.mockResolvedValueOnce([ { id: 1, name: 'old_label', description: 'its a me', color: '#000000' }, { @@ -1319,6 +1319,29 @@ describe('modules/platform/gitea/index', () => { labels: [2], }); }); + + it('should remove old labels', async () => { + helper.getRepoLabels.mockResolvedValueOnce([ + { id: 1, name: 'old_label', description: 'its a me', color: '#000000' }, + ]); + helper.getOrgLabels.mockResolvedValueOnce([]); + helper.searchPRs.mockResolvedValueOnce(mockPRs); + await initFakeRepo(); + await gitea.updatePr({ + number: 1, + prTitle: 'New Title', + prBody: 'New Body', + state: 'closed', + addLabels: [], + }); + + expect(helper.updatePR).toHaveBeenCalledWith(mockRepo.full_name, 1, { + title: 'New Title', + body: 'New Body', + state: 'closed', + labels: [], + }); + }); }); describe('mergePr', () => { diff --git a/lib/modules/platform/types.ts b/lib/modules/platform/types.ts index e4b909f9a9a1e4..a40969eedb8537 100644 --- a/lib/modules/platform/types.ts +++ b/lib/modules/platform/types.ts @@ -120,6 +120,8 @@ export interface UpdatePrConfig { prBody?: string; state?: 'open' | 'closed'; targetBranch?: string; + labels?: string[] | null; // gitea updates labels by replacing the labels array so this is needed + // github, gitlab have specific endpoints to add new or remove old labels addLabels?: string[] | null; removeLabels?: string[] | null; } diff --git a/lib/workers/repository/update/pr/body/index.ts b/lib/workers/repository/update/pr/body/index.ts index dbe284c30001f3..abc6e4ff2f3e7e 100644 --- a/lib/workers/repository/update/pr/body/index.ts +++ b/lib/workers/repository/update/pr/body/index.ts @@ -102,8 +102,10 @@ export function getPrBody( const prDebugData64 = toBase64(JSON.stringify(prBodyConfig.debugData)); prBody += `\n\n`; - const prLabelsHash = toBase64(JSON.stringify(prepareLabels(config))); - prBody += `\n\n`; + // sort the labels, create labelHash and add it as comment to pr body + // adding the comment at top, to tackle github's pr-description length limit of 2000 chars + const prLabelsHash = toBase64(JSON.stringify(prepareLabels(config).sort())); + prBody = `\n\n` + prBody; prBody = platform.massageMarkdown(prBody); diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index b20c73b4c625bf..e6f0a99947b0ea 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -387,12 +387,17 @@ export async function ensurePr( ); updatePrConfig.targetBranch = config.baseBranch; } + // if labelsHash is present in pr body + // divide labels into two categories: i) which needs to be added ii) which needs to be removed + // note: existing labels aren't present in these two categories + // this is necessary because some platforms handle these two categories separately if (existingLabelsHash) { const newLabels = prepareLabels(config); const newLabelsHash = toBase64(JSON.stringify(newLabels)); + // only update labels if there is any change to the labels array && labels haven't been modified by user if ( - !areLabelsModified(existingLabelsHash, existingPr.labels) && - existingLabelsHash !== newLabelsHash + existingLabelsHash !== newLabelsHash && + !areLabelsModified(existingLabelsHash, existingPr.labels) ) { logger.debug( { @@ -408,6 +413,11 @@ export async function ensurePr( existingLabelsHash, newLabelsHash ); + + // for gitea + updatePrConfig.labels = newLabels; + + // for github, gitlab updatePrConfig.addLabels = addLabels; updatePrConfig.removeLabels = removeLabels; } diff --git a/lib/workers/repository/update/pr/labels.ts b/lib/workers/repository/update/pr/labels.ts index 300069acee5343..951b2c5154a8e2 100644 --- a/lib/workers/repository/update/pr/labels.ts +++ b/lib/workers/repository/update/pr/labels.ts @@ -32,11 +32,9 @@ export function areLabelsModified( oldLabelsHash: string, existingLabels?: string[] ): boolean { - if (!existingLabels?.length) { - return false; - } - - const existingLabelsHash = toBase64(JSON.stringify(existingLabels)); + const existingLabelsHash = toBase64( + JSON.stringify(existingLabels?.sort() ?? []) + ); if (existingLabelsHash !== oldLabelsHash) { logger.debug( 'PR labels have been modified by user, skipping labels update' From 068f70fcf005d2e6eef05511ad895375ba79cbc6 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Tue, 24 Oct 2023 17:47:26 +0545 Subject: [PATCH 12/60] fix tests --- lib/modules/platform/gitea/index.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/modules/platform/gitea/index.spec.ts b/lib/modules/platform/gitea/index.spec.ts index c0e958e3da32c9..413e627f52a2d7 100644 --- a/lib/modules/platform/gitea/index.spec.ts +++ b/lib/modules/platform/gitea/index.spec.ts @@ -1309,7 +1309,7 @@ describe('modules/platform/gitea/index', () => { prTitle: 'New Title', prBody: 'New Body', state: 'closed', - addLabels: ['new_label'], + labels: ['new_label'], }); expect(helper.updatePR).toHaveBeenCalledWith(mockRepo.full_name, 1, { @@ -1332,7 +1332,7 @@ describe('modules/platform/gitea/index', () => { prTitle: 'New Title', prBody: 'New Body', state: 'closed', - addLabels: [], + labels: [], }); expect(helper.updatePR).toHaveBeenCalledWith(mockRepo.full_name, 1, { From b221ab440be40a71d197e36eb4c935df7b35c717 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Tue, 24 Oct 2023 21:47:11 +0545 Subject: [PATCH 13/60] fix coverage --- .../repository/update/pr/index.spec.ts | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/lib/workers/repository/update/pr/index.spec.ts b/lib/workers/repository/update/pr/index.spec.ts index 866eca46bccda8..1dbeafb8134754 100644 --- a/lib/workers/repository/update/pr/index.spec.ts +++ b/lib/workers/repository/update/pr/index.spec.ts @@ -19,6 +19,7 @@ import type { Pr } from '../../../../modules/platform/types'; import { ExternalHostError } from '../../../../types/errors/external-host-error'; import type { PrCache } from '../../../../util/cache/repository/types'; import { fingerprint } from '../../../../util/fingerprint'; +import { toBase64 } from '../../../../util/string'; import * as _limits from '../../../global/limits'; import type { BranchConfig, BranchUpgradeConfig } from '../../../types'; import { embedChangelogs } from '../../changelog'; @@ -269,6 +270,102 @@ describe('workers/repository/update/pr/index', () => { }); describe('Update', () => { + // updates labels + it('updates PR if labels have changed in config', async () => { + const existingPr: Pr = { + ...pr, + bodyStruct: getPrBodyStruct( + `\n\n Some body` + ), + labels: ['old_label'], + }; + platform.getBranchPr.mockResolvedValueOnce(existingPr); + + config.labels = ['new_label']; + const res = await ensurePr(config); + + expect(res).toEqual({ + type: 'with-pr', + pr: { ...pr, labels: ['old_label'] }, + }); + expect(platform.updatePr).toHaveBeenCalled(); + expect(platform.createPr).not.toHaveBeenCalled(); + expect(logger.logger.debug).toHaveBeenCalledWith( + { + branchName: 'renovate-branch', + oldLabels: ['old_label'], + newLabels: ['new_label'], + }, + `PR labels have changed` + ); + expect(prCache.setPrCache).toHaveBeenCalled(); + }); + + // skips updating labels if existing pr doesn't have labelsHash + it('skips pr update if existing pr does not have labelsHash', async () => { + const existingPr: Pr = { + ...pr, + labels: ['old_label'], + }; + platform.getBranchPr.mockResolvedValueOnce(existingPr); + + config.labels = ['new_label']; + const res = await ensurePr(config); + + expect(res).toEqual({ + type: 'with-pr', + pr: { ...pr, labels: ['old_label'] }, + }); + expect(platform.updatePr).not.toHaveBeenCalled(); + expect(platform.createPr).not.toHaveBeenCalled(); + expect(logger.logger.debug).not.toHaveBeenCalledWith( + { + branchName: 'renovate-branch', + oldLabels: ['old_label'], + newLabels: ['new_label'], + }, + `PR labels have changed` + ); + expect(prCache.setPrCache).toHaveBeenCalled(); + }); + + // skip updating labels if pr labels have been modified by user + it('skips pr update if pr labels have been modified by user', async () => { + const existingPr: Pr = { + ...pr, + bodyStruct: getPrBodyStruct( + `\n\n Some body` + ), + }; + platform.getBranchPr.mockResolvedValueOnce(existingPr); + + config.labels = ['new_label']; + const res = await ensurePr(config); + + expect(res).toEqual({ + type: 'with-pr', + pr, + }); + expect(platform.updatePr).toHaveBeenCalled(); + expect(platform.createPr).not.toHaveBeenCalled(); + expect(logger.logger.debug).not.toHaveBeenCalledWith( + { + branchName: 'renovate-branch', + oldLabels: ['old_label'], + newLabels: ['new_label'], + }, + `PR labels have changed` + ); + expect(logger.logger.debug).toHaveBeenCalledWith( + 'PR labels have been modified by user, skipping labels update' + ); + expect(prCache.setPrCache).toHaveBeenCalled(); + }); + it('updates PR due to title change', async () => { const changedPr: Pr = { ...pr, title: 'Another title' }; // user changed the prTitle platform.getBranchPr.mockResolvedValueOnce(changedPr); From 3d6f734da3f68626108cc0ded09f77567c318677 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Tue, 24 Oct 2023 22:40:50 +0545 Subject: [PATCH 14/60] refactor getChangedLabels fn --- lib/workers/repository/update/pr/index.spec.ts | 15 +++++++++++++-- lib/workers/repository/update/pr/index.ts | 10 ++++------ lib/workers/repository/update/pr/labels.spec.ts | 4 ++-- lib/workers/repository/update/pr/labels.ts | 15 +++++---------- 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/lib/workers/repository/update/pr/index.spec.ts b/lib/workers/repository/update/pr/index.spec.ts index 1dbeafb8134754..ed0ccf73991ae6 100644 --- a/lib/workers/repository/update/pr/index.spec.ts +++ b/lib/workers/repository/update/pr/index.spec.ts @@ -282,13 +282,24 @@ describe('workers/repository/update/pr/index', () => { labels: ['old_label'], }; platform.getBranchPr.mockResolvedValueOnce(existingPr); - + prBody.getPrBody.mockReturnValueOnce( + `\n\n Some body` + ); config.labels = ['new_label']; const res = await ensurePr(config); expect(res).toEqual({ type: 'with-pr', - pr: { ...pr, labels: ['old_label'] }, + pr: { + ...pr, + labels: ['old_label'], + bodyStruct: { + hash: expect.any(String), + labelsHash: toBase64(JSON.stringify(['new_label'])), + }, + }, }); expect(platform.updatePr).toHaveBeenCalled(); expect(platform.createPr).not.toHaveBeenCalled(); diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index e6f0a99947b0ea..db8e449dc8efe0 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -28,7 +28,7 @@ import { fingerprint } from '../../../../util/fingerprint'; import { getBranchLastCommitTime } from '../../../../util/git'; import { memoize } from '../../../../util/memoize'; import { regEx } from '../../../../util/regex'; -import { fromBase64, toBase64 } from '../../../../util/string'; +import { toBase64 } from '../../../../util/string'; import { incLimitedValue, isLimitReached } from '../../../global/limits'; import type { BranchConfig, @@ -402,16 +402,14 @@ export async function ensurePr( logger.debug( { branchName, - oldLabels: existingLabelsHash - ? JSON.parse(fromBase64(existingLabelsHash)) - : [], + oldLabels: existingPr.labels, newLabels, }, 'PR labels have changed' ); const [addLabels, removeLabels] = getChangedLabels( - existingLabelsHash, - newLabelsHash + existingPr.labels!, + newLabels ); // for gitea diff --git a/lib/workers/repository/update/pr/labels.spec.ts b/lib/workers/repository/update/pr/labels.spec.ts index e002ae05537ed9..143f2de88faaa4 100644 --- a/lib/workers/repository/update/pr/labels.spec.ts +++ b/lib/workers/repository/update/pr/labels.spec.ts @@ -81,14 +81,14 @@ describe('workers/repository/update/pr/labels', () => { describe('getChangedLabels', () => { it('adds new labels', () => { - expect(getChangedLabels('WyJucG0iXQ==', 'WyJub2RlIiwibnBtIl0=')).toEqual([ + expect(getChangedLabels(['npm'], ['node', 'npm'])).toEqual([ ['node'], [], ]); }); it('removes old labels', () => { - expect(getChangedLabels('WyJub2RlIiwibnBtIl0=', 'WyJucG0iXQ==')).toEqual([ + expect(getChangedLabels(['node', 'npm'], ['npm'])).toEqual([ [], ['node'], ]); diff --git a/lib/workers/repository/update/pr/labels.ts b/lib/workers/repository/update/pr/labels.ts index 951b2c5154a8e2..c97d5dca9bed4f 100644 --- a/lib/workers/repository/update/pr/labels.ts +++ b/lib/workers/repository/update/pr/labels.ts @@ -1,7 +1,7 @@ import is from '@sindresorhus/is'; import type { RenovateConfig } from '../../../../config/types'; import { logger } from '../../../../logger'; -import { fromBase64, toBase64 } from '../../../../util/string'; +import { toBase64 } from '../../../../util/string'; import * as template from '../../../../util/template'; export function prepareLabels(config: RenovateConfig): string[] { @@ -14,16 +14,11 @@ export function prepareLabels(config: RenovateConfig): string[] { } export function getChangedLabels( - oldLabelsHash: string, - newLabelsHash: string + oldLabels: string[], + newLabels: string[] ): [string[] | null, string[] | null] { - const existingLabels: string[] = JSON.parse(fromBase64(oldLabelsHash)); - const newLabels: string[] = JSON.parse(fromBase64(newLabelsHash)); - - const labelsToAdd = - newLabels?.filter((l) => !existingLabels?.includes(l)) ?? null; - const labelsToRemove = - existingLabels?.filter((l) => !newLabels?.includes(l)) ?? null; + const labelsToAdd = newLabels?.filter((l) => !oldLabels?.includes(l)); + const labelsToRemove = oldLabels?.filter((l) => !newLabels?.includes(l)); return [labelsToAdd, labelsToRemove]; } From 65138bf7c6976f48880c366210bf73b445050483 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Tue, 24 Oct 2023 22:51:59 +0545 Subject: [PATCH 15/60] apply suggestions --- lib/modules/platform/gitea/gitea-helper.spec.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/modules/platform/gitea/gitea-helper.spec.ts b/lib/modules/platform/gitea/gitea-helper.spec.ts index 7bacf192b23c41..d6f0e4197a892a 100644 --- a/lib/modules/platform/gitea/gitea-helper.spec.ts +++ b/lib/modules/platform/gitea/gitea-helper.spec.ts @@ -375,8 +375,7 @@ describe('modules/platform/gitea/gitea-helper', () => { .patch(`/repos/${mockRepo.full_name}/pulls/${mockPR.number}`) .reply(200); - const res = await closePR(mockRepo.full_name, mockPR.number); - expect(res).toBeUndefined(); + await expect(closePR(mockRepo.full_name, mockPR.number)).toResolve(); }); }); @@ -387,10 +386,11 @@ describe('modules/platform/gitea/gitea-helper', () => { .post(`/repos/${mockRepo.full_name}/pulls/${mockPR.number}/merge`) .reply(200); - const res = await mergePR(mockRepo.full_name, mockPR.number, { - Do: 'rebase', - }); - expect(res).toBeUndefined(); + await expect( + mergePR(mockRepo.full_name, mockPR.number, { + Do: 'rebase', + }) + ).toResolve(); }); }); From e73029f67f4c17d0f4b20427894aefc35317cad9 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Tue, 24 Oct 2023 23:12:44 +0545 Subject: [PATCH 16/60] add docs --- docs/usage/configuration-options.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 51a02f3db66b23..9f74ef475ef1ce 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -2036,10 +2036,11 @@ Consider this example: With the above config, every PR raised by Renovate will have the label `dependencies` while PRs containing `eslint`-related packages will instead have the label `linting`. -Renovate only adds labels when it creates the PR, which means: +Behaviour details: +- Renovate only adds labels when it creates the PR - If you remove labels which Renovate added, it won't re-apply them -- If you change your config, the new/changed labels are not applied to any open PRs +- If you change your config, the new/changed labels are applied to any open PRs The `labels` array is non-mergeable, meaning if multiple `packageRules` match then Renovate uses the last value for `labels`. If you want to add/combine labels, use the `addLabels` config option, which is mergeable. From 6a51748d5642c42afa5a0b4ba424e2d226a0d499 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Fri, 3 Nov 2023 20:35:18 +0545 Subject: [PATCH 17/60] Update docs/usage/configuration-options.md Co-authored-by: Rhys Arkins --- docs/usage/configuration-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 9f74ef475ef1ce..be20987fc04ae2 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -2038,7 +2038,7 @@ With the above config, every PR raised by Renovate will have the label `dependen Behaviour details: -- Renovate only adds labels when it creates the PR +- Renovate creates PRs with the currently configured/applicable labels - If you remove labels which Renovate added, it won't re-apply them - If you change your config, the new/changed labels are applied to any open PRs From 2365865f01a0b0c909fa038b1780411fb4f184c5 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Fri, 3 Nov 2023 20:35:28 +0545 Subject: [PATCH 18/60] Update docs/usage/configuration-options.md Co-authored-by: Rhys Arkins --- docs/usage/configuration-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index be20987fc04ae2..fc29571ca1bbb3 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -2039,7 +2039,7 @@ With the above config, every PR raised by Renovate will have the label `dependen Behaviour details: - Renovate creates PRs with the currently configured/applicable labels -- If you remove labels which Renovate added, it won't re-apply them +- If you add or remove labels in a PR which Renovate created, it won't touch labels again in that open PR - If you change your config, the new/changed labels are applied to any open PRs The `labels` array is non-mergeable, meaning if multiple `packageRules` match then Renovate uses the last value for `labels`. From b9f3cdad13d0ad995c47e51de5862898dba6e411 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Mon, 6 Nov 2023 16:21:14 +0545 Subject: [PATCH 19/60] store labels in existing debugData --- lib/modules/platform/pr-body.ts | 5 -- lib/modules/platform/types.ts | 2 +- .../repository/update/pr/body/index.ts | 6 -- .../repository/update/pr/index.spec.ts | 54 +++++++++--- lib/workers/repository/update/pr/index.ts | 85 ++++++++++--------- .../repository/update/pr/labels.spec.ts | 33 ++++++- lib/workers/repository/update/pr/labels.ts | 39 ++++++--- 7 files changed, 145 insertions(+), 79 deletions(-) diff --git a/lib/modules/platform/pr-body.ts b/lib/modules/platform/pr-body.ts index 3bc41a02e6dd61..ae3de68fe59b0d 100644 --- a/lib/modules/platform/pr-body.ts +++ b/lib/modules/platform/pr-body.ts @@ -70,11 +70,6 @@ export function getPrBodyStruct( const result: PrBodyStruct = { hash }; const rebaseRequested = isRebaseRequested(body); - const labelsHash = getLabels(body); - if (labelsHash) { - result.labelsHash = labelsHash; - } - if (!is.undefined(rebaseRequested)) { result.rebaseRequested = rebaseRequested; } diff --git a/lib/modules/platform/types.ts b/lib/modules/platform/types.ts index a40969eedb8537..517a3ac58ce21e 100644 --- a/lib/modules/platform/types.ts +++ b/lib/modules/platform/types.ts @@ -55,6 +55,7 @@ export interface PrDebugData { createdInVer: string; updatedInVer: string; targetBranch: string; + labels?: string[]; } export interface PrBodyStruct { @@ -62,7 +63,6 @@ export interface PrBodyStruct { rawConfigHash?: string; rebaseRequested?: boolean; debugData?: PrDebugData; - labelsHash?: string; } /** diff --git a/lib/workers/repository/update/pr/body/index.ts b/lib/workers/repository/update/pr/body/index.ts index abc6e4ff2f3e7e..7722c4b041c640 100644 --- a/lib/workers/repository/update/pr/body/index.ts +++ b/lib/workers/repository/update/pr/body/index.ts @@ -6,7 +6,6 @@ import * as template from '../../../../../util/template'; import { joinUrlParts } from '../../../../../util/url'; import type { BranchConfig } from '../../../../types'; import { getDepWarningsPR, getWarnings } from '../../../errors-warnings'; -import { prepareLabels } from '../labels'; import { getChangelogs } from './changelogs'; import { getPrConfigDescription } from './config-description'; import { getControls } from './controls'; @@ -102,11 +101,6 @@ export function getPrBody( const prDebugData64 = toBase64(JSON.stringify(prBodyConfig.debugData)); prBody += `\n\n`; - // sort the labels, create labelHash and add it as comment to pr body - // adding the comment at top, to tackle github's pr-description length limit of 2000 chars - const prLabelsHash = toBase64(JSON.stringify(prepareLabels(config).sort())); - prBody = `\n\n` + prBody; - prBody = platform.massageMarkdown(prBody); if (prBodyConfig?.rebasingNotice) { diff --git a/lib/workers/repository/update/pr/index.spec.ts b/lib/workers/repository/update/pr/index.spec.ts index ed0ccf73991ae6..5172b87e75b35e 100644 --- a/lib/workers/repository/update/pr/index.spec.ts +++ b/lib/workers/repository/update/pr/index.spec.ts @@ -272,19 +272,25 @@ describe('workers/repository/update/pr/index', () => { describe('Update', () => { // updates labels it('updates PR if labels have changed in config', async () => { + const prDebugData = { + createdInVer: '1.0.0', + targetBranch: 'main', + labels: ['old_label'], + }; + const existingPr: Pr = { ...pr, bodyStruct: getPrBodyStruct( - `\n\n Some body` ), labels: ['old_label'], }; platform.getBranchPr.mockResolvedValueOnce(existingPr); prBody.getPrBody.mockReturnValueOnce( - `\n\n Some body` ); config.labels = ['new_label']; @@ -297,7 +303,11 @@ describe('workers/repository/update/pr/index', () => { labels: ['old_label'], bodyStruct: { hash: expect.any(String), - labelsHash: toBase64(JSON.stringify(['new_label'])), + debugData: { + createdInVer: '1.0.0', + labels: ['new_label'], + targetBranch: 'main', + }, }, }, }); @@ -314,8 +324,8 @@ describe('workers/repository/update/pr/index', () => { expect(prCache.setPrCache).toHaveBeenCalled(); }); - // skips updating labels if existing pr doesn't have labelsHash - it('skips pr update if existing pr does not have labelsHash', async () => { + // skips updating labels if existing pr doesn't have labels in debugData + it('skips pr update if existing pr does not have labels in debugData', async () => { const existingPr: Pr = { ...pr, labels: ['old_label'], @@ -344,11 +354,17 @@ describe('workers/repository/update/pr/index', () => { // skip updating labels if pr labels have been modified by user it('skips pr update if pr labels have been modified by user', async () => { + const prDebugData = { + createdInVer: '1.0.0', + targetBranch: 'main', + labels: ['old_label'], + }; + const existingPr: Pr = { ...pr, bodyStruct: getPrBodyStruct( - `\n\n Some body` ), }; @@ -359,9 +375,19 @@ describe('workers/repository/update/pr/index', () => { expect(res).toEqual({ type: 'with-pr', - pr, + pr: { + ...pr, + bodyStruct: { + hash: expect.any(String), + debugData: { + createdInVer: '1.0.0', + labels: ['old_label'], + targetBranch: 'main', + }, + }, + }, }); - expect(platform.updatePr).toHaveBeenCalled(); + expect(platform.updatePr).not.toHaveBeenCalled(); expect(platform.createPr).not.toHaveBeenCalled(); expect(logger.logger.debug).not.toHaveBeenCalledWith( { @@ -371,9 +397,9 @@ describe('workers/repository/update/pr/index', () => { }, `PR labels have changed` ); - expect(logger.logger.debug).toHaveBeenCalledWith( - 'PR labels have been modified by user, skipping labels update' - ); + // expect(logger.logger.debug).toHaveBeenCalledWith( + // 'PR labels have been modified by user, skipping labels update' + // ); expect(prCache.setPrCache).toHaveBeenCalled(); }); diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index db8e449dc8efe0..d02b0ca3089901 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -27,8 +27,6 @@ import { stripEmojis } from '../../../../util/emoji'; import { fingerprint } from '../../../../util/fingerprint'; import { getBranchLastCommitTime } from '../../../../util/git'; import { memoize } from '../../../../util/memoize'; -import { regEx } from '../../../../util/regex'; -import { toBase64 } from '../../../../util/string'; import { incLimitedValue, isLimitReached } from '../../../global/limits'; import type { BranchConfig, @@ -38,13 +36,19 @@ import type { import { embedChangelogs } from '../../changelog'; import { resolveBranchStatus } from '../branch/status-checks'; import { getPrBody } from './body'; -import { areLabelsModified, getChangedLabels, prepareLabels } from './labels'; +import { + areLabelsModified, + getChangedLabels, + prepareLabels, + shouldUpdateLabels, +} from './labels'; import { addParticipants } from './participants'; import { getPrCache, setPrCache } from './pr-cache'; import { generatePrBodyFingerprintConfig, validatePrCache, } from './pr-fingerprint'; +import { dequal } from 'dequal'; export function getPlatformPrOptions( config: RenovateConfig & PlatformPrOptions @@ -79,15 +83,23 @@ export type EnsurePrResult = ResultWithPr | ResultWithoutPr; export function updatePrDebugData( targetBranch: string, + labels: string[], debugData: PrDebugData | undefined ): PrDebugData { const createdByRenovateVersion = debugData?.createdInVer ?? pkg.version; const updatedByRenovateVersion = pkg.version; - return { + + const updatedPrDebugData: PrDebugData = { createdInVer: createdByRenovateVersion, updatedInVer: updatedByRenovateVersion, targetBranch, }; + + if (debugData?.labels) { + updatedPrDebugData.labels = labels; + } + + return updatedPrDebugData; } function hasNotIgnoredReviewers(pr: Pr, config: BranchConfig): boolean { @@ -324,6 +336,7 @@ export async function ensurePr( { debugData: updatePrDebugData( config.baseBranch, + prepareLabels(config).sort(), existingPr?.bodyStruct?.debugData ), }, @@ -333,13 +346,6 @@ export async function ensurePr( try { if (existingPr) { logger.debug('Processing existing PR'); - - const existingLabelsHash = existingPr.bodyStruct?.labelsHash; - // remove labels hash from pr body if existing pr doesn't have one - if (!existingLabelsHash) { - prBody = prBody.replace(regEx(//g), ''); - } - if ( !existingPr.hasAssignees && !hasNotIgnoredReviewers(existingPr, config) && @@ -356,10 +362,17 @@ export async function ensurePr( const existingPrBodyHash = existingPr.bodyStruct?.hash; const newPrTitle = stripEmojis(prTitle); const newPrBodyHash = hashBody(prBody); + const labelsFromDebugData = existingPr.bodyStruct?.debugData?.labels; + const labelsNeedUpdate = shouldUpdateLabels( + labelsFromDebugData, + existingPr.labels, + config.labels + ); if ( existingPr?.targetBranch === config.baseBranch && existingPrTitle === newPrTitle && - existingPrBodyHash === newPrBodyHash + existingPrBodyHash === newPrBodyHash && + !labelsNeedUpdate ) { // adds or-cache for existing PRs setPrCache(branchName, prBodyFingerprint, false); @@ -387,38 +400,30 @@ export async function ensurePr( ); updatePrConfig.targetBranch = config.baseBranch; } - // if labelsHash is present in pr body - // divide labels into two categories: i) which needs to be added ii) which needs to be removed - // note: existing labels aren't present in these two categories + // divide labels into two categories: i) which needs to be added and ii) which needs to be removed + // Note: existing labels aren't present in these two categories // this is necessary because some platforms handle these two categories separately - if (existingLabelsHash) { + if (labelsNeedUpdate) { const newLabels = prepareLabels(config); - const newLabelsHash = toBase64(JSON.stringify(newLabels)); - // only update labels if there is any change to the labels array && labels haven't been modified by user - if ( - existingLabelsHash !== newLabelsHash && - !areLabelsModified(existingLabelsHash, existingPr.labels) - ) { - logger.debug( - { - branchName, - oldLabels: existingPr.labels, - newLabels, - }, - 'PR labels have changed' - ); - const [addLabels, removeLabels] = getChangedLabels( - existingPr.labels!, - newLabels - ); + logger.debug( + { + branchName, + oldLabels: labelsFromDebugData, + newLabels, + }, + 'PR labels have changed' + ); + const [addLabels, removeLabels] = getChangedLabels( + labelsFromDebugData!, + newLabels + ); - // for gitea - updatePrConfig.labels = newLabels; + // for gitea + updatePrConfig.labels = newLabels; - // for github, gitlab - updatePrConfig.addLabels = addLabels; - updatePrConfig.removeLabels = removeLabels; - } + // for github, gitlab + updatePrConfig.addLabels = addLabels; + updatePrConfig.removeLabels = removeLabels; } if (existingPrTitle !== newPrTitle) { logger.debug( diff --git a/lib/workers/repository/update/pr/labels.spec.ts b/lib/workers/repository/update/pr/labels.spec.ts index 143f2de88faaa4..af11445da009cc 100644 --- a/lib/workers/repository/update/pr/labels.spec.ts +++ b/lib/workers/repository/update/pr/labels.spec.ts @@ -1,4 +1,9 @@ -import { areLabelsModified, getChangedLabels, prepareLabels } from './labels'; +import { + areLabelsModified, + getChangedLabels, + prepareLabels, + shouldUpdateLabels, +} from './labels'; describe('workers/repository/update/pr/labels', () => { describe('prepareLabels(config)', () => { @@ -97,12 +102,34 @@ describe('workers/repository/update/pr/labels', () => { describe('areLabelsModified', () => { it('returns true', () => { - expect(areLabelsModified('WyJub2RlIiwibnBtIl0=', ['npm'])).toBeTrue(); + expect(areLabelsModified(['npm', 'node'], ['npm'])).toBeTrue(); }); it('returns false', () => { + expect(areLabelsModified(['node', 'npm'], ['node', 'npm'])).toBeFalse(); + }); + }); + + describe('shouldUpdateLabels', () => { + it('returns true', () => { + expect( + shouldUpdateLabels(['npm', 'node'], ['npm', 'node'], ['npm']) + ).toBeTrue(); + }); + + it('returns false if no labels found in debugData', () => { + expect( + shouldUpdateLabels(undefined, ['npm', 'node'], ['npm', 'node']) + ).toBeFalse(); + }); + + it('returns false if labels have been modified by user', () => { + expect(shouldUpdateLabels(['npm', 'node'], ['npm'], ['npm'])).toBeFalse(); + }); + + it('returns false if labels are not changed', () => { expect( - areLabelsModified('WyJub2RlIiwibnBtIl0=', ['node', 'npm']) + shouldUpdateLabels(['npm', 'node'], ['npm', 'node'], ['npm', 'node']) ).toBeFalse(); }); }); diff --git a/lib/workers/repository/update/pr/labels.ts b/lib/workers/repository/update/pr/labels.ts index c97d5dca9bed4f..0d09897fe9bffc 100644 --- a/lib/workers/repository/update/pr/labels.ts +++ b/lib/workers/repository/update/pr/labels.ts @@ -1,8 +1,9 @@ import is from '@sindresorhus/is'; import type { RenovateConfig } from '../../../../config/types'; -import { logger } from '../../../../logger'; -import { toBase64 } from '../../../../util/string'; import * as template from '../../../../util/template'; +import { dequal } from 'dequal'; +import { logger } from '../../../../logger'; +import { id } from 'common-tags'; export function prepareLabels(config: RenovateConfig): string[] { const labels = config.labels ?? []; @@ -24,18 +25,36 @@ export function getChangedLabels( } export function areLabelsModified( - oldLabelsHash: string, - existingLabels?: string[] + oldLabels: string[], + newLabels?: string[] ): boolean { - const existingLabelsHash = toBase64( - JSON.stringify(existingLabels?.sort() ?? []) - ); - if (existingLabelsHash !== oldLabelsHash) { + const modified = !dequal(oldLabels.sort(), newLabels?.sort()); + + if (modified) { logger.debug( 'PR labels have been modified by user, skipping labels update' ); - return true; } - return false; + return modified; +} + +export function shouldUpdateLabels( + labelsInDebugData?: string[], + labelsInPr?: string[], + newLabels?: string[] +): boolean { + if (!labelsInDebugData) { + return false; + } + + if (areLabelsModified(labelsInDebugData, labelsInPr)) { + return false; + } + + if (dequal((newLabels ?? []).sort(), labelsInDebugData.sort())) { + return false; + } + + return true; } From 277f2d65d30b44e32f7a9f5c2641376bfcc14b09 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Mon, 6 Nov 2023 17:00:18 +0545 Subject: [PATCH 20/60] fix build issues --- lib/modules/platform/pr-body.ts | 9 --------- lib/workers/repository/update/pr/index.ts | 10 ++-------- lib/workers/repository/update/pr/labels.ts | 5 ++--- 3 files changed, 4 insertions(+), 20 deletions(-) diff --git a/lib/modules/platform/pr-body.ts b/lib/modules/platform/pr-body.ts index ae3de68fe59b0d..b203565a70f654 100644 --- a/lib/modules/platform/pr-body.ts +++ b/lib/modules/platform/pr-body.ts @@ -15,7 +15,6 @@ const renovateConfigHashRe = regEx( ); const prCheckboxRe = regEx(/- (?\[[\sx]]) /); -const prLabelsRe = regEx(/\n?\n?/); function noWhitespaceOrHeadings(input: string): string { return input.replace(regEx(/\r?\n|\r|\s|#/g), ''); @@ -44,14 +43,6 @@ function isRebaseRequested(body: string): boolean | undefined { return match.groups?.checkbox === '[x]'; } -function getLabels(body: string): string | undefined { - const match = prLabelsRe.exec(body); - if (!match) { - return undefined; - } - return match.groups?.labels; -} - export function getRenovateDebugPayload(body: string): string | undefined { const match = prDebugDataRe.exec(body); return match?.groups?.payload; diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index d02b0ca3089901..72f6771b33da99 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -36,19 +36,13 @@ import type { import { embedChangelogs } from '../../changelog'; import { resolveBranchStatus } from '../branch/status-checks'; import { getPrBody } from './body'; -import { - areLabelsModified, - getChangedLabels, - prepareLabels, - shouldUpdateLabels, -} from './labels'; +import { getChangedLabels, prepareLabels, shouldUpdateLabels } from './labels'; import { addParticipants } from './participants'; import { getPrCache, setPrCache } from './pr-cache'; import { generatePrBodyFingerprintConfig, validatePrCache, } from './pr-fingerprint'; -import { dequal } from 'dequal'; export function getPlatformPrOptions( config: RenovateConfig & PlatformPrOptions @@ -331,7 +325,7 @@ export async function ensurePr( } } - let prBody = getPrBody( + const prBody = getPrBody( config, { debugData: updatePrDebugData( diff --git a/lib/workers/repository/update/pr/labels.ts b/lib/workers/repository/update/pr/labels.ts index 0d09897fe9bffc..3fd958b3c2dbe7 100644 --- a/lib/workers/repository/update/pr/labels.ts +++ b/lib/workers/repository/update/pr/labels.ts @@ -1,9 +1,8 @@ import is from '@sindresorhus/is'; -import type { RenovateConfig } from '../../../../config/types'; -import * as template from '../../../../util/template'; import { dequal } from 'dequal'; +import type { RenovateConfig } from '../../../../config/types'; import { logger } from '../../../../logger'; -import { id } from 'common-tags'; +import * as template from '../../../../util/template'; export function prepareLabels(config: RenovateConfig): string[] { const labels = config.labels ?? []; From 3192786c6c32f75ee068a541d0e15722a5ef4d54 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Mon, 6 Nov 2023 17:56:27 +0545 Subject: [PATCH 21/60] fix coverage --- lib/workers/repository/update/pr/labels.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/workers/repository/update/pr/labels.spec.ts b/lib/workers/repository/update/pr/labels.spec.ts index af11445da009cc..277f35b17adb96 100644 --- a/lib/workers/repository/update/pr/labels.spec.ts +++ b/lib/workers/repository/update/pr/labels.spec.ts @@ -115,6 +115,7 @@ describe('workers/repository/update/pr/labels', () => { expect( shouldUpdateLabels(['npm', 'node'], ['npm', 'node'], ['npm']) ).toBeTrue(); + expect(shouldUpdateLabels(['npm', 'node'], ['npm', 'node'])).toBeTrue(); }); it('returns false if no labels found in debugData', () => { From 61fe7d1f02b879ad3b3e032fe9a99739e5ff21ed Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Tue, 7 Nov 2023 09:31:48 +0545 Subject: [PATCH 22/60] fix: logic updatePrdebugData add labels to debugData when creating PR --- lib/workers/repository/update/pr/index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index 72f6771b33da99..cace8602e1fdee 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -89,7 +89,9 @@ export function updatePrDebugData( targetBranch, }; - if (debugData?.labels) { + // this might seems confusing but we wither want there to be no debugData ie. this is a new PR in creation + // or debugData with labels array ie. pr created with the new update labels logic + if (!debugData || is.array(debugData?.labels)) { updatedPrDebugData.labels = labels; } From b08bba8587b1ec7b1158863aa595c2542415114c Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Tue, 7 Nov 2023 09:47:46 +0100 Subject: [PATCH 23/60] Update lib/workers/repository/update/pr/body/index.ts --- lib/workers/repository/update/pr/body/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/workers/repository/update/pr/body/index.ts b/lib/workers/repository/update/pr/body/index.ts index 7722c4b041c640..8e07a77a0afb1d 100644 --- a/lib/workers/repository/update/pr/body/index.ts +++ b/lib/workers/repository/update/pr/body/index.ts @@ -100,7 +100,6 @@ export function getPrBody( prBody = prBody.replace(regEx(/\n\n\n+/g), '\n\n'); const prDebugData64 = toBase64(JSON.stringify(prBodyConfig.debugData)); prBody += `\n\n`; - prBody = platform.massageMarkdown(prBody); if (prBodyConfig?.rebasingNotice) { From 407223e3393701a5694022ade6a516b5ce228114 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Wed, 8 Nov 2023 17:43:29 +0545 Subject: [PATCH 24/60] fix formatting --- lib/modules/platform/codecommit/index.spec.ts | 3 +-- .../platform/gitea/gitea-helper.spec.ts | 4 ++-- lib/modules/platform/gitea/gitea-helper.ts | 2 +- lib/modules/platform/github/index.spec.ts | 4 ++-- lib/modules/platform/gitlab/index.spec.ts | 4 ++-- lib/workers/repository/update/pr/index.spec.ts | 18 +++++++++--------- lib/workers/repository/update/pr/index.ts | 10 +++++----- .../repository/update/pr/labels.spec.ts | 6 +++--- lib/workers/repository/update/pr/labels.ts | 8 ++++---- 9 files changed, 29 insertions(+), 30 deletions(-) diff --git a/lib/modules/platform/codecommit/index.spec.ts b/lib/modules/platform/codecommit/index.spec.ts index 0252d413c3d2bc..2af857a2f60d54 100644 --- a/lib/modules/platform/codecommit/index.spec.ts +++ b/lib/modules/platform/codecommit/index.spec.ts @@ -53,8 +53,7 @@ describe('modules/platform/codecommit/index', () => { }); it('validates massageMarkdown functionality', () => { - const newStr = codeCommit.massageMarkdown( - ); + const newStr = codeCommit.massageMarkdown(); expect(newStr).toBe( '**foo**bartext\n[//]: # ()', ); diff --git a/lib/modules/platform/gitea/gitea-helper.spec.ts b/lib/modules/platform/gitea/gitea-helper.spec.ts index 6d53d27413f9bc..193aa97870dbc5 100644 --- a/lib/modules/platform/gitea/gitea-helper.spec.ts +++ b/lib/modules/platform/gitea/gitea-helper.spec.ts @@ -389,7 +389,7 @@ describe('modules/platform/gitea/gitea-helper', () => { await expect( mergePR(mockRepo.full_name, mockPR.number, { Do: 'rebase', - }) + }), ).toResolve(); }); }); @@ -613,7 +613,7 @@ describe('modules/platform/gitea/gitea-helper', () => { const res = await assignLabel( mockRepo.full_name, mockIssue.number, - mockLabel.id + mockLabel.id, ); expect(res).toBeUndefined(); }); diff --git a/lib/modules/platform/gitea/gitea-helper.ts b/lib/modules/platform/gitea/gitea-helper.ts index f9af9f6e29e7cf..d43dc5c45bda6e 100644 --- a/lib/modules/platform/gitea/gitea-helper.ts +++ b/lib/modules/platform/gitea/gitea-helper.ts @@ -310,7 +310,7 @@ export async function assignLabel( repoPath: string, issue: number, label: number, - options?: GiteaHttpOptions + options?: GiteaHttpOptions, ): Promise { const url = `${API_PATH}/repos/${repoPath}/issues/${issue}/labels`; await giteaHttp.patchJson(url, { diff --git a/lib/modules/platform/github/index.spec.ts b/lib/modules/platform/github/index.spec.ts index c6b061b6984327..b6f4b892601478 100644 --- a/lib/modules/platform/github/index.spec.ts +++ b/lib/modules/platform/github/index.spec.ts @@ -3083,10 +3083,10 @@ describe('modules/platform/github/index', () => { await expect(github.updatePr(pr)).toResolve(); expect(logger.logger.debug).toHaveBeenCalledWith( - `Adding labels 'new_label' to #1234` + `Adding labels 'new_label' to #1234`, ); expect(logger.logger.debug).toHaveBeenCalledWith( - `Deleting label old_label from #1234` + `Deleting label old_label from #1234`, ); }); }); diff --git a/lib/modules/platform/gitlab/index.spec.ts b/lib/modules/platform/gitlab/index.spec.ts index 767dd473e3f260..74e930d2294b11 100644 --- a/lib/modules/platform/gitlab/index.spec.ts +++ b/lib/modules/platform/gitlab/index.spec.ts @@ -2545,7 +2545,7 @@ describe('modules/platform/gitlab/index', () => { httpMock .scope(gitlabApiHost) .get( - '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me' + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', ) .reply(200, [ { @@ -2566,7 +2566,7 @@ describe('modules/platform/gitlab/index', () => { state: 'closed', addLabels: ['new_label'], removeLabels: ['old_label'], - }) + }), ).toResolve(); }); }); diff --git a/lib/workers/repository/update/pr/index.spec.ts b/lib/workers/repository/update/pr/index.spec.ts index ca8eebc130aaa4..5344912b84d34d 100644 --- a/lib/workers/repository/update/pr/index.spec.ts +++ b/lib/workers/repository/update/pr/index.spec.ts @@ -282,16 +282,16 @@ describe('workers/repository/update/pr/index', () => { ...pr, bodyStruct: getPrBodyStruct( `\n\n Some body` + JSON.stringify(prDebugData), + )}-->\n Some body`, ), labels: ['old_label'], }; platform.getBranchPr.mockResolvedValueOnce(existingPr); prBody.getPrBody.mockReturnValueOnce( `\n\n Some body` + JSON.stringify({ ...prDebugData, labels: ['new_label'] }), + )}-->\n Some body`, ); config.labels = ['new_label']; const res = await ensurePr(config); @@ -319,7 +319,7 @@ describe('workers/repository/update/pr/index', () => { oldLabels: ['old_label'], newLabels: ['new_label'], }, - `PR labels have changed` + `PR labels have changed`, ); expect(prCache.setPrCache).toHaveBeenCalled(); }); @@ -347,7 +347,7 @@ describe('workers/repository/update/pr/index', () => { oldLabels: ['old_label'], newLabels: ['new_label'], }, - `PR labels have changed` + `PR labels have changed`, ); expect(prCache.setPrCache).toHaveBeenCalled(); }); @@ -364,8 +364,8 @@ describe('workers/repository/update/pr/index', () => { ...pr, bodyStruct: getPrBodyStruct( `\n\n Some body` + JSON.stringify(prDebugData), + )}-->\n Some body`, ), }; platform.getBranchPr.mockResolvedValueOnce(existingPr); @@ -395,7 +395,7 @@ describe('workers/repository/update/pr/index', () => { oldLabels: ['old_label'], newLabels: ['new_label'], }, - `PR labels have changed` + `PR labels have changed`, ); // expect(logger.logger.debug).toHaveBeenCalledWith( // 'PR labels have been modified by user, skipping labels update' diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index 97a95603f3edea..34637f842a3a30 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -78,7 +78,7 @@ export type EnsurePrResult = ResultWithPr | ResultWithoutPr; export function updatePrDebugData( targetBranch: string, labels: string[], - debugData: PrDebugData | undefined + debugData: PrDebugData | undefined, ): PrDebugData { const createdByRenovateVersion = debugData?.createdInVer ?? pkg.version; const updatedByRenovateVersion = pkg.version; @@ -333,7 +333,7 @@ export async function ensurePr( debugData: updatePrDebugData( config.baseBranch, prepareLabels(config).sort(), - existingPr?.bodyStruct?.debugData + existingPr?.bodyStruct?.debugData, ), }, config, @@ -362,7 +362,7 @@ export async function ensurePr( const labelsNeedUpdate = shouldUpdateLabels( labelsFromDebugData, existingPr.labels, - config.labels + config.labels, ); if ( existingPr?.targetBranch === config.baseBranch && @@ -407,11 +407,11 @@ export async function ensurePr( oldLabels: labelsFromDebugData, newLabels, }, - 'PR labels have changed' + 'PR labels have changed', ); const [addLabels, removeLabels] = getChangedLabels( labelsFromDebugData!, - newLabels + newLabels, ); // for gitea diff --git a/lib/workers/repository/update/pr/labels.spec.ts b/lib/workers/repository/update/pr/labels.spec.ts index 277f35b17adb96..fd9acddeb5579f 100644 --- a/lib/workers/repository/update/pr/labels.spec.ts +++ b/lib/workers/repository/update/pr/labels.spec.ts @@ -113,14 +113,14 @@ describe('workers/repository/update/pr/labels', () => { describe('shouldUpdateLabels', () => { it('returns true', () => { expect( - shouldUpdateLabels(['npm', 'node'], ['npm', 'node'], ['npm']) + shouldUpdateLabels(['npm', 'node'], ['npm', 'node'], ['npm']), ).toBeTrue(); expect(shouldUpdateLabels(['npm', 'node'], ['npm', 'node'])).toBeTrue(); }); it('returns false if no labels found in debugData', () => { expect( - shouldUpdateLabels(undefined, ['npm', 'node'], ['npm', 'node']) + shouldUpdateLabels(undefined, ['npm', 'node'], ['npm', 'node']), ).toBeFalse(); }); @@ -130,7 +130,7 @@ describe('workers/repository/update/pr/labels', () => { it('returns false if labels are not changed', () => { expect( - shouldUpdateLabels(['npm', 'node'], ['npm', 'node'], ['npm', 'node']) + shouldUpdateLabels(['npm', 'node'], ['npm', 'node'], ['npm', 'node']), ).toBeFalse(); }); }); diff --git a/lib/workers/repository/update/pr/labels.ts b/lib/workers/repository/update/pr/labels.ts index 3fd958b3c2dbe7..5a1600ed609c88 100644 --- a/lib/workers/repository/update/pr/labels.ts +++ b/lib/workers/repository/update/pr/labels.ts @@ -15,7 +15,7 @@ export function prepareLabels(config: RenovateConfig): string[] { export function getChangedLabels( oldLabels: string[], - newLabels: string[] + newLabels: string[], ): [string[] | null, string[] | null] { const labelsToAdd = newLabels?.filter((l) => !oldLabels?.includes(l)); const labelsToRemove = oldLabels?.filter((l) => !newLabels?.includes(l)); @@ -25,13 +25,13 @@ export function getChangedLabels( export function areLabelsModified( oldLabels: string[], - newLabels?: string[] + newLabels?: string[], ): boolean { const modified = !dequal(oldLabels.sort(), newLabels?.sort()); if (modified) { logger.debug( - 'PR labels have been modified by user, skipping labels update' + 'PR labels have been modified by user, skipping labels update', ); } @@ -41,7 +41,7 @@ export function areLabelsModified( export function shouldUpdateLabels( labelsInDebugData?: string[], labelsInPr?: string[], - newLabels?: string[] + newLabels?: string[], ): boolean { if (!labelsInDebugData) { return false; From 727e013a1633b80c4d56155f90bee5b51ab28a0f Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Wed, 8 Nov 2023 18:01:15 +0545 Subject: [PATCH 25/60] revert the labels struct changes --- docs/usage/configuration-options.md | 4 + lib/modules/platform/azure/index.spec.ts | 93 +++++++++---------- lib/modules/platform/azure/index.ts | 9 +- .../platform/bitbucket-server/index.spec.ts | 1 - .../platform/bitbucket-server/index.ts | 3 +- lib/modules/platform/bitbucket/index.spec.ts | 3 +- lib/modules/platform/bitbucket/index.ts | 3 +- lib/modules/platform/codecommit/index.spec.ts | 4 +- lib/modules/platform/gitlab/index.spec.ts | 1 - 9 files changed, 61 insertions(+), 60 deletions(-) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index b8bbd8b453b5ed..4d04149b5a5100 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -2036,6 +2036,10 @@ Behaviour details: The `labels` array is non-mergeable, meaning if multiple `packageRules` match then Renovate uses the last value for `labels`. If you want to add/combine labels, use the `addLabels` config option, which is mergeable. + +!!! note + Currently updating of the labels on open PRs is only supported for the platforms: github, gitlab and gitea + ## lockFileMaintenance You can use `lockFileMaintenance` to refresh lock files to keep them up-to-date. diff --git a/lib/modules/platform/azure/index.spec.ts b/lib/modules/platform/azure/index.spec.ts index 7b22515992300b..3f4b4a40743e59 100644 --- a/lib/modules/platform/azure/index.spec.ts +++ b/lib/modules/platform/azure/index.spec.ts @@ -75,7 +75,7 @@ describe('modules/platform/azure/index', () => { }, }, ]), - }) as any, + } as any), ); return azure.getRepos(); } @@ -229,7 +229,7 @@ describe('modules/platform/azure/index', () => { }, ]), getPullRequestCommits: jest.fn().mockReturnValue([]), - }) as any, + } as any), ); const res = await azure.findPr({ branchName: 'branch-a', @@ -270,7 +270,7 @@ describe('modules/platform/azure/index', () => { }, ]), getPullRequestCommits: jest.fn().mockReturnValue([]), - }) as any, + } as any), ); const res = await azure.findPr({ branchName: 'branch-a', @@ -311,7 +311,7 @@ describe('modules/platform/azure/index', () => { }, ]), getPullRequestCommits: jest.fn().mockReturnValue([]), - }) as any, + } as any), ); const res = await azure.findPr({ branchName: 'branch-a', @@ -352,7 +352,7 @@ describe('modules/platform/azure/index', () => { }, ]), getPullRequestCommits: jest.fn().mockReturnValue([]), - }) as any, + } as any), ); const res = await azure.findPr({ branchName: 'branch-a', @@ -491,7 +491,7 @@ describe('modules/platform/azure/index', () => { () => ({ getPullRequests: jest.fn(() => []), - }) as any, + } as any), ); expect(await azure.getPrList()).toEqual([]); }); @@ -561,7 +561,7 @@ describe('modules/platform/azure/index', () => { context: { genre: 'a-genre', name: 'a-name' }, }, ]), - }) as any, + } as any), ); const res = await azure.getBranchStatusCheck( 'somebranch', @@ -582,7 +582,7 @@ describe('modules/platform/azure/index', () => { context: { genre: 'a-genre', name: 'a-name' }, }, ]), - }) as any, + } as any), ); const res = await azure.getBranchStatusCheck( 'somebranch', @@ -603,7 +603,7 @@ describe('modules/platform/azure/index', () => { context: { genre: 'a-genre', name: 'a-name' }, }, ]), - }) as any, + } as any), ); const res = await azure.getBranchStatusCheck( 'somebranch', @@ -624,7 +624,7 @@ describe('modules/platform/azure/index', () => { context: { genre: 'a-genre', name: 'a-name' }, }, ]), - }) as any, + } as any), ); const res = await azure.getBranchStatusCheck( 'somebranch', @@ -645,7 +645,7 @@ describe('modules/platform/azure/index', () => { context: { genre: 'a-genre', name: 'a-name' }, }, ]), - }) as any, + } as any), ); const res = await azure.getBranchStatusCheck( 'somebranch', @@ -666,7 +666,7 @@ describe('modules/platform/azure/index', () => { context: { genre: 'a-genre', name: 'a-name' }, }, ]), - }) as any, + } as any), ); const res = await azure.getBranchStatusCheck( 'somebranch', @@ -709,7 +709,7 @@ describe('modules/platform/azure/index', () => { context: { genre: 'another-genre', name: 'a-name' }, }, ]), - }) as any, + } as any), ); const res = await azure.getBranchStatusCheck( 'somebranch', @@ -732,7 +732,7 @@ describe('modules/platform/azure/index', () => { context: { genre: 'renovate' }, }, ]), - }) as any, + } as any), ); const res = await azure.getBranchStatus('somebranch', true); expect(res).toBe('green'); @@ -750,7 +750,7 @@ describe('modules/platform/azure/index', () => { context: { genre: 'renovate' }, }, ]), - }) as any, + } as any), ); const res = await azure.getBranchStatus('somebranch', false); expect(res).toBe('yellow'); @@ -763,7 +763,7 @@ describe('modules/platform/azure/index', () => { ({ getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })), getStatuses: jest.fn(() => [{ state: GitStatusState.Error }]), - }) as any, + } as any), ); const res = await azure.getBranchStatus('somebranch', true); expect(res).toBe('red'); @@ -776,7 +776,7 @@ describe('modules/platform/azure/index', () => { ({ getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })), getStatuses: jest.fn(() => [{ state: GitStatusState.Pending }]), - }) as any, + } as any), ); const res = await azure.getBranchStatus('somebranch', true); expect(res).toBe('yellow'); @@ -789,7 +789,7 @@ describe('modules/platform/azure/index', () => { ({ getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })), getStatuses: jest.fn(() => []), - }) as any, + } as any), ); const res = await azure.getBranchStatus('somebranch', true); expect(res).toBe('yellow'); @@ -808,7 +808,7 @@ describe('modules/platform/azure/index', () => { () => ({ getPullRequests: jest.fn(() => []), - }) as any, + } as any), ); const pr = await azure.getPr(1234); expect(pr).toBeNull(); @@ -837,7 +837,7 @@ describe('modules/platform/azure/index', () => { }, }, ]), - }) as any, + } as any), ); const pr = await azure.getPr(1234); expect(pr).toMatchSnapshot(); @@ -854,7 +854,7 @@ describe('modules/platform/azure/index', () => { pullRequestId: 456, })), createPullRequestLabel: jest.fn(() => ({})), - }) as any, + } as any), ); const pr = await azure.createPr({ sourceBranch: 'some-branch', @@ -875,7 +875,7 @@ describe('modules/platform/azure/index', () => { pullRequestId: 456, })), createPullRequestLabel: jest.fn(() => ({})), - }) as any, + } as any), ); const pr = await azure.createPr({ sourceBranch: 'some-branch', @@ -1034,7 +1034,7 @@ describe('modules/platform/azure/index', () => { createPullRequest: jest.fn(() => prResult), createPullRequestLabel: jest.fn(() => ({})), createPullRequestReviewer: updateFn, - }) as any, + } as any), ); const pr = await azure.createPr({ sourceBranch: 'some-branch', @@ -1057,7 +1057,7 @@ describe('modules/platform/azure/index', () => { () => ({ updatePullRequest, - }) as any, + } as any), ); await azure.updatePr({ number: 1234, @@ -1075,7 +1075,7 @@ describe('modules/platform/azure/index', () => { () => ({ updatePullRequest, - }) as any, + } as any), ); await azure.updatePr({ number: 1234, @@ -1091,7 +1091,7 @@ describe('modules/platform/azure/index', () => { () => ({ updatePullRequest, - }) as any, + } as any), ); await azure.updatePr({ number: 1234, @@ -1109,7 +1109,7 @@ describe('modules/platform/azure/index', () => { () => ({ updatePullRequest, - }) as any, + } as any), ); await azure.updatePr({ number: 1234, @@ -1145,7 +1145,7 @@ describe('modules/platform/azure/index', () => { pullRequestId: prResult.pullRequestId, createdBy: prResult.createdBy, })), - }) as any, + } as any), ); const pr = await azure.updatePr({ number: prResult.pullRequestId, @@ -1360,7 +1360,7 @@ describe('modules/platform/azure/index', () => { getRepositories: jest.fn(() => [{ id: '1', project: { id: 2 } }]), createThread: jest.fn(() => [{ id: 123 }]), getThreads: jest.fn(() => []), - }) as any, + } as any), ); azureApi.coreApi.mockImplementation( () => @@ -1372,7 +1372,7 @@ describe('modules/platform/azure/index', () => { getTeamMembersWithExtendedProperties: jest.fn(() => [ { identity: { displayName: 'jyc', uniqueName: 'jyc', id: 123 } }, ]), - }) as any, + } as any), ); await azure.addAssignees(123, ['test@bonjour.fr', 'jyc', 'def']); expect(azureApi.gitApi).toHaveBeenCalledTimes(3); @@ -1387,7 +1387,7 @@ describe('modules/platform/azure/index', () => { ({ getRepositories: jest.fn(() => [{ id: '1', project: { id: 2 } }]), createPullRequestReviewer: jest.fn(), - }) as any, + } as any), ); azureApi.coreApi.mockImplementation( () => @@ -1399,7 +1399,7 @@ describe('modules/platform/azure/index', () => { getTeamMembersWithExtendedProperties: jest.fn(() => [ { identity: { displayName: 'jyc', uniqueName: 'jyc', id: 123 } }, ]), - }) as any, + } as any), ); await azure.addReviewers(123, ['test@bonjour.fr', 'jyc', 'required:def']); expect(azureApi.gitApi).toHaveBeenCalledTimes(3); @@ -1410,8 +1410,7 @@ describe('modules/platform/azure/index', () => { it('returns updated pr body', () => { const prBody = '\n---\n\n - [ ] rebase\n' + - 'plus also [a link](https://github.com/foo/bar/issues/5)' + - ``; + 'plus also [a link](https://github.com/foo/bar/issues/5)'; expect(azure.massageMarkdown(prBody)).toBe( 'plus also [a link](https://github.com/foo/bar/issues/5)', ); @@ -1436,7 +1435,7 @@ describe('modules/platform/azure/index', () => { ({ getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })), createCommitStatus: createCommitStatusMock, - }) as any, + } as any), ); await azure.setBranchStatus({ branchName: 'test', @@ -1468,7 +1467,7 @@ describe('modules/platform/azure/index', () => { ({ getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })), createCommitStatus: createCommitStatusMock, - }) as any, + } as any), ); await azure.setBranchStatus({ branchName: 'test', @@ -1511,7 +1510,7 @@ describe('modules/platform/azure/index', () => { title: 'title', })), updatePullRequest: updatePullRequestMock, - }) as any, + } as any), ); azureHelper.getMergeMethod = jest @@ -1553,7 +1552,7 @@ describe('modules/platform/azure/index', () => { updatePullRequest: jest .fn() .mockRejectedValue(new Error(`oh no pr couldn't be updated`)), - }) as any, + } as any), ); azureHelper.getMergeMethod = jest @@ -1577,7 +1576,7 @@ describe('modules/platform/azure/index', () => { targetRefName: 'refs/heads/ding', })), updatePullRequest: jest.fn(), - }) as any, + } as any), ); azureHelper.getMergeMethod = jest .fn() @@ -1612,7 +1611,7 @@ describe('modules/platform/azure/index', () => { updatePullRequest: jest.fn(() => ({ status: 1, })), - }) as any, + } as any), ); azureHelper.getMergeMethod = jest .fn() @@ -1644,7 +1643,7 @@ describe('modules/platform/azure/index', () => { updatePullRequest: jest.fn(() => ({ status: 1, })), - }) as any, + } as any), ); azureHelper.getMergeMethod = jest .fn() @@ -1668,7 +1667,7 @@ describe('modules/platform/azure/index', () => { () => ({ deletePullRequestLabels: jest.fn(), - }) as any, + } as any), ); await azure.deleteLabel(1234, 'rebase'); expect(azureApi.gitApi.mock.calls).toMatchSnapshot(); @@ -1688,7 +1687,7 @@ describe('modules/platform/azure/index', () => { getItemContent: jest.fn(() => Promise.resolve(Readable.from(JSON.stringify(data))), ), - }) as any, + } as any), ); const res = await azure.getJsonFile('file.json'); expect(res).toEqual(data); @@ -1707,7 +1706,7 @@ describe('modules/platform/azure/index', () => { getItemContent: jest.fn(() => Promise.resolve(Readable.from(json5Data)), ), - }) as any, + } as any), ); const res = await azure.getJsonFile('file.json5'); expect(res).toEqual({ foo: 'bar' }); @@ -1721,7 +1720,7 @@ describe('modules/platform/azure/index', () => { getItemContent: jest.fn(() => Promise.resolve(Readable.from(JSON.stringify(data))), ), - }) as any, + } as any), ); const res = await azure.getJsonFile('file.json', undefined, 'dev'); expect(res).toEqual(data); @@ -1734,7 +1733,7 @@ describe('modules/platform/azure/index', () => { getItemContent: jest.fn(() => Promise.resolve(Readable.from('!@#')), ), - }) as any, + } as any), ); await expect(azure.getJsonFile('file.json')).rejects.toThrow(); }); @@ -1746,7 +1745,7 @@ describe('modules/platform/azure/index', () => { getItemContent: jest.fn(() => { throw new Error('some error'); }), - }) as any, + } as any), ); await expect(azure.getJsonFile('file.json')).rejects.toThrow(); }); diff --git a/lib/modules/platform/azure/index.ts b/lib/modules/platform/azure/index.ts index aa3485388295e7..874da300b9ff6d 100644 --- a/lib/modules/platform/azure/index.ts +++ b/lib/modules/platform/azure/index.ts @@ -754,8 +754,10 @@ export async function mergePr({ logger.trace( `Updating PR ${pullRequestId} to status ${PullRequestStatus.Completed} (${ PullRequestStatus[PullRequestStatus.Completed] - }) with lastMergeSourceCommit ${// TODO: types (#22198) - pr.lastMergeSourceCommit?.commitId} using mergeStrategy ${mergeStrategy} (${ + }) with lastMergeSourceCommit ${ + // TODO: types (#22198) + pr.lastMergeSourceCommit?.commitId + } using mergeStrategy ${mergeStrategy} (${ GitPullRequestMergeStrategy[mergeStrategy] })`, ); @@ -810,8 +812,7 @@ export function massageMarkdown(input: string): string { 'renaming the PR to start with "rebase!"', ) .replace(regEx(`\n---\n\n.*?.*?\n`), '') - .replace(regEx(//g), '') - .replace(regEx(//g), ''); + .replace(regEx(//g), ''); } /* istanbul ignore next */ diff --git a/lib/modules/platform/bitbucket-server/index.spec.ts b/lib/modules/platform/bitbucket-server/index.spec.ts index 315be78c24cc8e..b5236718daade1 100644 --- a/lib/modules/platform/bitbucket-server/index.spec.ts +++ b/lib/modules/platform/bitbucket-server/index.spec.ts @@ -1743,7 +1743,6 @@ describe('modules/platform/bitbucket-server/index', () => { Empty comment. - Followed by some information. `); expect(prBody).toMatchSnapshot(); diff --git a/lib/modules/platform/bitbucket-server/index.ts b/lib/modules/platform/bitbucket-server/index.ts index a43e695d802d83..bd9a0be19c34c0 100644 --- a/lib/modules/platform/bitbucket-server/index.ts +++ b/lib/modules/platform/bitbucket-server/index.ts @@ -983,6 +983,5 @@ export function massageMarkdown(input: string): string { .replace(regEx(/<\/?summary>/g), '**') .replace(regEx(/<\/?details>/g), '') .replace(regEx(`\n---\n\n.*?.*?(\n|$)`), '') - .replace(regEx('', 'g'), '') - .replace(regEx(//g), ''); + .replace(regEx('', 'g'), ''); } diff --git a/lib/modules/platform/bitbucket/index.spec.ts b/lib/modules/platform/bitbucket/index.spec.ts index b6b288ff064d6d..f898638bc1f877 100644 --- a/lib/modules/platform/bitbucket/index.spec.ts +++ b/lib/modules/platform/bitbucket/index.spec.ts @@ -1370,8 +1370,7 @@ describe('modules/platform/bitbucket/index', () => { const prBody = '
foo\n
\n\n
text' + '\n---\n\n - [ ] rebase\n' + - '\n\n
\n\n
\n
' + - ``; + '\n\n
\n\n\n
'; expect(bitbucket.massageMarkdown(prBody)).toMatchSnapshot(); }); }); diff --git a/lib/modules/platform/bitbucket/index.ts b/lib/modules/platform/bitbucket/index.ts index 61ee2e5006b119..9f30b6e2aef8ff 100644 --- a/lib/modules/platform/bitbucket/index.ts +++ b/lib/modules/platform/bitbucket/index.ts @@ -564,8 +564,7 @@ export function massageMarkdown(input: string): string { .replace(regEx(/<\/?(details|blockquote)>/g), '') .replace(regEx(`\n---\n\n.*?.*?\n`), '') .replace(regEx(/\]\(\.\.\/pull\//g), '](../../pull-requests/') - .replace(regEx(//g), '') - .replace(regEx(//g), ''); + .replace(regEx(//g), ''); } export async function ensureIssue({ diff --git a/lib/modules/platform/codecommit/index.spec.ts b/lib/modules/platform/codecommit/index.spec.ts index 2af857a2f60d54..d56363fe16e3c9 100644 --- a/lib/modules/platform/codecommit/index.spec.ts +++ b/lib/modules/platform/codecommit/index.spec.ts @@ -53,7 +53,9 @@ describe('modules/platform/codecommit/index', () => { }); it('validates massageMarkdown functionality', () => { - const newStr = codeCommit.massageMarkdown(); + const newStr = codeCommit.massageMarkdown( + '
foobar
text
\n', + ); expect(newStr).toBe( '**foo**bartext\n[//]: # ()', ); diff --git a/lib/modules/platform/gitlab/index.spec.ts b/lib/modules/platform/gitlab/index.spec.ts index 74e930d2294b11..d6f602c77f3fff 100644 --- a/lib/modules/platform/gitlab/index.spec.ts +++ b/lib/modules/platform/gitlab/index.spec.ts @@ -2553,7 +2553,6 @@ describe('modules/platform/gitlab/index', () => { source_branch: 'branch-a', title: 'branch a pr', state: 'open', - description: ``, // equivallent to labels array : ['old_label'] }, ]) .put('/api/v4/projects/undefined/merge_requests/1') From 39d8fe0b2b21d08aba1ea52079d9433106e5b041 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Wed, 8 Nov 2023 18:10:23 +0545 Subject: [PATCH 26/60] update snpas --- .../platform/bitbucket-server/__snapshots__/index.spec.ts.snap | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/modules/platform/bitbucket-server/__snapshots__/index.spec.ts.snap b/lib/modules/platform/bitbucket-server/__snapshots__/index.spec.ts.snap index 6953dafe479665..76d488bcf8bbf9 100644 --- a/lib/modules/platform/bitbucket-server/__snapshots__/index.spec.ts.snap +++ b/lib/modules/platform/bitbucket-server/__snapshots__/index.spec.ts.snap @@ -198,7 +198,6 @@ exports[`modules/platform/bitbucket-server/index endpoint with no path massageMa Empty comment. - Followed by some information. " `; @@ -403,7 +402,6 @@ exports[`modules/platform/bitbucket-server/index endpoint with path massageMarkd Empty comment. - Followed by some information. " `; From 4c5e802c4462e988630224cfe17bd53e32a8763e Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Wed, 8 Nov 2023 21:32:07 +0545 Subject: [PATCH 27/60] refactor params of the new fns --- lib/workers/repository/update/pr/index.ts | 7 +++---- .../repository/update/pr/labels.spec.ts | 6 +++++- lib/workers/repository/update/pr/labels.ts | 19 +++++++++++-------- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index 34637f842a3a30..eb43c3dc879cf8 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -362,7 +362,7 @@ export async function ensurePr( const labelsNeedUpdate = shouldUpdateLabels( labelsFromDebugData, existingPr.labels, - config.labels, + prepareLabels(config), ); if ( existingPr?.targetBranch === config.baseBranch && @@ -492,9 +492,8 @@ export async function ensurePr( if ( err.body?.message === 'Validation failed' && err.body.errors?.length && - err.body.errors.some( - (error: { message?: string }) => - error.message?.startsWith('A pull request already exists'), + err.body.errors.some((error: { message?: string }) => + error.message?.startsWith('A pull request already exists'), ) ) { logger.warn('A pull requests already exists'); diff --git a/lib/workers/repository/update/pr/labels.spec.ts b/lib/workers/repository/update/pr/labels.spec.ts index fd9acddeb5579f..8ca982836b1e9f 100644 --- a/lib/workers/repository/update/pr/labels.spec.ts +++ b/lib/workers/repository/update/pr/labels.spec.ts @@ -107,6 +107,7 @@ describe('workers/repository/update/pr/labels', () => { it('returns false', () => { expect(areLabelsModified(['node', 'npm'], ['node', 'npm'])).toBeFalse(); + expect(areLabelsModified([], [])).toBeTrue(); }); }); @@ -115,7 +116,10 @@ describe('workers/repository/update/pr/labels', () => { expect( shouldUpdateLabels(['npm', 'node'], ['npm', 'node'], ['npm']), ).toBeTrue(); - expect(shouldUpdateLabels(['npm', 'node'], ['npm', 'node'])).toBeTrue(); + expect( + shouldUpdateLabels(['npm', 'node'], ['npm', 'node'], undefined), + ).toBeTrue(); + expect(shouldUpdateLabels([], [], ['npm', 'node'])).toBeTrue(); }); it('returns false if no labels found in debugData', () => { diff --git a/lib/workers/repository/update/pr/labels.ts b/lib/workers/repository/update/pr/labels.ts index 5a1600ed609c88..d0104481a21241 100644 --- a/lib/workers/repository/update/pr/labels.ts +++ b/lib/workers/repository/update/pr/labels.ts @@ -24,10 +24,10 @@ export function getChangedLabels( } export function areLabelsModified( - oldLabels: string[], - newLabels?: string[], + labelsFromDebugData: string[], + labelsInPr: string[], ): boolean { - const modified = !dequal(oldLabels.sort(), newLabels?.sort()); + const modified = !dequal(labelsFromDebugData.sort(), labelsInPr.sort()); if (modified) { logger.debug( @@ -39,19 +39,22 @@ export function areLabelsModified( } export function shouldUpdateLabels( - labelsInDebugData?: string[], - labelsInPr?: string[], - newLabels?: string[], + labelsInDebugData: string[] | undefined, + labelsInPr: string[] | undefined, + newLabels: string[] | undefined, ): boolean { - if (!labelsInDebugData) { + if (!is.array(labelsInDebugData)) { + logger.debug({labelsInDebugData}, 'No labels in PR'); return false; } - if (areLabelsModified(labelsInDebugData, labelsInPr)) { + if (areLabelsModified(labelsInDebugData, labelsInPr ?? [])) { + logger.debug({labelsInDebugData, labelsInPr}, 'Labels in PR have been modified by user'); return false; } if (dequal((newLabels ?? []).sort(), labelsInDebugData.sort())) { + logger.debug({newLabels, existingLabels: labelsInDebugData}, 'New labels and existing labels are same'); return false; } From 3f096762286a8c1374f01393ce006c7632799ef7 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Wed, 8 Nov 2023 22:04:27 +0545 Subject: [PATCH 28/60] fix tests --- lib/workers/repository/update/pr/labels.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/workers/repository/update/pr/labels.spec.ts b/lib/workers/repository/update/pr/labels.spec.ts index 8ca982836b1e9f..7dca6fbc4517ee 100644 --- a/lib/workers/repository/update/pr/labels.spec.ts +++ b/lib/workers/repository/update/pr/labels.spec.ts @@ -107,7 +107,7 @@ describe('workers/repository/update/pr/labels', () => { it('returns false', () => { expect(areLabelsModified(['node', 'npm'], ['node', 'npm'])).toBeFalse(); - expect(areLabelsModified([], [])).toBeTrue(); + expect(areLabelsModified([], [])).toBeFalse(); }); }); From 1e5bee8804e9d314491f7dccea0d0bd8988c5903 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Wed, 8 Nov 2023 22:26:31 +0545 Subject: [PATCH 29/60] fix formatting --- lib/modules/platform/azure/index.spec.ts | 90 +++++++++++----------- lib/modules/platform/azure/index.ts | 6 +- lib/workers/repository/update/pr/index.ts | 5 +- lib/workers/repository/update/pr/labels.ts | 12 ++- 4 files changed, 59 insertions(+), 54 deletions(-) diff --git a/lib/modules/platform/azure/index.spec.ts b/lib/modules/platform/azure/index.spec.ts index 3f4b4a40743e59..1b2e258a71f28c 100644 --- a/lib/modules/platform/azure/index.spec.ts +++ b/lib/modules/platform/azure/index.spec.ts @@ -75,7 +75,7 @@ describe('modules/platform/azure/index', () => { }, }, ]), - } as any), + }) as any, ); return azure.getRepos(); } @@ -229,7 +229,7 @@ describe('modules/platform/azure/index', () => { }, ]), getPullRequestCommits: jest.fn().mockReturnValue([]), - } as any), + }) as any, ); const res = await azure.findPr({ branchName: 'branch-a', @@ -270,7 +270,7 @@ describe('modules/platform/azure/index', () => { }, ]), getPullRequestCommits: jest.fn().mockReturnValue([]), - } as any), + }) as any, ); const res = await azure.findPr({ branchName: 'branch-a', @@ -311,7 +311,7 @@ describe('modules/platform/azure/index', () => { }, ]), getPullRequestCommits: jest.fn().mockReturnValue([]), - } as any), + }) as any, ); const res = await azure.findPr({ branchName: 'branch-a', @@ -352,7 +352,7 @@ describe('modules/platform/azure/index', () => { }, ]), getPullRequestCommits: jest.fn().mockReturnValue([]), - } as any), + }) as any, ); const res = await azure.findPr({ branchName: 'branch-a', @@ -491,7 +491,7 @@ describe('modules/platform/azure/index', () => { () => ({ getPullRequests: jest.fn(() => []), - } as any), + }) as any, ); expect(await azure.getPrList()).toEqual([]); }); @@ -561,7 +561,7 @@ describe('modules/platform/azure/index', () => { context: { genre: 'a-genre', name: 'a-name' }, }, ]), - } as any), + }) as any, ); const res = await azure.getBranchStatusCheck( 'somebranch', @@ -582,7 +582,7 @@ describe('modules/platform/azure/index', () => { context: { genre: 'a-genre', name: 'a-name' }, }, ]), - } as any), + }) as any, ); const res = await azure.getBranchStatusCheck( 'somebranch', @@ -603,7 +603,7 @@ describe('modules/platform/azure/index', () => { context: { genre: 'a-genre', name: 'a-name' }, }, ]), - } as any), + }) as any, ); const res = await azure.getBranchStatusCheck( 'somebranch', @@ -624,7 +624,7 @@ describe('modules/platform/azure/index', () => { context: { genre: 'a-genre', name: 'a-name' }, }, ]), - } as any), + }) as any, ); const res = await azure.getBranchStatusCheck( 'somebranch', @@ -645,7 +645,7 @@ describe('modules/platform/azure/index', () => { context: { genre: 'a-genre', name: 'a-name' }, }, ]), - } as any), + }) as any, ); const res = await azure.getBranchStatusCheck( 'somebranch', @@ -666,7 +666,7 @@ describe('modules/platform/azure/index', () => { context: { genre: 'a-genre', name: 'a-name' }, }, ]), - } as any), + }) as any, ); const res = await azure.getBranchStatusCheck( 'somebranch', @@ -709,7 +709,7 @@ describe('modules/platform/azure/index', () => { context: { genre: 'another-genre', name: 'a-name' }, }, ]), - } as any), + }) as any, ); const res = await azure.getBranchStatusCheck( 'somebranch', @@ -732,7 +732,7 @@ describe('modules/platform/azure/index', () => { context: { genre: 'renovate' }, }, ]), - } as any), + }) as any, ); const res = await azure.getBranchStatus('somebranch', true); expect(res).toBe('green'); @@ -750,7 +750,7 @@ describe('modules/platform/azure/index', () => { context: { genre: 'renovate' }, }, ]), - } as any), + }) as any, ); const res = await azure.getBranchStatus('somebranch', false); expect(res).toBe('yellow'); @@ -763,7 +763,7 @@ describe('modules/platform/azure/index', () => { ({ getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })), getStatuses: jest.fn(() => [{ state: GitStatusState.Error }]), - } as any), + }) as any, ); const res = await azure.getBranchStatus('somebranch', true); expect(res).toBe('red'); @@ -776,7 +776,7 @@ describe('modules/platform/azure/index', () => { ({ getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })), getStatuses: jest.fn(() => [{ state: GitStatusState.Pending }]), - } as any), + }) as any, ); const res = await azure.getBranchStatus('somebranch', true); expect(res).toBe('yellow'); @@ -789,7 +789,7 @@ describe('modules/platform/azure/index', () => { ({ getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })), getStatuses: jest.fn(() => []), - } as any), + }) as any, ); const res = await azure.getBranchStatus('somebranch', true); expect(res).toBe('yellow'); @@ -808,7 +808,7 @@ describe('modules/platform/azure/index', () => { () => ({ getPullRequests: jest.fn(() => []), - } as any), + }) as any, ); const pr = await azure.getPr(1234); expect(pr).toBeNull(); @@ -837,7 +837,7 @@ describe('modules/platform/azure/index', () => { }, }, ]), - } as any), + }) as any, ); const pr = await azure.getPr(1234); expect(pr).toMatchSnapshot(); @@ -854,7 +854,7 @@ describe('modules/platform/azure/index', () => { pullRequestId: 456, })), createPullRequestLabel: jest.fn(() => ({})), - } as any), + }) as any, ); const pr = await azure.createPr({ sourceBranch: 'some-branch', @@ -875,7 +875,7 @@ describe('modules/platform/azure/index', () => { pullRequestId: 456, })), createPullRequestLabel: jest.fn(() => ({})), - } as any), + }) as any, ); const pr = await azure.createPr({ sourceBranch: 'some-branch', @@ -1034,7 +1034,7 @@ describe('modules/platform/azure/index', () => { createPullRequest: jest.fn(() => prResult), createPullRequestLabel: jest.fn(() => ({})), createPullRequestReviewer: updateFn, - } as any), + }) as any, ); const pr = await azure.createPr({ sourceBranch: 'some-branch', @@ -1057,7 +1057,7 @@ describe('modules/platform/azure/index', () => { () => ({ updatePullRequest, - } as any), + }) as any, ); await azure.updatePr({ number: 1234, @@ -1075,7 +1075,7 @@ describe('modules/platform/azure/index', () => { () => ({ updatePullRequest, - } as any), + }) as any, ); await azure.updatePr({ number: 1234, @@ -1091,7 +1091,7 @@ describe('modules/platform/azure/index', () => { () => ({ updatePullRequest, - } as any), + }) as any, ); await azure.updatePr({ number: 1234, @@ -1109,7 +1109,7 @@ describe('modules/platform/azure/index', () => { () => ({ updatePullRequest, - } as any), + }) as any, ); await azure.updatePr({ number: 1234, @@ -1145,7 +1145,7 @@ describe('modules/platform/azure/index', () => { pullRequestId: prResult.pullRequestId, createdBy: prResult.createdBy, })), - } as any), + }) as any, ); const pr = await azure.updatePr({ number: prResult.pullRequestId, @@ -1360,7 +1360,7 @@ describe('modules/platform/azure/index', () => { getRepositories: jest.fn(() => [{ id: '1', project: { id: 2 } }]), createThread: jest.fn(() => [{ id: 123 }]), getThreads: jest.fn(() => []), - } as any), + }) as any, ); azureApi.coreApi.mockImplementation( () => @@ -1372,7 +1372,7 @@ describe('modules/platform/azure/index', () => { getTeamMembersWithExtendedProperties: jest.fn(() => [ { identity: { displayName: 'jyc', uniqueName: 'jyc', id: 123 } }, ]), - } as any), + }) as any, ); await azure.addAssignees(123, ['test@bonjour.fr', 'jyc', 'def']); expect(azureApi.gitApi).toHaveBeenCalledTimes(3); @@ -1387,7 +1387,7 @@ describe('modules/platform/azure/index', () => { ({ getRepositories: jest.fn(() => [{ id: '1', project: { id: 2 } }]), createPullRequestReviewer: jest.fn(), - } as any), + }) as any, ); azureApi.coreApi.mockImplementation( () => @@ -1399,7 +1399,7 @@ describe('modules/platform/azure/index', () => { getTeamMembersWithExtendedProperties: jest.fn(() => [ { identity: { displayName: 'jyc', uniqueName: 'jyc', id: 123 } }, ]), - } as any), + }) as any, ); await azure.addReviewers(123, ['test@bonjour.fr', 'jyc', 'required:def']); expect(azureApi.gitApi).toHaveBeenCalledTimes(3); @@ -1435,7 +1435,7 @@ describe('modules/platform/azure/index', () => { ({ getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })), createCommitStatus: createCommitStatusMock, - } as any), + }) as any, ); await azure.setBranchStatus({ branchName: 'test', @@ -1467,7 +1467,7 @@ describe('modules/platform/azure/index', () => { ({ getBranch: jest.fn(() => ({ commit: { commitId: 'abcd1234' } })), createCommitStatus: createCommitStatusMock, - } as any), + }) as any, ); await azure.setBranchStatus({ branchName: 'test', @@ -1510,7 +1510,7 @@ describe('modules/platform/azure/index', () => { title: 'title', })), updatePullRequest: updatePullRequestMock, - } as any), + }) as any, ); azureHelper.getMergeMethod = jest @@ -1552,7 +1552,7 @@ describe('modules/platform/azure/index', () => { updatePullRequest: jest .fn() .mockRejectedValue(new Error(`oh no pr couldn't be updated`)), - } as any), + }) as any, ); azureHelper.getMergeMethod = jest @@ -1576,7 +1576,7 @@ describe('modules/platform/azure/index', () => { targetRefName: 'refs/heads/ding', })), updatePullRequest: jest.fn(), - } as any), + }) as any, ); azureHelper.getMergeMethod = jest .fn() @@ -1611,7 +1611,7 @@ describe('modules/platform/azure/index', () => { updatePullRequest: jest.fn(() => ({ status: 1, })), - } as any), + }) as any, ); azureHelper.getMergeMethod = jest .fn() @@ -1643,7 +1643,7 @@ describe('modules/platform/azure/index', () => { updatePullRequest: jest.fn(() => ({ status: 1, })), - } as any), + }) as any, ); azureHelper.getMergeMethod = jest .fn() @@ -1667,7 +1667,7 @@ describe('modules/platform/azure/index', () => { () => ({ deletePullRequestLabels: jest.fn(), - } as any), + }) as any, ); await azure.deleteLabel(1234, 'rebase'); expect(azureApi.gitApi.mock.calls).toMatchSnapshot(); @@ -1687,7 +1687,7 @@ describe('modules/platform/azure/index', () => { getItemContent: jest.fn(() => Promise.resolve(Readable.from(JSON.stringify(data))), ), - } as any), + }) as any, ); const res = await azure.getJsonFile('file.json'); expect(res).toEqual(data); @@ -1706,7 +1706,7 @@ describe('modules/platform/azure/index', () => { getItemContent: jest.fn(() => Promise.resolve(Readable.from(json5Data)), ), - } as any), + }) as any, ); const res = await azure.getJsonFile('file.json5'); expect(res).toEqual({ foo: 'bar' }); @@ -1720,7 +1720,7 @@ describe('modules/platform/azure/index', () => { getItemContent: jest.fn(() => Promise.resolve(Readable.from(JSON.stringify(data))), ), - } as any), + }) as any, ); const res = await azure.getJsonFile('file.json', undefined, 'dev'); expect(res).toEqual(data); @@ -1733,7 +1733,7 @@ describe('modules/platform/azure/index', () => { getItemContent: jest.fn(() => Promise.resolve(Readable.from('!@#')), ), - } as any), + }) as any, ); await expect(azure.getJsonFile('file.json')).rejects.toThrow(); }); @@ -1745,7 +1745,7 @@ describe('modules/platform/azure/index', () => { getItemContent: jest.fn(() => { throw new Error('some error'); }), - } as any), + }) as any, ); await expect(azure.getJsonFile('file.json')).rejects.toThrow(); }); diff --git a/lib/modules/platform/azure/index.ts b/lib/modules/platform/azure/index.ts index 874da300b9ff6d..00d1bbba8fdc12 100644 --- a/lib/modules/platform/azure/index.ts +++ b/lib/modules/platform/azure/index.ts @@ -754,10 +754,8 @@ export async function mergePr({ logger.trace( `Updating PR ${pullRequestId} to status ${PullRequestStatus.Completed} (${ PullRequestStatus[PullRequestStatus.Completed] - }) with lastMergeSourceCommit ${ - // TODO: types (#22198) - pr.lastMergeSourceCommit?.commitId - } using mergeStrategy ${mergeStrategy} (${ + }) with lastMergeSourceCommit ${// TODO: types (#22198) + pr.lastMergeSourceCommit?.commitId} using mergeStrategy ${mergeStrategy} (${ GitPullRequestMergeStrategy[mergeStrategy] })`, ); diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index eb43c3dc879cf8..0af1365963ac75 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -492,8 +492,9 @@ export async function ensurePr( if ( err.body?.message === 'Validation failed' && err.body.errors?.length && - err.body.errors.some((error: { message?: string }) => - error.message?.startsWith('A pull request already exists'), + err.body.errors.some( + (error: { message?: string }) => + error.message?.startsWith('A pull request already exists'), ) ) { logger.warn('A pull requests already exists'); diff --git a/lib/workers/repository/update/pr/labels.ts b/lib/workers/repository/update/pr/labels.ts index d0104481a21241..41d92d032b0786 100644 --- a/lib/workers/repository/update/pr/labels.ts +++ b/lib/workers/repository/update/pr/labels.ts @@ -44,17 +44,23 @@ export function shouldUpdateLabels( newLabels: string[] | undefined, ): boolean { if (!is.array(labelsInDebugData)) { - logger.debug({labelsInDebugData}, 'No labels in PR'); + logger.debug({ labelsInDebugData }, 'No labels in PR'); return false; } if (areLabelsModified(labelsInDebugData, labelsInPr ?? [])) { - logger.debug({labelsInDebugData, labelsInPr}, 'Labels in PR have been modified by user'); + logger.debug( + { labelsInDebugData, labelsInPr }, + 'Labels in PR have been modified by user', + ); return false; } if (dequal((newLabels ?? []).sort(), labelsInDebugData.sort())) { - logger.debug({newLabels, existingLabels: labelsInDebugData}, 'New labels and existing labels are same'); + logger.debug( + { newLabels, existingLabels: labelsInDebugData }, + 'New labels and existing labels are same', + ); return false; } From d970eceeccdd776fd0dc8da0d14a02d983f42e20 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Thu, 9 Nov 2023 11:37:59 +0545 Subject: [PATCH 30/60] remove extra logs --- lib/workers/repository/update/pr/labels.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/lib/workers/repository/update/pr/labels.ts b/lib/workers/repository/update/pr/labels.ts index 41d92d032b0786..c553025ed5abbd 100644 --- a/lib/workers/repository/update/pr/labels.ts +++ b/lib/workers/repository/update/pr/labels.ts @@ -30,7 +30,7 @@ export function areLabelsModified( const modified = !dequal(labelsFromDebugData.sort(), labelsInPr.sort()); if (modified) { - logger.debug( + logger.debug( {labelsFromDebugData, labelsInPr}, 'PR labels have been modified by user, skipping labels update', ); } @@ -44,23 +44,14 @@ export function shouldUpdateLabels( newLabels: string[] | undefined, ): boolean { if (!is.array(labelsInDebugData)) { - logger.debug({ labelsInDebugData }, 'No labels in PR'); return false; } if (areLabelsModified(labelsInDebugData, labelsInPr ?? [])) { - logger.debug( - { labelsInDebugData, labelsInPr }, - 'Labels in PR have been modified by user', - ); return false; } if (dequal((newLabels ?? []).sort(), labelsInDebugData.sort())) { - logger.debug( - { newLabels, existingLabels: labelsInDebugData }, - 'New labels and existing labels are same', - ); return false; } From 1c85e92f99e73281ca5a906e65692d195ac2a250 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Thu, 9 Nov 2023 17:47:33 +0545 Subject: [PATCH 31/60] gitea: include labels in getPR result --- lib/modules/platform/gitea/index.ts | 3 +++ lib/modules/platform/gitea/types.ts | 1 + 2 files changed, 4 insertions(+) diff --git a/lib/modules/platform/gitea/index.ts b/lib/modules/platform/gitea/index.ts index 3810caba662614..76cc22b9fdaba8 100644 --- a/lib/modules/platform/gitea/index.ts +++ b/lib/modules/platform/gitea/index.ts @@ -119,7 +119,10 @@ function toRenovatePR(data: PR): Pr | null { isDraft = true; } + const prLabels= data.labels?.map(label => label.name); + return { + labels: prLabels, number: data.number, state: data.state, title, diff --git a/lib/modules/platform/gitea/types.ts b/lib/modules/platform/gitea/types.ts index bc6d78fc8cab8d..c0d0457614d868 100644 --- a/lib/modules/platform/gitea/types.ts +++ b/lib/modules/platform/gitea/types.ts @@ -19,6 +19,7 @@ export interface PR { state: PRState; title: string; body: string; + labels?:Record[], mergeable: boolean; created_at: string; closed_at: string; From fdeb79faf7cac87f39e0cb58500c24fc40619e54 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Thu, 9 Nov 2023 17:52:35 +0545 Subject: [PATCH 32/60] fix formatting --- lib/modules/platform/gitea/index.ts | 2 +- lib/modules/platform/gitea/types.ts | 2 +- lib/workers/repository/update/pr/labels.ts | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/modules/platform/gitea/index.ts b/lib/modules/platform/gitea/index.ts index 76cc22b9fdaba8..fe3272c0250453 100644 --- a/lib/modules/platform/gitea/index.ts +++ b/lib/modules/platform/gitea/index.ts @@ -119,7 +119,7 @@ function toRenovatePR(data: PR): Pr | null { isDraft = true; } - const prLabels= data.labels?.map(label => label.name); + const prLabels = data.labels?.map((label) => label.name); return { labels: prLabels, diff --git a/lib/modules/platform/gitea/types.ts b/lib/modules/platform/gitea/types.ts index c0d0457614d868..9411467079daf2 100644 --- a/lib/modules/platform/gitea/types.ts +++ b/lib/modules/platform/gitea/types.ts @@ -19,7 +19,7 @@ export interface PR { state: PRState; title: string; body: string; - labels?:Record[], + labels?: Record[]; mergeable: boolean; created_at: string; closed_at: string; diff --git a/lib/workers/repository/update/pr/labels.ts b/lib/workers/repository/update/pr/labels.ts index c553025ed5abbd..af9888cdb74b76 100644 --- a/lib/workers/repository/update/pr/labels.ts +++ b/lib/workers/repository/update/pr/labels.ts @@ -30,7 +30,8 @@ export function areLabelsModified( const modified = !dequal(labelsFromDebugData.sort(), labelsInPr.sort()); if (modified) { - logger.debug( {labelsFromDebugData, labelsInPr}, + logger.debug( + { labelsFromDebugData, labelsInPr }, 'PR labels have been modified by user, skipping labels update', ); } From 71a632edbd6eae88f19947283027ccb6ece27d9c Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Thu, 9 Nov 2023 18:03:04 +0545 Subject: [PATCH 33/60] fix tests --- .../gitea/__snapshots__/index.spec.ts.snap | 14 ++++++++++++++ lib/modules/platform/gitea/index.spec.ts | 10 ++++++++++ 2 files changed, 24 insertions(+) diff --git a/lib/modules/platform/gitea/__snapshots__/index.spec.ts.snap b/lib/modules/platform/gitea/__snapshots__/index.spec.ts.snap index c08c86e20b0000..746dd244b7dad6 100644 --- a/lib/modules/platform/gitea/__snapshots__/index.spec.ts.snap +++ b/lib/modules/platform/gitea/__snapshots__/index.spec.ts.snap @@ -9,6 +9,7 @@ exports[`modules/platform/gitea/index createPr should use base branch by default "createdAt": "2014-04-01T05:14:20Z", "hasAssignees": false, "isDraft": false, + "labels": undefined, "number": 42, "sha": "0d9c7726c3d628b7e28af234595cfd20febdbf8e", "sourceBranch": "pr-branch", @@ -28,6 +29,7 @@ exports[`modules/platform/gitea/index createPr should use default branch if requ "createdAt": "2014-04-01T05:14:20Z", "hasAssignees": false, "isDraft": false, + "labels": undefined, "number": 42, "sha": "0d9c7726c3d628b7e28af234595cfd20febdbf8e", "sourceBranch": "pr-branch", @@ -47,6 +49,7 @@ exports[`modules/platform/gitea/index getPr should fallback to direct fetching i "createdAt": "2015-03-22T20:36:16Z", "hasAssignees": false, "isDraft": false, + "labels": undefined, "number": 1, "sha": "some-head-sha", "sourceBranch": "some-head-branch", @@ -66,6 +69,7 @@ exports[`modules/platform/gitea/index getPr should return enriched pull request "createdAt": "2015-03-22T20:36:16Z", "hasAssignees": false, "isDraft": false, + "labels": undefined, "number": 1, "sha": "some-head-sha", "sourceBranch": "some-head-branch", @@ -93,6 +97,7 @@ exports[`modules/platform/gitea/index getPrList should filter list by creator 2` "createdAt": "2015-03-22T20:36:16Z", "hasAssignees": false, "isDraft": false, + "labels": undefined, "number": 1, "sha": "some-head-sha", "sourceBranch": "some-head-branch", @@ -109,6 +114,9 @@ exports[`modules/platform/gitea/index getPrList should filter list by creator 2` "createdAt": "2011-08-18T22:30:38Z", "hasAssignees": false, "isDraft": false, + "labels": [ + "bug", + ], "number": 2, "sha": "other-head-sha", "sourceBranch": "other-head-branch", @@ -125,6 +133,7 @@ exports[`modules/platform/gitea/index getPrList should filter list by creator 2` "createdAt": "2011-08-18T22:30:39Z", "hasAssignees": false, "isDraft": true, + "labels": undefined, "number": 3, "sha": "draft-head-sha", "sourceBranch": "draft-head-branch", @@ -146,6 +155,7 @@ exports[`modules/platform/gitea/index getPrList should return list of pull reque "createdAt": "2015-03-22T20:36:16Z", "hasAssignees": false, "isDraft": false, + "labels": undefined, "number": 1, "sha": "some-head-sha", "sourceBranch": "some-head-branch", @@ -162,6 +172,9 @@ exports[`modules/platform/gitea/index getPrList should return list of pull reque "createdAt": "2011-08-18T22:30:38Z", "hasAssignees": false, "isDraft": false, + "labels": [ + "bug", + ], "number": 2, "sha": "other-head-sha", "sourceBranch": "other-head-branch", @@ -178,6 +191,7 @@ exports[`modules/platform/gitea/index getPrList should return list of pull reque "createdAt": "2011-08-18T22:30:39Z", "hasAssignees": false, "isDraft": true, + "labels": undefined, "number": 3, "sha": "draft-head-sha", "sourceBranch": "draft-head-branch", diff --git a/lib/modules/platform/gitea/index.spec.ts b/lib/modules/platform/gitea/index.spec.ts index 56b27db3882b32..ff278db471c7be 100644 --- a/lib/modules/platform/gitea/index.spec.ts +++ b/lib/modules/platform/gitea/index.spec.ts @@ -112,6 +112,16 @@ describe('modules/platform/gitea/index', () => { sha: 'other-head-sha', repo: partial({ full_name: mockRepo.full_name }), }, + labels: [ + { + color: '00aabb', + description: 'Used to mark PRs that resolve a bug', + exclusive: false, + id: 1, + name: 'bug', + url: 'https://some-url', + }, + ], }), partial({ number: 3, From 2a5aae6326d373b3bac836e2c4bc707170af0fa5 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Thu, 9 Nov 2023 18:28:37 +0545 Subject: [PATCH 34/60] refactor --- lib/modules/platform/bitbucket/index.spec.ts | 1 + .../platform/gitea/gitea-helper.spec.ts | 18 ++++++------------ lib/modules/platform/github/index.spec.ts | 1 - lib/modules/platform/github/index.ts | 2 +- lib/modules/platform/pr-body.ts | 1 + lib/modules/platform/types.ts | 10 ++++++++-- lib/workers/repository/update/pr/index.spec.ts | 7 ++++--- lib/workers/repository/update/pr/index.ts | 7 +++++-- 8 files changed, 26 insertions(+), 21 deletions(-) diff --git a/lib/modules/platform/bitbucket/index.spec.ts b/lib/modules/platform/bitbucket/index.spec.ts index f898638bc1f877..8a6695384d53ef 100644 --- a/lib/modules/platform/bitbucket/index.spec.ts +++ b/lib/modules/platform/bitbucket/index.spec.ts @@ -1371,6 +1371,7 @@ describe('modules/platform/bitbucket/index', () => { '
foo\n
\n\n
text' + '\n---\n\n - [ ] rebase\n' + '\n\n
\n\n
\n
'; + expect(bitbucket.massageMarkdown(prBody)).toMatchSnapshot(); }); }); diff --git a/lib/modules/platform/gitea/gitea-helper.spec.ts b/lib/modules/platform/gitea/gitea-helper.spec.ts index 193aa97870dbc5..4d91061f7a682f 100644 --- a/lib/modules/platform/gitea/gitea-helper.spec.ts +++ b/lib/modules/platform/gitea/gitea-helper.spec.ts @@ -594,12 +594,9 @@ describe('modules/platform/gitea/gitea-helper', () => { ) .reply(200); - const res = await unassignLabel( - mockRepo.full_name, - mockIssue.number, - mockLabel.id, - ); - expect(res).toBeUndefined(); + await expect( + unassignLabel(mockRepo.full_name, mockIssue.number, mockLabel.id), + ).toResolve(); }); }); @@ -610,12 +607,9 @@ describe('modules/platform/gitea/gitea-helper', () => { .patch(`/repos/${mockRepo.full_name}/issues/${mockIssue.number}/labels`) .reply(200); - const res = await assignLabel( - mockRepo.full_name, - mockIssue.number, - mockLabel.id, - ); - expect(res).toBeUndefined(); + await expect( + assignLabel(mockRepo.full_name, mockIssue.number, mockLabel.id), + ).toResolve(); }); }); diff --git a/lib/modules/platform/github/index.spec.ts b/lib/modules/platform/github/index.spec.ts index b6f4b892601478..785025a136ffe6 100644 --- a/lib/modules/platform/github/index.spec.ts +++ b/lib/modules/platform/github/index.spec.ts @@ -3074,7 +3074,6 @@ describe('modules/platform/github/index', () => { state: 'open', title: 'old title', updated_at: '01-09-2022', - body: '', // equivalent to labels array : ['old_label] }) .post('/repos/some/repo/issues/1234/labels') .reply(200, pr) diff --git a/lib/modules/platform/github/index.ts b/lib/modules/platform/github/index.ts index 8c88a142a1adbe..01f3e6933d5790 100644 --- a/lib/modules/platform/github/index.ts +++ b/lib/modules/platform/github/index.ts @@ -1699,7 +1699,7 @@ export async function updatePr({ try { // add and remove labels before updating pr body because if by some mishap - // labels aren't changed then pr body will have wrong labelsHash + // labels aren't changed then pr body will have wrong labels in debugData hash if (labelsToAdd) { await addLabels(prNo, labelsToAdd); } diff --git a/lib/modules/platform/pr-body.ts b/lib/modules/platform/pr-body.ts index cbc41c7099294d..f50d1baa009099 100644 --- a/lib/modules/platform/pr-body.ts +++ b/lib/modules/platform/pr-body.ts @@ -61,6 +61,7 @@ export function getPrBodyStruct( const result: PrBodyStruct = { hash }; const rebaseRequested = isRebaseRequested(body); + if (!is.undefined(rebaseRequested)) { result.rebaseRequested = rebaseRequested; } diff --git a/lib/modules/platform/types.ts b/lib/modules/platform/types.ts index 5fc6af2ce5f073..7dfd31830811f5 100644 --- a/lib/modules/platform/types.ts +++ b/lib/modules/platform/types.ts @@ -120,8 +120,14 @@ export interface UpdatePrConfig { prBody?: string; state?: 'open' | 'closed'; targetBranch?: string; - labels?: string[] | null; // gitea updates labels by replacing the labels array so this is needed - // github, gitlab have specific endpoints to add new or remove old labels + + /** + * three fields for labels might seem confusing but they are needed to handle + * the update of labels on different platforms + * 1. gitea: updates labels by replacing the labels array so this is needed + * 2. github, gitlab: have specific endpoints to add and remove labels + */ + labels?: string[] | null; addLabels?: string[] | null; removeLabels?: string[] | null; } diff --git a/lib/workers/repository/update/pr/index.spec.ts b/lib/workers/repository/update/pr/index.spec.ts index 5344912b84d34d..b1eb80bb751966 100644 --- a/lib/workers/repository/update/pr/index.spec.ts +++ b/lib/workers/repository/update/pr/index.spec.ts @@ -397,9 +397,10 @@ describe('workers/repository/update/pr/index', () => { }, `PR labels have changed`, ); - // expect(logger.logger.debug).toHaveBeenCalledWith( - // 'PR labels have been modified by user, skipping labels update' - // ); + expect(logger.logger.debug).toHaveBeenCalledWith( + { labelsFromDebugData: ['old_label'], labelsInPr: [] }, + 'PR labels have been modified by user, skipping labels update', + ); expect(prCache.setPrCache).toHaveBeenCalled(); }); diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index 0af1365963ac75..5367197bb1d4b0 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -89,8 +89,11 @@ export function updatePrDebugData( targetBranch, }; - // this might seems confusing but we wither want there to be no debugData ie. this is a new PR in creation - // or debugData with labels array ie. pr created with the new update labels logic + /** + * Update the labels field in this struct + * 1. When a new PR is created ie. debugData will be undefined + * 2. When a PR was created using the new update labels logic ie. debugData.labels will be an array + */ if (!debugData || is.array(debugData?.labels)) { updatedPrDebugData.labels = labels; } From f198a6850b0f65e80c938a93c58c91a32ccb10cb Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Sat, 11 Nov 2023 00:48:48 +0545 Subject: [PATCH 35/60] add comments --- lib/modules/platform/gitea/index.ts | 10 +++++++- lib/modules/platform/gitea/types.ts | 5 +++- lib/modules/platform/github/index.ts | 3 +-- lib/modules/platform/gitlab/index.ts | 4 +++ lib/modules/platform/types.ts | 14 ++++++----- lib/workers/repository/update/pr/index.ts | 29 ++++++++++++++-------- lib/workers/repository/update/pr/labels.ts | 22 +++++++++++++++- 7 files changed, 65 insertions(+), 22 deletions(-) diff --git a/lib/modules/platform/gitea/index.ts b/lib/modules/platform/gitea/index.ts index fe3272c0250453..0a7914073bc936 100644 --- a/lib/modules/platform/gitea/index.ts +++ b/lib/modules/platform/gitea/index.ts @@ -119,6 +119,8 @@ function toRenovatePR(data: PR): Pr | null { isDraft = true; } + // from the labels array present in the PR + // create a new array with only the name of the labels to pass further (we do not need the other information) const prLabels = data.labels?.map((label) => label.name); return { @@ -644,7 +646,13 @@ const platform: Platform = { prUpdateParams.base = targetBranch; } - // no need to do extra call for removing labels as gitea API replaces labels array + /** + * Update PR labels. + * In the Gitea API, labels are replaced on each update if the field is present. + * If the field is not present (i.e., undefined), labels aren't updated. + * However, the labels array must contain label IDs instead of names, + * so a lookup is performed to fetch the details (including the ID) of each label. + */ if (Array.isArray(labels)) { prUpdateParams.labels = ( await Promise.all(labels.map(lookupLabelByName)) diff --git a/lib/modules/platform/gitea/types.ts b/lib/modules/platform/gitea/types.ts index 9411467079daf2..3cf565fd723550 100644 --- a/lib/modules/platform/gitea/types.ts +++ b/lib/modules/platform/gitea/types.ts @@ -19,7 +19,6 @@ export interface PR { state: PRState; title: string; body: string; - labels?: Record[]; mergeable: boolean; created_at: string; closed_at: string; @@ -37,6 +36,10 @@ export interface PR { }; assignees?: any[]; user?: { username?: string }; + + // labels returned from the Gitea API are represented as an array of objects + // ref: https://docs.gitea.com/api/1.20/#tag/repository/operation/repoGetPullRequest + labels?: Record[]; } export interface Issue { diff --git a/lib/modules/platform/github/index.ts b/lib/modules/platform/github/index.ts index 01f3e6933d5790..b99e346bc5fbd3 100644 --- a/lib/modules/platform/github/index.ts +++ b/lib/modules/platform/github/index.ts @@ -1697,9 +1697,8 @@ export async function updatePr({ options.token = config.forkToken; } + // Update PR labels try { - // add and remove labels before updating pr body because if by some mishap - // labels aren't changed then pr body will have wrong labels in debugData hash if (labelsToAdd) { await addLabels(prNo, labelsToAdd); } diff --git a/lib/modules/platform/gitlab/index.ts b/lib/modules/platform/gitlab/index.ts index 524c98592b3198..cd33f61adbcd93 100644 --- a/lib/modules/platform/gitlab/index.ts +++ b/lib/modules/platform/gitlab/index.ts @@ -780,9 +780,13 @@ export async function updatePr({ if (targetBranch) { body.target_branch = targetBranch; } + + // Add new labels to the PR if (addLabels) { body.add_labels = addLabels; } + + // Remove old labels from the PR if (removeLabels) { body.remove_labels = removeLabels; } diff --git a/lib/modules/platform/types.ts b/lib/modules/platform/types.ts index 7dfd31830811f5..99f65d298176cc 100644 --- a/lib/modules/platform/types.ts +++ b/lib/modules/platform/types.ts @@ -121,13 +121,15 @@ export interface UpdatePrConfig { state?: 'open' | 'closed'; targetBranch?: string; - /** - * three fields for labels might seem confusing but they are needed to handle - * the update of labels on different platforms - * 1. gitea: updates labels by replacing the labels array so this is needed - * 2. github, gitlab: have specific endpoints to add and remove labels - */ + // The use of three fields for labels may appear confusing, + // but it's necessary to accommodate the different methods of + // updating labels on various platforms. + + // For Gitea, labels are updated by replacing the entire labels array. labels?: string[] | null; + + // In the case of GitHub and GitLab, specific endpoints exist + // for adding and removing labels. addLabels?: string[] | null; removeLabels?: string[] | null; } diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index 5367197bb1d4b0..eaa8d89124c8d9 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -89,11 +89,10 @@ export function updatePrDebugData( targetBranch, }; - /** - * Update the labels field in this struct - * 1. When a new PR is created ie. debugData will be undefined - * 2. When a PR was created using the new update labels logic ie. debugData.labels will be an array - */ + // Add labels to the debug data object. + // When to add: + // 1. Add it when a new PR is created, i.e., when debugData is undefined. + // 2. Add it if an existing PR already has labels in the debug data, confirming that we can update its labels. if (!debugData || is.array(debugData?.labels)) { updatedPrDebugData.labels = labels; } @@ -335,7 +334,7 @@ export async function ensurePr( { debugData: updatePrDebugData( config.baseBranch, - prepareLabels(config).sort(), + prepareLabels(config).sort(), // include labels in debug data, sort them just to be safe existingPr?.bodyStruct?.debugData, ), }, @@ -361,12 +360,14 @@ export async function ensurePr( const existingPrBodyHash = existingPr.bodyStruct?.hash; const newPrTitle = stripEmojis(prTitle); const newPrBodyHash = hashBody(prBody); + const labelsFromDebugData = existingPr.bodyStruct?.debugData?.labels; const labelsNeedUpdate = shouldUpdateLabels( labelsFromDebugData, existingPr.labels, prepareLabels(config), ); + if ( existingPr?.targetBranch === config.baseBranch && existingPrTitle === newPrTitle && @@ -399,9 +400,7 @@ export async function ensurePr( ); updatePrConfig.targetBranch = config.baseBranch; } - // divide labels into two categories: i) which needs to be added and ii) which needs to be removed - // Note: existing labels aren't present in these two categories - // this is necessary because some platforms handle these two categories separately + if (labelsNeedUpdate) { const newLabels = prepareLabels(config); logger.debug( @@ -412,15 +411,23 @@ export async function ensurePr( }, 'PR labels have changed', ); + + // Divide labels into three categories: + // i) addLabels: Labels that need to be added + // ii) removeLabels: Labels that need to be removed + // iii) labels: New labels for the PR, replacing the old labels array entirely. + // This distinction is necessary because different platforms update labels differently + // For more details, refer to the updatePr function of each platform + const [addLabels, removeLabels] = getChangedLabels( labelsFromDebugData!, newLabels, ); - // for gitea + // for Gitea updatePrConfig.labels = newLabels; - // for github, gitlab + // for Github, Gitlab updatePrConfig.addLabels = addLabels; updatePrConfig.removeLabels = removeLabels; } diff --git a/lib/workers/repository/update/pr/labels.ts b/lib/workers/repository/update/pr/labels.ts index af9888cdb74b76..191ad6f5b0e7fa 100644 --- a/lib/workers/repository/update/pr/labels.ts +++ b/lib/workers/repository/update/pr/labels.ts @@ -13,16 +13,28 @@ export function prepareLabels(config: RenovateConfig): string[] { .filter(is.nonEmptyStringAndNotWhitespace); } +/** + * Determine changed labels between old and new label arrays. + * + * This function takes two arrays of labels, 'oldLabels' and 'newLabels', and calculates the labels + * that need to be added and removed to transition from 'oldLabels' to 'newLabels'. + */ export function getChangedLabels( oldLabels: string[], newLabels: string[], -): [string[] | null, string[] | null] { +): Array { const labelsToAdd = newLabels?.filter((l) => !oldLabels?.includes(l)); const labelsToRemove = oldLabels?.filter((l) => !newLabels?.includes(l)); return [labelsToAdd, labelsToRemove]; } +/** + * Check if labels in the PR have been modified. + * + * This function compares two arrays of labels, 'labelsFromDebugData' and 'labelsInPr', + * to determine if they are different, indicating that labels in the PR have been modified. + */ export function areLabelsModified( labelsFromDebugData: string[], labelsInPr: string[], @@ -39,19 +51,27 @@ export function areLabelsModified( return modified; } +/** + * Determine if labels should be updated in the Pull Request + */ export function shouldUpdateLabels( labelsInDebugData: string[] | undefined, labelsInPr: string[] | undefined, newLabels: string[] | undefined, ): boolean { + // If the 'labelsInDebugData' field is undefined + // it means the PR was created before the update-labels logic was merged, and labels should not be updated. + // Reference: https://github.com/renovatebot/renovate/pull/25340 if (!is.array(labelsInDebugData)) { return false; } + // If the labels in the PR have been modified by the user, they should not be updated. if (areLabelsModified(labelsInDebugData, labelsInPr ?? [])) { return false; } + // If the 'labels are unchanged, they should not be updated. if (dequal((newLabels ?? []).sort(), labelsInDebugData.sort())) { return false; } From dacdb5daabbe22edf6f1a17b1927d9ac5ae1e74b Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Sat, 11 Nov 2023 00:49:18 +0545 Subject: [PATCH 36/60] Update docs/usage/configuration-options.md Co-authored-by: Rhys Arkins --- docs/usage/configuration-options.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 6097d84096542e..0bf33e1d2331cb 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -2039,17 +2039,13 @@ With the above config, every PR raised by Renovate will have the label `dependen Behaviour details: -- Renovate creates PRs with the currently configured/applicable labels -- If you add or remove labels in a PR which Renovate created, it won't touch labels again in that open PR -- If you change your config, the new/changed labels are applied to any open PRs +- Renovate creates PRs with labels, if they are configured +- If any other bot or users modifies labels in a PR which Renovate created, it won't touch labels again in that open PR +- If the labels for a PR change through configuration or other means, they are applied to any open PRs with unmodified labels (GitHub, GitLab, and Gitea only) The `labels` array is non-mergeable, meaning if multiple `packageRules` match then Renovate uses the last value for `labels`. If you want to add/combine labels, use the `addLabels` config option, which is mergeable. - -!!! note - Currently updating of the labels on open PRs is only supported for the platforms: github, gitlab and gitea - ## lockFileMaintenance You can use `lockFileMaintenance` to refresh lock files to keep them up-to-date. From 0dca273b0109335cc27e0d9d58a5091e6647d755 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Sat, 11 Nov 2023 20:35:41 +0545 Subject: [PATCH 37/60] Apply suggestions from code review Co-authored-by: Rhys Arkins --- docs/usage/configuration-options.md | 2 +- lib/workers/repository/update/pr/index.ts | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 0bf33e1d2331cb..e89033b74cd213 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -2039,7 +2039,7 @@ With the above config, every PR raised by Renovate will have the label `dependen Behaviour details: -- Renovate creates PRs with labels, if they are configured +- Renovate adds labels to the PR at time of PR creation, if any have been configured - If any other bot or users modifies labels in a PR which Renovate created, it won't touch labels again in that open PR - If the labels for a PR change through configuration or other means, they are applied to any open PRs with unmodified labels (GitHub, GitLab, and Gitea only) diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index eaa8d89124c8d9..c63755b1a82953 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -344,6 +344,7 @@ export async function ensurePr( try { if (existingPr) { logger.debug('Processing existing PR'); + if ( !existingPr.hasAssignees && !hasNotIgnoredReviewers(existingPr, config) && @@ -354,18 +355,20 @@ export async function ensurePr( logger.debug(`Setting assignees and reviewers as status checks failed`); await addParticipants(config, existingPr); } - // Check if existing PR needs updating const existingPrTitle = stripEmojis(existingPr.title); const existingPrBodyHash = existingPr.bodyStruct?.hash; const newPrTitle = stripEmojis(prTitle); const newPrBodyHash = hashBody(prBody); - const labelsFromDebugData = existingPr.bodyStruct?.debugData?.labels; + const prInitialLabels = existingPr.bodyStruct?.debugData?.labels; + const prCurrentLabels = existingPr.labels; + const configuredLabels = prepareLabels(config); + const labelsNeedUpdate = shouldUpdateLabels( - labelsFromDebugData, - existingPr.labels, - prepareLabels(config), + prInitialLabels, + prCurrentLabels, + configuredLabels, ); if ( @@ -406,8 +409,8 @@ export async function ensurePr( logger.debug( { branchName, - oldLabels: labelsFromDebugData, - newLabels, + prCurrentLabels, + configuredLabels, }, 'PR labels have changed', ); @@ -420,12 +423,12 @@ export async function ensurePr( // For more details, refer to the updatePr function of each platform const [addLabels, removeLabels] = getChangedLabels( - labelsFromDebugData!, - newLabels, + prCurrentLabels, + configuredLabels, ); // for Gitea - updatePrConfig.labels = newLabels; + updatePrConfig.labels = configuredLabels; // for Github, Gitlab updatePrConfig.addLabels = addLabels; From 15ec73a2e84909f6d14734dde8d1b44e088c57e7 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Sat, 11 Nov 2023 23:30:09 +0545 Subject: [PATCH 38/60] fix lint issues --- .../repository/update/pr/index.spec.ts | 8 +++---- lib/workers/repository/update/pr/index.ts | 3 +-- lib/workers/repository/update/pr/labels.ts | 22 +++++++++---------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/lib/workers/repository/update/pr/index.spec.ts b/lib/workers/repository/update/pr/index.spec.ts index b1eb80bb751966..ae2163b0731f0f 100644 --- a/lib/workers/repository/update/pr/index.spec.ts +++ b/lib/workers/repository/update/pr/index.spec.ts @@ -316,8 +316,8 @@ describe('workers/repository/update/pr/index', () => { expect(logger.logger.debug).toHaveBeenCalledWith( { branchName: 'renovate-branch', - oldLabels: ['old_label'], - newLabels: ['new_label'], + prCurrentLabels: ['old_label'], + configuredLabels: ['new_label'], }, `PR labels have changed`, ); @@ -392,8 +392,8 @@ describe('workers/repository/update/pr/index', () => { expect(logger.logger.debug).not.toHaveBeenCalledWith( { branchName: 'renovate-branch', - oldLabels: ['old_label'], - newLabels: ['new_label'], + prCurrentLabels: ['old_label'], + configuredLabels: ['new_label'], }, `PR labels have changed`, ); diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index c63755b1a82953..3ebe77fd362922 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -405,7 +405,6 @@ export async function ensurePr( } if (labelsNeedUpdate) { - const newLabels = prepareLabels(config); logger.debug( { branchName, @@ -423,7 +422,7 @@ export async function ensurePr( // For more details, refer to the updatePr function of each platform const [addLabels, removeLabels] = getChangedLabels( - prCurrentLabels, + prCurrentLabels!, configuredLabels, ); diff --git a/lib/workers/repository/update/pr/labels.ts b/lib/workers/repository/update/pr/labels.ts index 191ad6f5b0e7fa..f650b9d936d185 100644 --- a/lib/workers/repository/update/pr/labels.ts +++ b/lib/workers/repository/update/pr/labels.ts @@ -32,18 +32,18 @@ export function getChangedLabels( /** * Check if labels in the PR have been modified. * - * This function compares two arrays of labels, 'labelsFromDebugData' and 'labelsInPr', + * This function compares two arrays of labels, 'prInitialLabels' and 'prCurrentLabels', * to determine if they are different, indicating that labels in the PR have been modified. */ export function areLabelsModified( - labelsFromDebugData: string[], - labelsInPr: string[], + prInitialLabels: string[], + prCurrentLabels: string[], ): boolean { - const modified = !dequal(labelsFromDebugData.sort(), labelsInPr.sort()); + const modified = !dequal(prInitialLabels.sort(), prCurrentLabels.sort()); if (modified) { logger.debug( - { labelsFromDebugData, labelsInPr }, + { prInitialLabels, prCurrentLabels }, 'PR labels have been modified by user, skipping labels update', ); } @@ -55,24 +55,24 @@ export function areLabelsModified( * Determine if labels should be updated in the Pull Request */ export function shouldUpdateLabels( - labelsInDebugData: string[] | undefined, - labelsInPr: string[] | undefined, - newLabels: string[] | undefined, + prInitialLabels: string[] | undefined, + prCurrentLabels: string[] | undefined, + configuredLabels: string[] | undefined, ): boolean { // If the 'labelsInDebugData' field is undefined // it means the PR was created before the update-labels logic was merged, and labels should not be updated. // Reference: https://github.com/renovatebot/renovate/pull/25340 - if (!is.array(labelsInDebugData)) { + if (!is.array(prInitialLabels)) { return false; } // If the labels in the PR have been modified by the user, they should not be updated. - if (areLabelsModified(labelsInDebugData, labelsInPr ?? [])) { + if (areLabelsModified(prInitialLabels, prCurrentLabels ?? [])) { return false; } // If the 'labels are unchanged, they should not be updated. - if (dequal((newLabels ?? []).sort(), labelsInDebugData.sort())) { + if (dequal((configuredLabels ?? []).sort(), prInitialLabels.sort())) { return false; } From c39e4e4f351d4eb68e0047dcc10d41ace847fb2a Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Sun, 12 Nov 2023 00:06:13 +0545 Subject: [PATCH 39/60] fix test --- lib/workers/repository/update/pr/index.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/workers/repository/update/pr/index.spec.ts b/lib/workers/repository/update/pr/index.spec.ts index ae2163b0731f0f..5d4d23f281c3b8 100644 --- a/lib/workers/repository/update/pr/index.spec.ts +++ b/lib/workers/repository/update/pr/index.spec.ts @@ -398,7 +398,7 @@ describe('workers/repository/update/pr/index', () => { `PR labels have changed`, ); expect(logger.logger.debug).toHaveBeenCalledWith( - { labelsFromDebugData: ['old_label'], labelsInPr: [] }, + { prInitialLabels: ['old_label'], prCurrentLabels: [] }, 'PR labels have been modified by user, skipping labels update', ); expect(prCache.setPrCache).toHaveBeenCalled(); From bcc173b47de1940709e707bbed5f7cca7d7840de Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Mon, 13 Nov 2023 18:10:10 +0545 Subject: [PATCH 40/60] Apply Suggestion --- .../platform/gitea/gitea-helper.spec.ts | 14 ----------- lib/modules/platform/gitea/gitea-helper.ts | 15 ------------ lib/modules/platform/gitea/index.ts | 2 +- lib/modules/platform/gitea/types.ts | 10 +++++++- lib/modules/platform/types.ts | 24 +++++++++++++------ .../repository/update/pr/index.spec.ts | 3 --- lib/workers/repository/update/pr/index.ts | 2 +- 7 files changed, 28 insertions(+), 42 deletions(-) diff --git a/lib/modules/platform/gitea/gitea-helper.spec.ts b/lib/modules/platform/gitea/gitea-helper.spec.ts index 4d91061f7a682f..9be5a2ad18afe7 100644 --- a/lib/modules/platform/gitea/gitea-helper.spec.ts +++ b/lib/modules/platform/gitea/gitea-helper.spec.ts @@ -2,7 +2,6 @@ import * as httpMock from '../../../../test/http-mock'; import { setBaseUrl } from '../../../util/http/gitea'; import { toBase64 } from '../../../util/string'; import { - assignLabel, closeIssue, closePR, createComment, @@ -600,19 +599,6 @@ describe('modules/platform/gitea/gitea-helper', () => { }); }); - describe('assignLabel', () => { - it('should call /api/v1/repos/[repo]/issues/[issue]/labels endpoint', async () => { - httpMock - .scope(baseUrl) - .patch(`/repos/${mockRepo.full_name}/issues/${mockIssue.number}/labels`) - .reply(200); - - await expect( - assignLabel(mockRepo.full_name, mockIssue.number, mockLabel.id), - ).toResolve(); - }); - }); - describe('createComment', () => { it('should call /api/v1/repos/[repo]/issues/[issue]/comments endpoint', async () => { httpMock diff --git a/lib/modules/platform/gitea/gitea-helper.ts b/lib/modules/platform/gitea/gitea-helper.ts index d43dc5c45bda6e..7dbc6594a5dc90 100644 --- a/lib/modules/platform/gitea/gitea-helper.ts +++ b/lib/modules/platform/gitea/gitea-helper.ts @@ -306,21 +306,6 @@ export async function unassignLabel( await giteaHttp.deleteJson(url, options); } -export async function assignLabel( - repoPath: string, - issue: number, - label: number, - options?: GiteaHttpOptions, -): Promise { - const url = `${API_PATH}/repos/${repoPath}/issues/${issue}/labels`; - await giteaHttp.patchJson(url, { - ...options, - body: { - labels: [label], - }, - }); -} - export async function createComment( repoPath: string, issue: number, diff --git a/lib/modules/platform/gitea/index.ts b/lib/modules/platform/gitea/index.ts index 0a7914073bc936..e2e04520363a27 100644 --- a/lib/modules/platform/gitea/index.ts +++ b/lib/modules/platform/gitea/index.ts @@ -121,7 +121,7 @@ function toRenovatePR(data: PR): Pr | null { // from the labels array present in the PR // create a new array with only the name of the labels to pass further (we do not need the other information) - const prLabels = data.labels?.map((label) => label.name); + const prLabels = data.labels?.map((label) => label.name).filter(is.string); return { labels: prLabels, diff --git a/lib/modules/platform/gitea/types.ts b/lib/modules/platform/gitea/types.ts index 3cf565fd723550..fb29dababb884c 100644 --- a/lib/modules/platform/gitea/types.ts +++ b/lib/modules/platform/gitea/types.ts @@ -14,6 +14,14 @@ export type CommitStatusType = | 'unknown'; export type PRMergeMethod = 'merge' | 'rebase' | 'rebase-merge' | 'squash'; +export interface GiteaLabel { + color: string; + description: string; + exclusive: boolean; + id: number; + name: string; + url: string; +} export interface PR { number: number; state: PRState; @@ -39,7 +47,7 @@ export interface PR { // labels returned from the Gitea API are represented as an array of objects // ref: https://docs.gitea.com/api/1.20/#tag/repository/operation/repoGetPullRequest - labels?: Record[]; + labels?: GiteaLabel[]; } export interface Issue { diff --git a/lib/modules/platform/types.ts b/lib/modules/platform/types.ts index 99f65d298176cc..750914a8e56692 100644 --- a/lib/modules/platform/types.ts +++ b/lib/modules/platform/types.ts @@ -121,16 +121,26 @@ export interface UpdatePrConfig { state?: 'open' | 'closed'; targetBranch?: string; - // The use of three fields for labels may appear confusing, - // but it's necessary to accommodate the different methods of - // updating labels on various platforms. - - // For Gitea, labels are updated by replacing the entire labels array. + /** + * This field allows for label management and is designed to + * accommodate the different label update methods on various platforms. + * + * - For Gitea, labels are updated by replacing the entire labels array. + * - In the case of GitHub and GitLab, specific endpoints exist + * for adding and removing labels. + */ labels?: string[] | null; - // In the case of GitHub and GitLab, specific endpoints exist - // for adding and removing labels. + /** + * Specifies an array of labels to be added. + * @see {@link labels} + */ addLabels?: string[] | null; + + /** + * Specifies an array of labels to be removed. + * @see {@link labels} + */ removeLabels?: string[] | null; } export interface EnsureIssueConfig { diff --git a/lib/workers/repository/update/pr/index.spec.ts b/lib/workers/repository/update/pr/index.spec.ts index 5d4d23f281c3b8..257fd2dc4daafc 100644 --- a/lib/workers/repository/update/pr/index.spec.ts +++ b/lib/workers/repository/update/pr/index.spec.ts @@ -270,7 +270,6 @@ describe('workers/repository/update/pr/index', () => { }); describe('Update', () => { - // updates labels it('updates PR if labels have changed in config', async () => { const prDebugData = { createdInVer: '1.0.0', @@ -324,7 +323,6 @@ describe('workers/repository/update/pr/index', () => { expect(prCache.setPrCache).toHaveBeenCalled(); }); - // skips updating labels if existing pr doesn't have labels in debugData it('skips pr update if existing pr does not have labels in debugData', async () => { const existingPr: Pr = { ...pr, @@ -352,7 +350,6 @@ describe('workers/repository/update/pr/index', () => { expect(prCache.setPrCache).toHaveBeenCalled(); }); - // skip updating labels if pr labels have been modified by user it('skips pr update if pr labels have been modified by user', async () => { const prDebugData = { createdInVer: '1.0.0', diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index 3ebe77fd362922..77b530de7730d1 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -93,7 +93,7 @@ export function updatePrDebugData( // When to add: // 1. Add it when a new PR is created, i.e., when debugData is undefined. // 2. Add it if an existing PR already has labels in the debug data, confirming that we can update its labels. - if (!debugData || is.array(debugData?.labels)) { + if (!debugData || is.array(debugData.labels)) { updatedPrDebugData.labels = labels; } From c2156be98bcf0bc0942b7a96c94139476325da39 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Tue, 14 Nov 2023 11:08:16 +0545 Subject: [PATCH 41/60] apply suggestions --- lib/modules/platform/gitea/index.spec.ts | 4 ---- lib/modules/platform/gitea/types.ts | 4 ---- lib/workers/repository/update/pr/labels.ts | 2 +- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/modules/platform/gitea/index.spec.ts b/lib/modules/platform/gitea/index.spec.ts index ff278db471c7be..c0da7eb0a71b6f 100644 --- a/lib/modules/platform/gitea/index.spec.ts +++ b/lib/modules/platform/gitea/index.spec.ts @@ -114,12 +114,8 @@ describe('modules/platform/gitea/index', () => { }, labels: [ { - color: '00aabb', - description: 'Used to mark PRs that resolve a bug', - exclusive: false, id: 1, name: 'bug', - url: 'https://some-url', }, ], }), diff --git a/lib/modules/platform/gitea/types.ts b/lib/modules/platform/gitea/types.ts index fb29dababb884c..0c20ecfcc3c1f8 100644 --- a/lib/modules/platform/gitea/types.ts +++ b/lib/modules/platform/gitea/types.ts @@ -15,12 +15,8 @@ export type CommitStatusType = export type PRMergeMethod = 'merge' | 'rebase' | 'rebase-merge' | 'squash'; export interface GiteaLabel { - color: string; - description: string; - exclusive: boolean; id: number; name: string; - url: string; } export interface PR { number: number; diff --git a/lib/workers/repository/update/pr/labels.ts b/lib/workers/repository/update/pr/labels.ts index f650b9d936d185..a5ab52e5753731 100644 --- a/lib/workers/repository/update/pr/labels.ts +++ b/lib/workers/repository/update/pr/labels.ts @@ -22,7 +22,7 @@ export function prepareLabels(config: RenovateConfig): string[] { export function getChangedLabels( oldLabels: string[], newLabels: string[], -): Array { +): [string[] | undefined, string[] | undefined] { const labelsToAdd = newLabels?.filter((l) => !oldLabels?.includes(l)); const labelsToRemove = oldLabels?.filter((l) => !newLabels?.includes(l)); From b7aebff4d43c8fae209abdfb1bfb74926150df3b Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Wed, 15 Nov 2023 11:39:07 +0545 Subject: [PATCH 42/60] Update lib/workers/repository/update/pr/labels.ts Co-authored-by: Michael Kriese --- lib/workers/repository/update/pr/labels.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/workers/repository/update/pr/labels.ts b/lib/workers/repository/update/pr/labels.ts index a5ab52e5753731..a0947f94b82d11 100644 --- a/lib/workers/repository/update/pr/labels.ts +++ b/lib/workers/repository/update/pr/labels.ts @@ -20,8 +20,8 @@ export function prepareLabels(config: RenovateConfig): string[] { * that need to be added and removed to transition from 'oldLabels' to 'newLabels'. */ export function getChangedLabels( - oldLabels: string[], - newLabels: string[], + oldLabels: string[] | undefined, + newLabels: string[] | undefined, ): [string[] | undefined, string[] | undefined] { const labelsToAdd = newLabels?.filter((l) => !oldLabels?.includes(l)); const labelsToRemove = oldLabels?.filter((l) => !newLabels?.includes(l)); From 682469a92ba95bb3dd6f5d1045a670ad21ba67e1 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Wed, 15 Nov 2023 11:46:47 +0545 Subject: [PATCH 43/60] remove non-null assertion --- lib/workers/repository/update/pr/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index 77b530de7730d1..4aaa02d387953f 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -422,7 +422,7 @@ export async function ensurePr( // For more details, refer to the updatePr function of each platform const [addLabels, removeLabels] = getChangedLabels( - prCurrentLabels!, + prCurrentLabels, configuredLabels, ); From 1ec080fa3ba5f6c38105f10e87b3080727f38c76 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Wed, 24 Jan 2024 19:44:25 +0545 Subject: [PATCH 44/60] fix gitea tests --- lib/modules/platform/gitea/index.spec.ts | 77 ++++++++++-------------- lib/modules/platform/gitea/index.ts | 26 +++++++- lib/modules/platform/gitea/utils.ts | 2 + 3 files changed, 57 insertions(+), 48 deletions(-) diff --git a/lib/modules/platform/gitea/index.spec.ts b/lib/modules/platform/gitea/index.spec.ts index aa5b7b3188ded7..8f18c7f94c7f9d 100644 --- a/lib/modules/platform/gitea/index.spec.ts +++ b/lib/modules/platform/gitea/index.spec.ts @@ -1837,56 +1837,43 @@ describe('modules/platform/gitea/index', () => { ).toResolve(); }); - it('should add new labels', async () => { - helper.getRepoLabels.mockResolvedValueOnce([ - { id: 1, name: 'old_label', description: 'its a me', color: '#000000' }, - { - id: 2, - name: 'new_label', - description: 'labelario', - color: '#ffffff', - }, - ]); - helper.getOrgLabels.mockResolvedValueOnce([]); - helper.searchPRs.mockResolvedValueOnce(mockPRs); - await initFakeRepo(); - await gitea.updatePr({ + it('should update labels', async () => { + const updatedMockPR = partial({ + ...mockPRs[0], number: 1, - prTitle: 'New Title', - prBody: 'New Body', - state: 'closed', - labels: ['new_label'], - }); - - expect(helper.updatePR).toHaveBeenCalledWith(mockRepo.full_name, 1, { title: 'New Title', body: 'New Body', - state: 'closed', - labels: [2], - }); - }); - - it('should remove old labels', async () => { - helper.getRepoLabels.mockResolvedValueOnce([ - { id: 1, name: 'old_label', description: 'its a me', color: '#000000' }, - ]); - helper.getOrgLabels.mockResolvedValueOnce([]); - helper.searchPRs.mockResolvedValueOnce(mockPRs); - await initFakeRepo(); - await gitea.updatePr({ - number: 1, - prTitle: 'New Title', - prBody: 'New Body', - state: 'closed', - labels: [], + state: 'open', + labels: [ + { + id: 1, + name: 'some-label', + }, + ], }); + const scope = httpMock + .scope('https://gitea.com/api/v1') + .get('/repos/some/repo/pulls') + .query({ state: 'all', sort: 'recentupdate' }) + .reply(200, mockPRs) + .get('/repos/some/repo/labels') + .reply(200, mockRepoLabels) + .get('/orgs/some/labels') + .reply(200, mockOrgLabels) + .patch('/repos/some/repo/pulls/1') + .reply(200, updatedMockPR); - expect(helper.updatePR).toHaveBeenCalledWith(mockRepo.full_name, 1, { - title: 'New Title', - body: 'New Body', - state: 'closed', - labels: [], - }); + await initFakePlatform(scope); + await initFakeRepo(scope); + await expect( + gitea.updatePr({ + number: 1, + prTitle: 'New Title', + prBody: 'New Body', + state: 'open', + labels: ['some-label'], + }), + ).toResolve(); }); }); diff --git a/lib/modules/platform/gitea/index.ts b/lib/modules/platform/gitea/index.ts index 0f5ff0d53a0192..a8d61fdb6f89e0 100644 --- a/lib/modules/platform/gitea/index.ts +++ b/lib/modules/platform/gitea/index.ts @@ -588,8 +588,7 @@ const platform: Platform = { targetBranch, }: UpdatePrConfig): Promise { let title = prTitle; - const pr = (await getPrList()).find((pr) => pr.number === number); - if (pr?.isDraft) { + if ((await getPrList()).find((pr) => pr.number === number)?.isDraft) { title = DRAFT_PREFIX + title; } @@ -602,7 +601,28 @@ const platform: Platform = { prUpdateParams.base = targetBranch; } - await helper.updatePR(config.repository, number, prUpdateParams); + /** + * Update PR labels. + * In the Gitea API, labels are replaced on each update if the field is present. + * If the field is not present (i.e., undefined), labels aren't updated. + * However, the labels array must contain label IDs instead of names, + * so a lookup is performed to fetch the details (including the ID) of each label. + */ + if (Array.isArray(labels)) { + prUpdateParams.labels = ( + await Promise.all(labels.map(lookupLabelByName)) + ).filter(is.number); + } + + const gpr = await helper.updatePR( + config.repository, + number, + prUpdateParams, + ); + const pr = toRenovatePR(gpr, botUserName); + if (pr) { + await GiteaPrCache.addPr(giteaHttp, config.repository, botUserName, pr); + } }, async mergePr({ id, strategy }: MergePRConfig): Promise { diff --git a/lib/modules/platform/gitea/utils.ts b/lib/modules/platform/gitea/utils.ts index d4e5bd5bb32919..b29411e6585c43 100644 --- a/lib/modules/platform/gitea/utils.ts +++ b/lib/modules/platform/gitea/utils.ts @@ -119,8 +119,10 @@ export function toRenovatePR(data: PR, author: string | null): Pr | null { title = title.substring(DRAFT_PREFIX.length); isDraft = true; } + const labels = (data?.labels ?? []).map((l) => l.name); return { + labels, number: data.number, state: data.state, title, From 319805325afa016fa743aaf3a1cdcaa058bff8bb Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Thu, 25 Jan 2024 01:52:39 +0545 Subject: [PATCH 45/60] use pmap --- lib/modules/platform/gitea/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/modules/platform/gitea/index.ts b/lib/modules/platform/gitea/index.ts index a8d61fdb6f89e0..756779e20f2365 100644 --- a/lib/modules/platform/gitea/index.ts +++ b/lib/modules/platform/gitea/index.ts @@ -490,7 +490,7 @@ const platform: Platform = { logger.debug(`Creating pull request: ${title} (${head} => ${base})`); try { const labels = Array.isArray(labelNames) - ? await Promise.all(labelNames.map(lookupLabelByName)) + ? await map(labelNames, lookupLabelByName) : []; const gpr = await helper.createPR(config.repository, { base, From d8aa7ad09100d1c2abce24f1024c5150dbb7d7c1 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Tue, 30 Jan 2024 16:15:19 +0545 Subject: [PATCH 46/60] Update lib/modules/platform/gitea/index.ts Co-authored-by: Michael Kriese --- lib/modules/platform/gitea/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/modules/platform/gitea/index.ts b/lib/modules/platform/gitea/index.ts index 756779e20f2365..e8a3807fc9ef9d 100644 --- a/lib/modules/platform/gitea/index.ts +++ b/lib/modules/platform/gitea/index.ts @@ -610,7 +610,7 @@ const platform: Platform = { */ if (Array.isArray(labels)) { prUpdateParams.labels = ( - await Promise.all(labels.map(lookupLabelByName)) + await map(labels, lookupLabelByName) ).filter(is.number); } From ad91fbf78648b3e12d956e3b32d8834812e564b9 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Tue, 30 Jan 2024 18:07:51 +0545 Subject: [PATCH 47/60] fix formatting --- lib/modules/platform/gitea/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/modules/platform/gitea/index.ts b/lib/modules/platform/gitea/index.ts index e8a3807fc9ef9d..fe85af0e4b7769 100644 --- a/lib/modules/platform/gitea/index.ts +++ b/lib/modules/platform/gitea/index.ts @@ -609,9 +609,9 @@ const platform: Platform = { * so a lookup is performed to fetch the details (including the ID) of each label. */ if (Array.isArray(labels)) { - prUpdateParams.labels = ( - await map(labels, lookupLabelByName) - ).filter(is.number); + prUpdateParams.labels = (await map(labels, lookupLabelByName)).filter( + is.number, + ); } const gpr = await helper.updatePR( From ebb1575b7a8b592fb6ec0d13c16fb0de6209d066 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Sat, 3 Feb 2024 09:54:38 +0545 Subject: [PATCH 48/60] Apply suggestions from code review Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> --- docs/usage/configuration-options.md | 4 ++-- lib/workers/repository/update/pr/index.ts | 2 +- lib/workers/repository/update/pr/labels.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 9d5829871309e3..9fab5d90cc98ca 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -2110,8 +2110,8 @@ With the above config, every PR raised by Renovate will have the label `dependen Behaviour details: -- Renovate adds labels to the PR at time of PR creation, if any have been configured -- If any other bot or users modifies labels in a PR which Renovate created, it won't touch labels again in that open PR +- When Renovate creates a PR, it will add any configured labels to that PR +- When another bot, or user, changes the labels on a open Renovate PR then Renovate won't change those labels - If the labels for a PR change through configuration or other means, they are applied to any open PRs with unmodified labels (GitHub, GitLab, and Gitea only) The `labels` array is non-mergeable, meaning if multiple `packageRules` match then Renovate uses the last value for `labels`. diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index 1622dbe007d189..c309f64fea9f6d 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -420,7 +420,7 @@ export async function ensurePr( // ii) removeLabels: Labels that need to be removed // iii) labels: New labels for the PR, replacing the old labels array entirely. // This distinction is necessary because different platforms update labels differently - // For more details, refer to the updatePr function of each platform + // For more details, refer to the updatePr function of each platform. const [addLabels, removeLabels] = getChangedLabels( prCurrentLabels, diff --git a/lib/workers/repository/update/pr/labels.ts b/lib/workers/repository/update/pr/labels.ts index a0947f94b82d11..336ec3a3764502 100644 --- a/lib/workers/repository/update/pr/labels.ts +++ b/lib/workers/repository/update/pr/labels.ts @@ -52,7 +52,7 @@ export function areLabelsModified( } /** - * Determine if labels should be updated in the Pull Request + * Determine if labels should be updated in the Pull Request. */ export function shouldUpdateLabels( prInitialLabels: string[] | undefined, From 4951c89510b6526aad06cf9c9e59f00c086ea64d Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Sat, 3 Feb 2024 09:55:20 +0545 Subject: [PATCH 49/60] Update docs/usage/configuration-options.md --- docs/usage/configuration-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 9fab5d90cc98ca..e6f5668cd21860 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -2112,7 +2112,7 @@ Behaviour details: - When Renovate creates a PR, it will add any configured labels to that PR - When another bot, or user, changes the labels on a open Renovate PR then Renovate won't change those labels -- If the labels for a PR change through configuration or other means, they are applied to any open PRs with unmodified labels (GitHub, GitLab, and Gitea only) +- On GitHub, GitLab and Gitea: if the labels for a PR change through configuration , the changes will be applied to all PRs with unmodified labels The `labels` array is non-mergeable, meaning if multiple `packageRules` match then Renovate uses the last value for `labels`. If you want to add/combine labels, use the `addLabels` config option, which is mergeable. From 97db32b223b619d9920008095e4b3f1932095516 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Sun, 4 Feb 2024 00:20:38 +0545 Subject: [PATCH 50/60] Update lib/workers/repository/update/pr/index.ts Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> --- lib/workers/repository/update/pr/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index c309f64fea9f6d..1e062728fdc095 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -430,7 +430,7 @@ export async function ensurePr( // for Gitea updatePrConfig.labels = configuredLabels; - // for Github, Gitlab + // for GitHub, GitLab updatePrConfig.addLabels = addLabels; updatePrConfig.removeLabels = removeLabels; } From 7491f6af8492039900cb23b21501aaf91b52ad8e Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Sun, 4 Feb 2024 00:21:02 +0545 Subject: [PATCH 51/60] Apply suggestions from code review Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com> --- docs/usage/configuration-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index e6f5668cd21860..67cc819a1253ae 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -2112,7 +2112,7 @@ Behaviour details: - When Renovate creates a PR, it will add any configured labels to that PR - When another bot, or user, changes the labels on a open Renovate PR then Renovate won't change those labels -- On GitHub, GitLab and Gitea: if the labels for a PR change through configuration , the changes will be applied to all PRs with unmodified labels +- On GitHub, GitLab and Gitea: if the labels for a PR change through configuration, the changes will be applied to all PRs with unmodified labels The `labels` array is non-mergeable, meaning if multiple `packageRules` match then Renovate uses the last value for `labels`. If you want to add/combine labels, use the `addLabels` config option, which is mergeable. From d68c1f54409ca049df2739ac2ae34f401ab9be94 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Fri, 9 Feb 2024 09:21:57 +0545 Subject: [PATCH 52/60] remove unnecessary comments --- lib/modules/platform/gitlab/index.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/modules/platform/gitlab/index.ts b/lib/modules/platform/gitlab/index.ts index 1ce5d73957f198..2acb4de58a31a4 100644 --- a/lib/modules/platform/gitlab/index.ts +++ b/lib/modules/platform/gitlab/index.ts @@ -808,12 +808,10 @@ export async function updatePr({ body.target_branch = targetBranch; } - // Add new labels to the PR if (addLabels) { body.add_labels = addLabels; } - // Remove old labels from the PR if (removeLabels) { body.remove_labels = removeLabels; } From 6f68ffaa6520c2dd7b7127f3592e1ccbc26035f0 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Sun, 18 Feb 2024 19:35:10 +0545 Subject: [PATCH 53/60] refactor logic and add logs --- lib/workers/repository/update/pr/labels.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/workers/repository/update/pr/labels.ts b/lib/workers/repository/update/pr/labels.ts index 336ec3a3764502..6e926e85da416a 100644 --- a/lib/workers/repository/update/pr/labels.ts +++ b/lib/workers/repository/update/pr/labels.ts @@ -66,15 +66,17 @@ export function shouldUpdateLabels( return false; } - // If the labels in the PR have been modified by the user, they should not be updated. - if (areLabelsModified(prInitialLabels, prCurrentLabels ?? [])) { + // If the labels are unchanged, they should not be updated + if (dequal((configuredLabels ?? []).sort(), prInitialLabels.sort())) { return false; } - // If the 'labels are unchanged, they should not be updated. - if (dequal((configuredLabels ?? []).sort(), prInitialLabels.sort())) { + // If the labels in the PR have been modified by the user, they should not be updated + if (areLabelsModified(prInitialLabels, prCurrentLabels ?? [])) { + logger.debug('Labels have been modified by user - skipping labels update.'); return false; } + logger.debug('Labels have been changed in repo config- upading labels.'); return true; } From 1a10a2c1d0a613eb93affe12d9070b9614bddbb4 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Sun, 18 Feb 2024 19:38:55 +0545 Subject: [PATCH 54/60] Apply suggestions from code review Co-authored-by: Rhys Arkins --- docs/usage/configuration-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 67cc819a1253ae..197d47b4b58b21 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -2111,7 +2111,7 @@ With the above config, every PR raised by Renovate will have the label `dependen Behaviour details: - When Renovate creates a PR, it will add any configured labels to that PR -- When another bot, or user, changes the labels on a open Renovate PR then Renovate won't change those labels +- If another bot, or user, changes the labels on an open Renovate PR then Renovate won't change labels on the PR after that - On GitHub, GitLab and Gitea: if the labels for a PR change through configuration, the changes will be applied to all PRs with unmodified labels The `labels` array is non-mergeable, meaning if multiple `packageRules` match then Renovate uses the last value for `labels`. From f24c866bf89b7c48b747d560b5af60fe2e44e0c1 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Sun, 18 Feb 2024 19:41:16 +0545 Subject: [PATCH 55/60] update docs --- docs/usage/configuration-options.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 197d47b4b58b21..acdb149d1cd885 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -2110,9 +2110,15 @@ With the above config, every PR raised by Renovate will have the label `dependen Behaviour details: +<<<<<<< Updated upstream - When Renovate creates a PR, it will add any configured labels to that PR - If another bot, or user, changes the labels on an open Renovate PR then Renovate won't change labels on the PR after that - On GitHub, GitLab and Gitea: if the labels for a PR change through configuration, the changes will be applied to all PRs with unmodified labels +======= +- Renovate will add any configured labels to PRs at time of PR creation +- If labels on an open Renovate PR are modified after PR creation (e.g. via a user manually, or any automated process) then Renovate won't "enforce" its configured labels on subsequent runs. i.e. it won't reset/reapply its configured `labels` +- On GitHub, GitLab and Gitea: if a PR's labels weren't modified after PR creation, and there is a change to Renovate `labels` configuration for such a PR, then Renovate _will_ reset/reapply configured `labels` to align them with the new config +>>>>>>> Stashed changes The `labels` array is non-mergeable, meaning if multiple `packageRules` match then Renovate uses the last value for `labels`. If you want to add/combine labels, use the `addLabels` config option, which is mergeable. From 670d907120c1280e68d7cae486be4f42de1170aa Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Mon, 19 Feb 2024 12:03:18 +0545 Subject: [PATCH 56/60] sort in preparelabels --- lib/workers/repository/update/pr/index.ts | 2 +- lib/workers/repository/update/pr/labels.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/workers/repository/update/pr/index.ts b/lib/workers/repository/update/pr/index.ts index 1e062728fdc095..e0b2214261df1f 100644 --- a/lib/workers/repository/update/pr/index.ts +++ b/lib/workers/repository/update/pr/index.ts @@ -335,7 +335,7 @@ export async function ensurePr( { debugData: updatePrDebugData( config.baseBranch, - prepareLabels(config).sort(), // include labels in debug data, sort them just to be safe + prepareLabels(config), // include labels in debug data existingPr?.bodyStruct?.debugData, ), }, diff --git a/lib/workers/repository/update/pr/labels.ts b/lib/workers/repository/update/pr/labels.ts index 6e926e85da416a..3c41e47b19740f 100644 --- a/lib/workers/repository/update/pr/labels.ts +++ b/lib/workers/repository/update/pr/labels.ts @@ -10,7 +10,8 @@ export function prepareLabels(config: RenovateConfig): string[] { return [...new Set([...labels, ...addLabels])] .filter(is.nonEmptyStringAndNotWhitespace) .map((label) => template.compile(label, config)) - .filter(is.nonEmptyStringAndNotWhitespace); + .filter(is.nonEmptyStringAndNotWhitespace) + .sort(); } /** @@ -77,6 +78,6 @@ export function shouldUpdateLabels( return false; } - logger.debug('Labels have been changed in repo config- upading labels.'); + logger.debug('Labels have been changed in repo config- updating labels.'); return true; } From 69e976a5cc29687cab575ec7b4507ab2425ce8e2 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Mon, 19 Feb 2024 12:08:55 +0545 Subject: [PATCH 57/60] fix docs --- docs/usage/configuration-options.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index acdb149d1cd885..897f0022f6613d 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -2110,15 +2110,9 @@ With the above config, every PR raised by Renovate will have the label `dependen Behaviour details: -<<<<<<< Updated upstream -- When Renovate creates a PR, it will add any configured labels to that PR -- If another bot, or user, changes the labels on an open Renovate PR then Renovate won't change labels on the PR after that -- On GitHub, GitLab and Gitea: if the labels for a PR change through configuration, the changes will be applied to all PRs with unmodified labels -======= - Renovate will add any configured labels to PRs at time of PR creation - If labels on an open Renovate PR are modified after PR creation (e.g. via a user manually, or any automated process) then Renovate won't "enforce" its configured labels on subsequent runs. i.e. it won't reset/reapply its configured `labels` - On GitHub, GitLab and Gitea: if a PR's labels weren't modified after PR creation, and there is a change to Renovate `labels` configuration for such a PR, then Renovate _will_ reset/reapply configured `labels` to align them with the new config ->>>>>>> Stashed changes The `labels` array is non-mergeable, meaning if multiple `packageRules` match then Renovate uses the last value for `labels`. If you want to add/combine labels, use the `addLabels` config option, which is mergeable. From 45818d7fccf80782ad2aeae034059b1adaafc13c Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Mon, 19 Feb 2024 15:01:36 +0545 Subject: [PATCH 58/60] fix tests --- lib/workers/repository/config-migration/pr/index.spec.ts | 2 +- lib/workers/repository/onboarding/pr/index.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/workers/repository/config-migration/pr/index.spec.ts b/lib/workers/repository/config-migration/pr/index.spec.ts index 7792174a60a70f..f104d009750d7d 100644 --- a/lib/workers/repository/config-migration/pr/index.spec.ts +++ b/lib/workers/repository/config-migration/pr/index.spec.ts @@ -144,8 +144,8 @@ describe('workers/repository/config-migration/pr/index', () => { ); expect(platform.createPr).toHaveBeenCalledTimes(1); expect(platform.createPr.mock.calls[0][0].labels).toEqual([ - 'label', 'additional-label', + 'label', ]); }); diff --git a/lib/workers/repository/onboarding/pr/index.spec.ts b/lib/workers/repository/onboarding/pr/index.spec.ts index ba26fbbfaf414a..030ce3680d93de 100644 --- a/lib/workers/repository/onboarding/pr/index.spec.ts +++ b/lib/workers/repository/onboarding/pr/index.spec.ts @@ -106,8 +106,8 @@ describe('workers/repository/onboarding/pr/index', () => { ); expect(platform.createPr).toHaveBeenCalledTimes(1); expect(platform.createPr.mock.calls[0][0].labels).toEqual([ - 'label', 'additional-label', + 'label', ]); }); From 921e9f246cb3bfb0749c26489f60b9e1edb13670 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh Date: Wed, 21 Feb 2024 12:22:08 +0545 Subject: [PATCH 59/60] Update docs/usage/configuration-options.md Co-authored-by: Rhys Arkins --- docs/usage/configuration-options.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 897f0022f6613d..40c456761d2e28 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -2110,9 +2110,8 @@ With the above config, every PR raised by Renovate will have the label `dependen Behaviour details: -- Renovate will add any configured labels to PRs at time of PR creation -- If labels on an open Renovate PR are modified after PR creation (e.g. via a user manually, or any automated process) then Renovate won't "enforce" its configured labels on subsequent runs. i.e. it won't reset/reapply its configured `labels` -- On GitHub, GitLab and Gitea: if a PR's labels weren't modified after PR creation, and there is a change to Renovate `labels` configuration for such a PR, then Renovate _will_ reset/reapply configured `labels` to align them with the new config +- On GitHub, GitLab and Gitea: Renovate will keep PR labels in sync with configured labels, provided that no other user or bot has made changes to the labels after PR creation. If labels are changed by any other account, Renovate will stop making further changes. +- For other platforms, Renovate will add labels only at time of PR creation and not update them after that. The `labels` array is non-mergeable, meaning if multiple `packageRules` match then Renovate uses the last value for `labels`. If you want to add/combine labels, use the `addLabels` config option, which is mergeable. From 70126e09310714f6160514cb1914c8ddd6d06583 Mon Sep 17 00:00:00 2001 From: Rahul Gautam Singh Date: Mon, 18 Mar 2024 08:00:25 +0545 Subject: [PATCH 60/60] log waring for unavaiable labels --- lib/modules/platform/gitea/index.spec.ts | 42 ++++++++++++++++++++++++ lib/modules/platform/gitea/index.ts | 5 +++ 2 files changed, 47 insertions(+) diff --git a/lib/modules/platform/gitea/index.spec.ts b/lib/modules/platform/gitea/index.spec.ts index 66fcdb8ea83978..1f5c598460ca87 100644 --- a/lib/modules/platform/gitea/index.spec.ts +++ b/lib/modules/platform/gitea/index.spec.ts @@ -1875,6 +1875,48 @@ describe('modules/platform/gitea/index', () => { }), ).toResolve(); }); + + it('should log a warning if labels could not be looked up', async () => { + const updatedMockPR = partial({ + ...mockPRs[0], + number: 1, + title: 'New Title', + body: 'New Body', + state: 'open', + labels: [ + { + id: 1, + name: 'some-label', + }, + ], + }); + const scope = httpMock + .scope('https://gitea.com/api/v1') + .get('/repos/some/repo/pulls') + .query({ state: 'all', sort: 'recentupdate' }) + .reply(200, mockPRs) + .get('/repos/some/repo/labels') + .reply(200, mockRepoLabels) + .get('/orgs/some/labels') + .reply(200, mockOrgLabels) + .patch('/repos/some/repo/pulls/1') + .reply(200, updatedMockPR); + + await initFakePlatform(scope); + await initFakeRepo(scope); + await expect( + gitea.updatePr({ + number: 1, + prTitle: 'New Title', + prBody: 'New Body', + state: 'open', + labels: ['some-label', 'unavailable-label'], + }), + ).toResolve(); + expect(logger.warn).toHaveBeenCalledWith( + 'Some labels could not be looked up. Renovate may halt label updates assuming changes by others.', + ); + }); }); describe('mergePr', () => { diff --git a/lib/modules/platform/gitea/index.ts b/lib/modules/platform/gitea/index.ts index c6facff9614a27..f55c94da9fde95 100644 --- a/lib/modules/platform/gitea/index.ts +++ b/lib/modules/platform/gitea/index.ts @@ -612,6 +612,11 @@ const platform: Platform = { prUpdateParams.labels = (await map(labels, lookupLabelByName)).filter( is.number, ); + if (labels.length !== prUpdateParams.labels.length) { + logger.warn( + 'Some labels could not be looked up. Renovate may halt label updates assuming changes by others.', + ); + } } const gpr = await helper.updatePR(