Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/usage/configuration-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -2002,6 +2002,10 @@ For example, to group all non-major devDependencies updates together into a sing
<br>
Lock file maintenance will never be grouped with other dependency updates.

## `groupSingleUpdates`
Comment thread
felipecrs marked this conversation as resolved.

For example, you can set it to `false` if you prefer individual dependency names in PR titles when only one update is in the group.

## `groupSlug`

By default, Renovate will "slugify" the groupName to determine the branch name.
Expand Down
9 changes: 9 additions & 0 deletions lib/config/options/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2579,6 +2579,15 @@ const options: Readonly<RenovateOptions>[] = [
mergeable: true,
advancedUse: true,
},
{
name: 'groupSingleUpdates',
description:
'Apply group settings even when the group contains only one update.',
type: 'boolean',
default: true,
cli: false,
env: false,
},
// Pull Request options
{
name: 'labels',
Expand Down
1 change: 1 addition & 0 deletions lib/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export interface RenovateSharedConfig {
gitIgnoredAuthors?: string[];
group?: GroupConfig;
groupName?: string;
groupSingleUpdates?: boolean;
groupSlug?: string;
hashedBranchLength?: number;
ignoreDeps?: string[];
Expand Down
86 changes: 81 additions & 5 deletions lib/workers/repository/updates/generate.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ beforeEach(() => {

describe('workers/repository/updates/generate', () => {
describe('generateBranchConfig()', () => {
it('does not group single upgrade', () => {
it('groups single upgrade by default', () => {
const { groupSingleUpdates } = getConfig();
const branch = [
{
manager: 'some-manager',
Expand All @@ -37,16 +38,91 @@ describe('workers/repository/updates/generate', () => {
groupName: 'some-group',
prTitle: 'some-title',
releaseTimestamp: '2017-02-07T20:01:41+00:00' as Timestamp,
groupSingleUpdates,
group: {
foo: 2,
},
},
] satisfies BranchUpgradeConfig[];
const res = generateBranchConfig(branch);
expect(res.groupName).toBe('some-group');
expect(res.isGroup).toBeTrue();
expect(res.recreateClosed).toBeFalse();
});

it('groups single upgrade across multiple files', () => {
const groupSingleUpdates = true;
const branch = [
{
manager: 'some-manager',
branchName: 'some-branch',
depName: 'some-dep',
newVersion: '2.0.0',
groupName: 'some-group',
prTitle: 'some-title',
releaseTimestamp: '2017-02-07T20:01:41+00:00' as Timestamp,
groupSingleUpdates,
group: {
foo: 2,
},
packageFile: 'package.json',
},
{
manager: 'some-manager',
branchName: 'some-branch',
depName: 'some-dep',
newVersion: '2.0.0',
groupName: 'some-group',
prTitle: 'some-title',
releaseTimestamp: '2017-02-07T20:01:41+00:00' as Timestamp,
groupSingleUpdates,
group: {
foo: 2,
},
packageFile: 'packages/core/package.json',
},
] satisfies BranchUpgradeConfig[];
const res = generateBranchConfig(branch);
expect(res.groupName).toBe('some-group');
expect(res.isGroup).toBeTrue();
});

it('does not group single upgrade when groupSingleUpdates is false', () => {
const branch = [
{
manager: 'some-manager',
branchName: 'some-branch',
depName: 'some-dep',
groupName: 'some-group',
prTitle: 'some-title',
releaseTimestamp: '2017-02-07T20:01:41+00:00' as Timestamp,
groupSingleUpdates: false,
group: {
foo: 2,
},
},
] satisfies BranchUpgradeConfig[];
const res = generateBranchConfig(branch);
expect(res.groupName).toBeUndefined();
expect(res.recreateClosed).toBeFalse();
});

it('does not group single upgrade without groupName even with groupSingleUpdates', () => {
const branch = [
{
manager: 'some-manager',
branchName: 'some-branch',
depName: 'some-dep',
prTitle: 'some-title',
releaseTimestamp: '2017-02-07T20:01:41+00:00' as Timestamp,
groupSingleUpdates: true,
group: {
foo: 2,
},
},
] satisfies BranchUpgradeConfig[];
const res = generateBranchConfig(branch);
expect(res.groupName).toBeUndefined();
expect(res.releaseTimestamp).toBeDefined();
expect(res.recreateClosed).toBe(false);
expect(res.minimumGroupSize).toBe(1);
});

it('handles lockFileMaintenance', () => {
Expand Down Expand Up @@ -169,7 +245,7 @@ describe('workers/repository/updates/generate', () => {
] satisfies BranchUpgradeConfig[];
const res = generateBranchConfig(branch);
expect(res.groupName).toBeUndefined();
expect(res.recreateClosed).toBe(false);
expect(res.recreateClosed).toBeFalse();
});

it('groups multiple upgrades same version', () => {
Expand Down
4 changes: 3 additions & 1 deletion lib/workers/repository/updates/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,9 @@ export function generateBranchConfig(
const typesGroup =
depNames.length > 1 && !hasGroupName && isTypesGroup(branchUpgrades);
logger.trace(`groupEligible: ${groupEligible}`);
const useGroupSettings = hasGroupName && groupEligible;
const useGroupSettings =
hasGroupName &&
(groupEligible || branchUpgrades[0].groupSingleUpdates === true);
Comment thread
felipecrs marked this conversation as resolved.
logger.trace(`useGroupSettings: ${useGroupSettings}`);
let releaseTimestamp: Timestamp;

Expand Down