diff --git a/lib/workers/repository/updates/generate.spec.ts b/lib/workers/repository/updates/generate.spec.ts index ab9ec59aea2f8e7d6aa582ada0b825aaa6563db0..557ae43779ceda41079f23ea32fc738e8f0c0dca 100644 --- a/lib/workers/repository/updates/generate.spec.ts +++ b/lib/workers/repository/updates/generate.spec.ts @@ -1,3 +1,4 @@ +import { codeBlock } from 'common-tags'; import { getConfig } from '../../../../test/util'; import type { RenovateConfig, UpdateType } from '../../../config/types'; import { NpmDatasource } from '../../../modules/datasource/npm'; @@ -1164,6 +1165,69 @@ describe('workers/repository/updates/generate', () => { ); }); + it('dedupes duplicate table rows', () => { + const branch: BranchUpgradeConfig[] = [ + { + commitBodyTable: true, + manager: 'some-manager', + datasource: NpmDatasource.id, + depName: 'some-dep', + groupName: 'some-group', + branchName: 'some-branch', + prTitle: 'some-title', + currentVersion: '5.1.0', + newVersion: '5.1.2', + }, + { + commitBodyTable: true, + manager: 'some-manager', + datasource: 'docker', + depName: 'some-dep', + groupName: 'some-group', + branchName: 'some-branch', + prTitle: 'some-title', + currentVersion: '5.1.0', + newVersion: '5.1.2', + }, + { + commitBodyTable: true, + manager: 'some-manager', + datasource: NpmDatasource.id, + depName: 'another-dep', + groupName: 'some-group', + branchName: 'some-branch', + prTitle: 'some-title', + currentVersion: '5.1.1', + newVersion: '5.1.2', + }, + { + commitBodyTable: true, + manager: 'some-manager', + datasource: NpmDatasource.id, + depName: 'another-dep', + groupName: 'some-group', + branchName: 'some-branch', + prTitle: 'some-title', + currentVersion: '5.1.1', + newVersion: '5.1.2', + }, + ]; + const res = generateBranchConfig(branch); + expect(res.commitMessage?.trim()).toBe(codeBlock` + | datasource | package | from | to | + | ---------- | ----------- | ----- | ----- | + | npm | another-dep | 5.1.1 | 5.1.2 | + | npm | some-dep | 5.1.0 | 5.1.2 | + | docker | some-dep | 5.1.0 | 5.1.2 | + `); + expect([ + ...(res.commitMessage?.matchAll(/another-dep/g) ?? []), + ]).toBeArrayOfSize(1); + expect([ + ...(res.commitMessage?.matchAll(/some-dep/g) ?? []), + ]).toBeArrayOfSize(2); + }); + it('using commitMessagePrefix without separator', () => { const branch: BranchUpgradeConfig[] = [ { diff --git a/lib/workers/repository/updates/generate.ts b/lib/workers/repository/updates/generate.ts index b569f3f507a597bb7a3b5997ab521321609873cd..93d2e12209b186b2d166dc9cfbbbf30f6ca23f8a 100644 --- a/lib/workers/repository/updates/generate.ts +++ b/lib/workers/repository/updates/generate.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */ import is from '@sindresorhus/is'; import { DateTime } from 'luxon'; import mdTable from 'markdown-table'; @@ -8,6 +7,7 @@ import { CONFIG_SECRETS_EXPOSED } from '../../../constants/error-messages'; import { logger } from '../../../logger'; import { newlineRegex, regEx } from '../../../util/regex'; import { sanitize } from '../../../util/sanitize'; +import { safeStringify } from '../../../util/stringify'; import * as template from '../../../util/template'; import type { BranchConfig, BranchUpgradeConfig } from '../../types'; import { CommitMessage } from '../model/commit-message'; @@ -387,10 +387,21 @@ export function generateBranchConfig( const tableRows = config.upgrades .map(getTableValues) .filter((x): x is string[] => is.array(x, is.string)); + if (tableRows.length) { - let table: string[][] = []; + const table: string[][] = []; table.push(['datasource', 'package', 'from', 'to']); - table = table.concat(tableRows!); + + const seenRows = new Set<string>(); + + for (const row of tableRows) { + const key = safeStringify(row); + if (seenRows.has(key)) { + continue; + } + seenRows.add(key); + table.push(row); + } config.commitMessage += '\n\n' + mdTable(table) + '\n'; } return config;