Skip to content
Merged
29 changes: 16 additions & 13 deletions docs/usage/configuration-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ You can store your Renovate configuration file in one of these locations:
When Renovate runs on a repository, it tries to find the configuration files in the order listed above.
Renovate stops the search after it finds the first match.

Renovate always uses the config from the repository's default branch, even if that configuration specifies multiple `baseBranches`.
Renovate always uses the config from the repository's default branch, even if that configuration specifies `baseBranchPatterns`.
Renovate does not read/override the config from within each base branch if present.

Also, be sure to check out Renovate's [shareable config presets](./config-presets.md) to save yourself from reinventing any wheels.
Expand Down Expand Up @@ -307,24 +307,27 @@ If you're not already using `bors-ng` or similar, don't worry about this option.
When creating a PR in Azure DevOps, some branches can be protected with branch policies to [check for linked work items](https://docs.microsoft.com/en-us/azure/devops/repos/git/branch-policies?view=azure-devops#check-for-linked-work-items).
Creating a work item in Azure DevOps is beyond the scope of Renovate, but Renovate can link an already existing work item when creating PRs.

## baseBranches
## baseBranchPatterns

This configuration option was formerly known as `baseBranches`.

By default, Renovate will detect and process only the repository's default branch.
For most projects, this is the expected approach.
Renovate also allows users to explicitly configure `baseBranches`, e.g. for use cases such as:
Renovate also allows users to explicitly configure `baseBranchPatterns`, e.g. for use cases such as:

- You wish Renovate to process only a non-default branch, e.g. `dev`: `"baseBranches": ["dev"]`
- You have multiple release streams you need Renovate to keep up to date, e.g. in branches `main` and `next`: `"baseBranches": ["main", "next"]`
- You want to update your main branch and consistently named release branches, e.g. `main` and `release/<version>`: `"baseBranches": ["main", "/^release\\/.*/"]`
- You wish Renovate to process only a non-default branch, e.g. `dev`: `"baseBranchPatterns": ["dev"]`
- You have multiple release streams you need Renovate to keep up to date, e.g. in branches `main` and `next`: `"baseBranchPatterns": ["main", "next"]`
- You want to update your main branch and consistently named release branches, e.g. `main` and `release/<version>`: `"baseBranchPatterns": ["main", "/^release\\/.*/"]`

It's possible to add this setting into the `renovate.json` file as part of the "Configure Renovate" onboarding PR.
If so then Renovate will reflect this setting in its description and use package file contents from the custom base branch(es) instead of default.

`baseBranches` supports Regular Expressions that must begin and end with `/`, e.g.:
The simplest approach is exact matches, e.g. `["main", "dev"]`.
`baseBranchPatterns` also supports Regular Expressions that must begin and end with `/`, e.g.:

```json
{
"baseBranches": ["main", "/^release\\/.*/"]
"baseBranchPatterns": ["main", "/^release\\/.*/"]
}
```

Expand All @@ -334,21 +337,21 @@ With a negation, all branches except those matching the regex will be added to t

```json
{
"baseBranches": ["!/^pre-release\\/.*/"]
"baseBranchPatterns": ["!/^pre-release\\/.*/"]
}
```

You can also use the special `"$default"` string to denote the repository's default branch, which is useful if you have it in an org preset, e.g.:

```json
{
"baseBranches": ["$default", "/^release\\/.*/"]
"baseBranchPatterns": ["$default", "/^release\\/.*/"]
}
```

<!-- prettier-ignore -->
!!! note
Do _not_ use the `baseBranches` config option when you've set a `forkToken`.
Do _not_ use the `baseBranchPatterns` config option when you've set a `forkToken`.
You may need a `forkToken` when you're using the Forking Renovate app.

## bbAutoResolvePrTasks
Expand Down Expand Up @@ -710,12 +713,12 @@ To help you with this, Renovate will create config migration pull requests, when

Example:

After we changed the [`baseBranches`](#basebranches) feature, the Renovate configuration migration pull request would make this change:
After we changed the [`baseBranchPatterns`](#basebranchpatterns) feature, the Renovate configuration migration pull request would make this change:

```diff
{
- "baseBranch": "main"
+ "baseBranches": ["main"]
+ "baseBranchPatterns": ["main"]
}
```

Expand Down
6 changes: 3 additions & 3 deletions docs/usage/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,17 +112,17 @@ Read our documentation on the [dependencyDashboardApproval](./configuration-opti
### Use an alternative branch as my Pull Request target

Say your repository's default branch is `main` but you want Renovate to use the `next` branch as its PR target.
You can configure the PR target branch via the `baseBranches` option.
You can configure the PR target branch via the `baseBranchPatterns` option.

Add this line to the `renovate.json` file that's in the _default_ branch (`main` in this example).

```json
{
"baseBranches": ["next"]
"baseBranchPatterns": ["next"]
}
```

You can set more than one PR target branch in the `baseBranches` array.
You can set more than one PR target branch in the `baseBranchPatterns` array.

### Support private npm modules

Expand Down
2 changes: 1 addition & 1 deletion docs/usage/getting-started/running.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ Forking Renovate needs only `read` level access to the code of any repository it
If you use Forking Renovate, you'll miss out on these features of the regular Renovate app:

- Automerge
- The `baseBranches` config option
- The `baseBranchPatterns` config option

### Hosting Renovate

Expand Down
2 changes: 1 addition & 1 deletion lib/config/__snapshots__/migration.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ exports[`config/migration > migrateConfig(config, parentConfig) > migrates confi
"autodiscover": true,
"automerge": false,
"automergeType": "branch",
"baseBranches": [
"baseBranchPatterns": [
"next",
],
"binarySource": "global",
Expand Down
12 changes: 11 additions & 1 deletion lib/config/migration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ describe('config/migration', () => {
expect(migratedConfig.automerge).toBe(false);
expect(migratedConfig.packageRules).toHaveLength(11);
expect(migratedConfig.hostRules).toHaveLength(1);
expect(migratedConfig.baseBranchPatterns).toMatchObject(['next']);
});

it('migrates before and after schedules', () => {
Expand Down Expand Up @@ -391,7 +392,7 @@ describe('config/migration', () => {
const { isMigrated, migratedConfig } =
configMigration.migrateConfig(config);
expect(migratedConfig).toEqual({
baseBranches: [],
baseBranchPatterns: [],
commitMessage: 'test',
ignorePaths: [],
includePaths: ['test'],
Expand Down Expand Up @@ -771,4 +772,13 @@ describe('config/migration', () => {
res = configMigration.migrateConfig(config);
expect(res.isMigrated).toBeTrue();
});

it('migrates baseBranches and baseBranch', () => {
const config = { baseBranches: ['main', 'dev'] };
const res = configMigration.migrateConfig(config);
expect(res.isMigrated).toBeTrue();
expect(res.migratedConfig).toEqual({
baseBranchPatterns: ['main', 'dev'],
});
});
});
16 changes: 14 additions & 2 deletions lib/config/migrations/custom/base-branch-migration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ describe('config/migrations/custom/base-branch-migration', () => {
baseBranch: 'test',
},
{
baseBranches: ['test'],
baseBranchPatterns: ['test'],
},
);
});
Expand All @@ -18,7 +18,19 @@ describe('config/migrations/custom/base-branch-migration', () => {
baseBranch: ['test'],
} as any,
{
baseBranches: ['test'],
baseBranchPatterns: ['test'],
},
);
});

it('should push to existing bassBranchPatterns', () => {
expect(BaseBranchMigration).toMigrate(
{
baseBranch: ['test'],
baseBranchPatterns: ['base'],
} as any,
{
baseBranchPatterns: ['base', 'test'],
},
);
});
Expand Down
5 changes: 3 additions & 2 deletions lib/config/migrations/custom/base-branch-migration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ export class BaseBranchMigration extends AbstractMigration {
override readonly propertyName = 'baseBranch';

override run(value: unknown): void {
const baseBranchPatterns = this.get('baseBranchPatterns') ?? [];
if (is.array<string>(value)) {
this.setSafely('baseBranches', value);
this.setHard('baseBranchPatterns', baseBranchPatterns.concat(value));
}
if (is.string(value)) {
this.setSafely('baseBranches', [value]);
this.setHard('baseBranchPatterns', baseBranchPatterns.concat([value]));
}
}
}
1 change: 1 addition & 0 deletions lib/config/migrations/migrations-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export class MigrationsService {
['masterIssueTitle', 'dependencyDashboardTitle'],
['masterIssueLabels', 'dependencyDashboardLabels'],
['regexManagers', 'customManagers'],
['baseBranches', 'baseBranchPatterns'],
]);

static readonly customMigrations: readonly MigrationConstructor[] = [
Expand Down
2 changes: 1 addition & 1 deletion lib/config/options/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1062,7 +1062,7 @@ const options: RenovateOptions[] = [
globalOnly: true,
},
{
name: 'baseBranches',
name: 'baseBranchPatterns',
description:
'List of one or more custom base branches defined as exact strings and/or via regex expressions.',
type: 'array',
Expand Down
3 changes: 2 additions & 1 deletion lib/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,8 @@ export interface RenovateConfig
reportPath?: string;
reportType?: 'logging' | 'file' | 's3' | null;
depName?: string;
baseBranches?: string[];
/** user configurable base branch patterns*/
baseBranchPatterns?: string[];
commitBody?: string;
useBaseBranchConfig?: UseBaseBranchConfigType;
baseBranch?: string;
Expand Down
6 changes: 3 additions & 3 deletions lib/config/validation-helpers/match-base-branches.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { check } from './match-base-branches';

describe('config/validation-helpers/match-base-branches', () => {
it('returns error when baseBranches is not defined', () => {
it('returns error when baseBranchPatterns is not defined', () => {
const res = check({
resolvedRule: { matchBaseBranches: ['develop'], addLabels: ['develop'] },
currentPath: 'packageRules[0]',
Expand All @@ -10,7 +10,7 @@ describe('config/validation-helpers/match-base-branches', () => {
{
topic: 'Configuration Error',
message:
'packageRules[0]: You must configure baseBranches inorder to use them inside matchBaseBranches.',
'packageRules[0]: You must configure baseBranchPatterns in order to use them inside matchBaseBranches.',
},
]);
});
Expand All @@ -19,7 +19,7 @@ describe('config/validation-helpers/match-base-branches', () => {
const res = check({
resolvedRule: { matchBaseBranches: ['develop'], addLabels: ['develop'] },
currentPath: 'packageRules[0]',
baseBranches: ['develop', 'main'],
baseBranchPatterns: ['develop', 'main'],
});
expect(res).toBeEmptyArray();
});
Expand Down
6 changes: 3 additions & 3 deletions lib/config/validation-helpers/match-base-branches.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import type { CheckBaseBranchesArgs } from './types';
export function check({
resolvedRule,
currentPath,
baseBranches,
baseBranchPatterns,
}: CheckBaseBranchesArgs): ValidationMessage[] {
const warnings: ValidationMessage[] = [];
if (Array.isArray(resolvedRule.matchBaseBranches)) {
if (!is.nonEmptyArray(baseBranches)) {
if (!is.nonEmptyArray(baseBranchPatterns)) {
warnings.push({
topic: 'Configuration Error',
message: `${currentPath}: You must configure baseBranches inorder to use them inside matchBaseBranches.`,
message: `${currentPath}: You must configure baseBranchPatterns in order to use them inside matchBaseBranches.`,
});
}
}
Expand Down
3 changes: 2 additions & 1 deletion lib/config/validation-helpers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ export interface CheckMatcherArgs {
export interface CheckBaseBranchesArgs {
resolvedRule: PackageRule;
currentPath: string;
baseBranches?: string[];
/** user configurable base branch patterns*/
baseBranchPatterns?: string[];
}
10 changes: 5 additions & 5 deletions lib/config/validation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ describe('config/validation', () => {

it('validates matchBaseBranches', async () => {
const config = {
baseBranches: ['foo'],
baseBranchPatterns: ['foo'],
packageRules: [
{
matchBaseBranches: ['foo'],
Expand All @@ -244,7 +244,7 @@ describe('config/validation', () => {
expect(warnings).toHaveLength(0);
});

it('catches invalid matchBaseBranches when baseBranches is not defined', async () => {
it('catches invalid matchBaseBranches when baseBranchPatterns is not defined', async () => {
const config = {
packageRules: [
{
Expand Down Expand Up @@ -372,15 +372,15 @@ describe('config/validation', () => {
]);
});

it('catches invalid baseBranches regex', async () => {
it('catches invalid baseBranchPatterns regex', async () => {
const config = {
baseBranches: ['/***$}{]][/', '/branch/i'],
baseBranchPatterns: ['/***$}{]][/', '/branch/i'],
};
const { errors } = await configValidation.validateConfig('repo', config);
expect(errors).toEqual([
{
topic: 'Configuration Error',
message: 'Invalid regExp for baseBranches: `/***$}{]][/`',
message: 'Invalid regExp for baseBranchPatterns: `/***$}{]][/`',
},
]);
});
Expand Down
12 changes: 6 additions & 6 deletions lib/config/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ export async function validateConfig(
...matchBaseBranchesValidator.check({
resolvedRule,
currentPath: `${currentPath}[${subIndex}]`,
baseBranches: config.baseBranches!,
baseBranchPatterns: config.baseBranchPatterns!,
}),
);
const selectorLength = Object.keys(resolvedRule).filter(
Expand Down Expand Up @@ -578,15 +578,15 @@ export async function validateConfig(
}
}
}
if (key === 'baseBranches') {
for (const baseBranch of val as string[]) {
if (key === 'baseBranchPatterns') {
for (const baseBranchPattern of val as string[]) {
if (
isRegexMatch(baseBranch) &&
!getRegexPredicate(baseBranch)
isRegexMatch(baseBranchPattern) &&
!getRegexPredicate(baseBranchPattern)
) {
errors.push({
topic: 'Configuration Error',
message: `Invalid regExp for ${currentPath}: \`${baseBranch}\``,
message: `Invalid regExp for ${currentPath}: \`${baseBranchPattern}\``,
});
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/modules/platform/local/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ The command doesn't do any "compare" - or before and after analysis - if you wan
## Limitations

- `local>` presets can't be resolved. Normally these would point to the local platform such as GitHub, but in the case of running locally, it does not exist
- `baseBranches` are ignored
- `baseBranchPatterns` are ignored
- Branch creation is not supported
5 changes: 4 additions & 1 deletion lib/util/git/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1214,7 +1214,10 @@ describe('util/git/index', { timeout: 10000 }, () => {
describe('syncGit()', () => {
it('should clone a specified base branch', async () => {
tmpDir = await tmp.dir({ unsafeCleanup: true });
GlobalConfig.set({ baseBranches: ['develop'], localDir: tmpDir.path });
GlobalConfig.set({
baseBranchPatterns: ['develop'],
localDir: tmpDir.path,
});
await git.initRepo({
url: origin.path,
defaultBranch: 'develop',
Expand Down
13 changes: 7 additions & 6 deletions lib/workers/global/config/parse/env.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,13 @@ describe('workers/global/config/parse/env', () => {
});

test.each`
envArg | config
${{ RENOVATE_RECREATE_CLOSED: 'true' }} | ${{ recreateWhen: 'always' }}
${{ RENOVATE_RECREATE_CLOSED: 'false' }} | ${{ recreateWhen: 'auto' }}
${{ RENOVATE_RECREATE_WHEN: 'auto' }} | ${{ recreateWhen: 'auto' }}
${{ RENOVATE_RECREATE_WHEN: 'always' }} | ${{ recreateWhen: 'always' }}
${{ RENOVATE_RECREATE_WHEN: 'never' }} | ${{ recreateWhen: 'never' }}
envArg | config
${{ RENOVATE_RECREATE_CLOSED: 'true' }} | ${{ recreateWhen: 'always' }}
${{ RENOVATE_RECREATE_CLOSED: 'false' }} | ${{ recreateWhen: 'auto' }}
${{ RENOVATE_RECREATE_WHEN: 'auto' }} | ${{ recreateWhen: 'auto' }}
${{ RENOVATE_RECREATE_WHEN: 'always' }} | ${{ recreateWhen: 'always' }}
${{ RENOVATE_RECREATE_WHEN: 'never' }} | ${{ recreateWhen: 'never' }}
${{ RENOVATE_BASE_BRANCHES: '["main", "dev"]' }} | ${{ baseBranchPatterns: ['main', 'dev'] }}
`('"$envArg" -> $config', async ({ envArg, config }) => {
expect(await env.getConfig(envArg)).toMatchObject(config);
});
Expand Down
1 change: 1 addition & 0 deletions lib/workers/global/config/parse/env.ts
Comment thread
RahulGautamSingh marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const renameKeys = {
mergeConfidenceApiBaseUrl: 'mergeConfidenceEndpoint',
mergeConfidenceSupportedDatasources: 'mergeConfidenceDatasources',
allowedPostUpgradeCommands: 'allowedCommands',
baseBranches: 'baseBranchPatterns',
};

function renameEnvKeys(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
Expand Down
Loading