Skip to content

Commit

Permalink
feat: new branchNameStrict configuration flag (#17216)
Browse files Browse the repository at this point in the history
  • Loading branch information
setchy committed Aug 19, 2022
1 parent e697051 commit ca5be4b
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 4 deletions.
6 changes: 6 additions & 0 deletions docs/usage/configuration-options.md
Expand Up @@ -287,6 +287,12 @@ If you truly need to configure this then it probably means either:
- You are hopefully mistaken, and there's a better approach you should use, so open a new "config help" discussion at the [Renovate discussions tab](https://github.com/renovatebot/renovate/discussions) or
- You have a use case we didn't expect and we should have a feature request from you to add it to the project

## branchNameStrict

By default, Renovate does not use strict-mode when slugifying the branch name. This means that certain special characters such as `.` may end up within the branch name.

By setting this configuration to `true`, all special characters will be removed from the branch name, resulting in a branch name consisting exclusively of alphabetic characters separated by `-`.

## branchPrefix

You can modify this field if you want to change the prefix used.
Expand Down
6 changes: 6 additions & 0 deletions lib/config/options/index.ts
Expand Up @@ -2352,6 +2352,12 @@ const options: RenovateOptions[] = [
default: false,
supportedPlatforms: ['github'],
},
{
name: 'branchNameStrict',
description: `Whether to be strict about the use of special characters within the branch name.`,
type: 'boolean',
default: false,
},
];

export function getOptions(): RenovateOptions[] {
Expand Down
1 change: 1 addition & 0 deletions lib/config/types.ts
Expand Up @@ -28,6 +28,7 @@ export interface RenovateSharedConfig {
branchPrefix?: string;
branchPrefixOld?: string;
branchName?: string;
branchNameStrict?: boolean;
manager?: string | null;
commitMessage?: string;
commitMessagePrefix?: string;
Expand Down
46 changes: 46 additions & 0 deletions lib/workers/repository/updates/branch-name.spec.ts
Expand Up @@ -146,6 +146,22 @@ describe('workers/repository/updates/branch-name', () => {
expect(upgrade.branchName).toBe('renovate/jest-42.x');
});

it('realistic defaults with strict branch name enabled', () => {
const upgrade: RenovateConfig = {
branchNameStrict: true,
branchName:
'{{{branchPrefix}}}{{{additionalBranchPrefix}}}{{{branchTopic}}}',
branchTopic:
'{{{depNameSanitized}}}-{{{newMajor}}}{{#if isPatch}}.{{{newMinor}}}{{/if}}.x{{#if isLockfileUpdate}}-lockfile{{/if}}',
branchPrefix: 'renovate/',
depNameSanitized: 'jest',
newMajor: '42',
group: {},
};
generateBranchName(upgrade);
expect(upgrade.branchName).toBe('renovate/jest-42-x');
});

it('hashedBranchLength hashing', () => {
const upgrade: RenovateConfig = {
branchName:
Expand Down Expand Up @@ -293,5 +309,35 @@ describe('workers/repository/updates/branch-name', () => {
expect(fixture.upgrade.branchName).toEqual(fixture.expectedBranchName);
});
});

it('strict branch name enabled group', () => {
const upgrade: RenovateConfig = {
branchNameStrict: true,
groupName: 'some group name `~#$%^&*()-_=+[]{}|;,./<>? .version',
group: {
branchName: '{{groupSlug}}-{{branchTopic}}',
branchTopic: 'grouptopic',
},
};
generateBranchName(upgrade);
expect(upgrade.branchName).toBe(
'some-group-name-dollarpercentand-or-lessgreater-version-grouptopic'
);
});

it('strict branch name disabled', () => {
const upgrade: RenovateConfig = {
branchNameStrict: false,
groupName: '[some] group name.#$%version',
group: {
branchName: '{{groupSlug}}-{{branchTopic}}',
branchTopic: 'grouptopic',
},
};
generateBranchName(upgrade);
expect(upgrade.branchName).toBe(
'some-group-name.dollarpercentversion-grouptopic'
);
});
});
});
25 changes: 21 additions & 4 deletions lib/workers/repository/updates/branch-name.ts
Expand Up @@ -10,22 +10,36 @@ import * as template from '../../../util/template';
const MIN_HASH_LENGTH = 6;

const RE_MULTIPLE_DASH = regEx(/--+/g);

const RE_SPECIAL_CHARS_STRICT = regEx(/[`~!@#$%^&*()_=+[\]\\|{};':",.<>?]/g);

/**
* Clean git branch name
*
* Remove what clean-git-ref fails to:
* - leading dot/leading dot after slash
* - trailing dot
* - whitespace
* - special characters
* - leading or trailing dashes
* - chained dashes(breaks markdown comments) are replaced by single dash
*/
function cleanBranchName(branchName: string): string {
function cleanBranchName(
branchName: string,
branchNameStrict?: boolean
): string {
let cleanedBranchName = branchName;

if (branchNameStrict) {
cleanedBranchName = cleanedBranchName.replace(RE_SPECIAL_CHARS_STRICT, '-'); // massage out all special characters that slip through slugify
}

return cleanGitRef
.clean(branchName)
.clean(cleanedBranchName)
.replace(regEx(/^\.|\.$/), '') // leading or trailing dot
.replace(regEx(/\/\./g), '/') // leading dot after slash
.replace(regEx(/\s/g), '') // whitespace
.replace(regEx(/[[\]?:\\^~]/g), '-') // massage out all these characters: : ? [ \ ^ ~
.replace(regEx(/[[\]?:\\^~]/g), '-') // massage out all these characters: [ ] ? : \ ^ ~
.replace(regEx(/(^|\/)-+/g), '$1') // leading dashes
.replace(regEx(/-+(\/|$)/g), '$1') // trailing dashes
.replace(RE_MULTIPLE_DASH, '-'); // chained dashes
Expand Down Expand Up @@ -94,5 +108,8 @@ export function generateBranchName(update: RenovateConfig): void {
update.branchName = template.compile(update.branchName, update);
}

update.branchName = cleanBranchName(update.branchName);
update.branchName = cleanBranchName(
update.branchName,
update.branchNameStrict
);
}

0 comments on commit ca5be4b

Please sign in to comment.