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
40 changes: 25 additions & 15 deletions docs/usage/key-concepts/automerge.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,29 @@ description: Learn all about Renovate's automerge functionality here

# Introduction

Automerging is a Renovate feature that you can use to automate upgrading dependencies.
When enabled, Renovate tries to merge the proposed update once the tests pass.
You can choose to automate some dependency updates by letting Renovate automerge its PR.
Renovate will wait for the required tests to pass before it automerges.

Keep in mind that Renovate automerges take a bit of time, do not expect Renovate to automerge a PR the second it opens and passes tests.
Wait for at least an hour or two before troubleshooting to ensure that Renovate has had the time to run once in a state where tests have passed and the branch is up-to-date with its base branch.
## Renovate automerges take time

Renovate automerges take time, so Renovate can't automerge a PR the second it passes your required tests.
Before you start troubleshooting, wait!
Give Renovate about two hours, so Renovate can run in a state where your tests have passed, and the PR branch is up-to-date with the base branch.
If you or others keep committing to the default branch then Renovate cannot find a suitable gap to automerge into!

Once a branch is automerged, the "Git state" needs to be recalculated for every remaining branch.
At times, merging one branch could result in another branch's updates being changed or even removed as unnecessary.
Renovate's approach is to ensure that automerging branches are up-to-date with their target branch before automerging.
This means merging multiple branches in a row won't work reliably, so we prefer not to do that.
What all this means is that Renovate will only automerge at most one branch/PR per target branch per run, before you need to wait for the next run.
After Renovate automerges a branch, Renovate must calculate the "Git state" again, for all remaining branches.
Merging one branch may result in another branch's updates being changed, or even removed as no longer needed.
Renovate requires automerging branches to be up-to-date with their target branch, _before_ automerging.
As merging more than one branch in a row does not work _reliably_, Renovate will only automerge one branch/PR, per target branch, per run.
Then you'll have to wait for the next time Renovate runs.

## Recommendations from the Renovate maintainers

As a general guide, we recommend that you enable automerge for any type of dependency updates where you would select "merge" anyway.
For any updates where you want to review the changelogs - or code - before you merge, you can keep automerge disabled.
In general, we recommend you enable automerge for any dependency update where you would select "merge" anyway.
Keep automerge _disabled_ for updates where you want to read the changelogs or code before the merge.

Automerge works particularly well for `devDependencies` as well as for production `dependencies` in projects which have great test coverage.
Automerge often works well for `devDependencies`.
It can work for production `dependencies` too, but your project should have good test coverage.

For example, if you have Jest or Mocha as a development dependency, and it has an upgrade with passing tests... automerge them!
If you have a linter like ESLint or TSLint and its update passes... automerge them!
Expand All @@ -34,7 +40,8 @@ If you have an API with 100% test coverage and Express is updated... automerge i
### Automerge lock file maintenance

The lowest risk type of update to automerge is probably `lockFileMaintenance`.
When Renovate performs lock file maintenance, it leaves the project dependency definitions unchanged, but refreshes the lock file completely so that the latest versions according to the package file constraints are installed.
When Renovate performs lock file maintenance, it leaves the project dependency definitions unchanged, but refreshes the lock file completely.
This means Renovate installs the latest versions, that match the package file constraints.

```json title="Example of automerging lock file maintenance"
{
Expand All @@ -48,8 +55,11 @@ When Renovate performs lock file maintenance, it leaves the project dependency d
### Automerge lint tool updates

Automerging lint tool updates can be a real time-saver.
Sometimes an update to a lint tool or plugin definition causes tests to fail, and that is usually deliberate/intentional because the lint authors have added a new rule that you need to adhere to.
But in many cases the new version(s) will pass tests, and if so then there's really nothing else to consider before merging, so they may as well be automerged:
Often a new lint tool version pass the updated tests, without any code changes on your end.
If the tests pass you may as well automerge the PR.

In cases where you need to make changes to your code, the Renovate PR will fail the linter check.
You can then make the necessary code changes directly in the Renovate branch for that PR, confirm the tests pass with your changes, and manually merge the PR.

```json title="Example of automerging lint and Prettier development packages"
{
Expand Down
3 changes: 3 additions & 0 deletions lib/modules/manager/gomod/__fixtures__/1/go-mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ replace github.com/pkg/errors => ../errors
replace golang.org/x/foo => github.com/pravesht/gocql v0.0.0

require github.com/caarlos0/env v3.5.0+incompatible

require sigs.k8s.io/structured-merge-diff/v4 v4.7.0
require github.com/cucumber/common/messages/go/v18 v18.0.0
18 changes: 18 additions & 0 deletions lib/modules/manager/gomod/__snapshots__/extract.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -774,5 +774,23 @@ exports[`modules/manager/gomod/extract > extractPackageFile() > extracts single-
"lineNumber": 13,
},
},
{
"currentValue": "v4.7.0",
"datasource": "go",
"depName": "sigs.k8s.io/structured-merge-diff/v4",
"depType": "require",
"managerData": {
"lineNumber": 15,
},
},
{
"currentValue": "v18.0.0",
"datasource": "go",
"depName": "github.com/cucumber/common/messages/go/v18",
"depType": "require",
"managerData": {
"lineNumber": 16,
},
},
]
`;
6 changes: 6 additions & 0 deletions lib/modules/manager/gomod/__snapshots__/update.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ replace github.com/pkg/errors => ../errors
replace golang.org/x/foo => github.com/pravesht/gocql v0.0.0

require github.com/caarlos0/env v3.5.0+incompatible

require sigs.k8s.io/structured-merge-diff/v4 v4.7.0
require github.com/cucumber/common/messages/go/v18 v18.0.0
"
`;

Expand Down Expand Up @@ -100,5 +103,8 @@ replace github.com/pkg/errors => ../errors
replace golang.org/x/foo => github.com/pravesht/gocql v0.0.0

require github.com/caarlos0/env v3.5.0+incompatible

require sigs.k8s.io/structured-merge-diff/v4 v4.7.0
require github.com/cucumber/common/messages/go/v18 v18.0.0
"
`;
4 changes: 2 additions & 2 deletions lib/modules/manager/gomod/extract.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ describe('modules/manager/gomod/extract', () => {
it('extracts single-line requires', () => {
const res = extractPackageFile(gomod1)?.deps;
expect(res).toMatchSnapshot();
expect(res).toHaveLength(10);
expect(res?.filter((e) => e.depType === 'require')).toHaveLength(7);
expect(res).toHaveLength(12);
expect(res?.filter((e) => e.depType === 'require')).toHaveLength(9);
expect(res?.filter((e) => e.depType === 'indirect')).toHaveLength(1);
expect(res?.filter((e) => e.skipReason)).toHaveLength(2);
expect(res?.filter((e) => e.depType === 'replace')).toHaveLength(2);
Expand Down
32 changes: 32 additions & 0 deletions lib/modules/manager/gomod/update.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,38 @@ describe('modules/manager/gomod/update', () => {
expect(res).toContain('github.com/pkg/errors/v2 v2.0.0');
});

it('bumps major with single package name component', () => {
const upgrade = {
depName: 'sigs.k8s.io/structured-merge-diff/v4',
managerData: { lineNumber: 15 },
currentValue: 'v4.7.0',
newValue: 'v6.0.0',
newMajor: 6,
updateType: 'major' as UpdateType,
depType: 'require',
};
const res = updateDependency({ fileContent: gomod1, upgrade });
expect(res).not.toEqual(gomod1);
expect(res).toContain('sigs.k8s.io/structured-merge-diff/v6 v6.0.0');
});

it('bumps major with multiple package name components', () => {
const upgrade = {
depName: 'github.com/cucumber/common/messages/go/v18',
managerData: { lineNumber: 16 },
currentValue: 'v18.0.0',
newValue: 'v19.0.0',
newMajor: 19,
updateType: 'major' as UpdateType,
depType: 'require',
};
const res = updateDependency({ fileContent: gomod1, upgrade });
expect(res).not.toEqual(gomod1);
expect(res).toContain(
'github.com/cucumber/common/messages/go/v19 v19.0.0',
);
});

it('replaces major gopkg.in updates', () => {
const upgrade = {
depName: 'gopkg.in/russross/blackfriday.v1',
Expand Down
4 changes: 3 additions & 1 deletion lib/modules/manager/gomod/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { newlineRegex, regEx } from '../../../util/regex';
import type { UpdateDependencyConfig } from '../types';

function getNameWithNoVersion(name: string): string {
let nameNoVersion = name.split('/').slice(0, 3).join('/');
// remove version suffixes like /v1 or /v2
let nameNoVersion = name.replace(/\/v\d+$/, '');
// gopkg.in is a special case where the major version is added with a dot rather than a slash
if (nameNoVersion.startsWith('gopkg.in')) {
nameNoVersion = nameNoVersion.replace(regEx(/\.v\d+$/), '');
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@
"vuln-vects": "1.1.0",
"xmldoc": "1.3.0",
"yaml": "2.7.1",
"zod": "3.24.2"
"zod": "3.24.3"
},
"optionalDependencies": {
"better-sqlite3": "11.9.1",
Expand Down
12 changes: 6 additions & 6 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading