renovate-merge¶
A schedule-driven merge-sweep. One job enumerates a group's open merge
requests, keeps the ones that are Renovate's, non-draft, and mergeable, and
merges each with its head sha. Run it from one pipeline schedule on
one repo and it drains the whole group — new repos need no wiring.
renovate-merge is a sibling of renovate-group, not
a replacement:
renovate-group |
renovate-merge |
|
|---|---|---|
| Does | runs Renovate to open MRs | merges the green ones |
| Schedule var | RENOVATE_TASK=scan |
RENOVATE_TASK=merge |
| Cadence | daily/weekly | frequent (e.g. hourly) |
Why it exists¶
Every phpboyscout project uses GitLab's fast-forward (ff) merge method
for linear, merge-commit-free history. GitLab's merge API requires a sha
to perform an FF merge, and Renovate's automerge call does not send one — so
every Renovate automerge returns 400 {"message":"SHA must be provided when
merging"} and the MR sits open indefinitely (a known upstream limitation,
renovatebot/renovate #26972).
After a cicd release that means one green phpboyscout/cicd pin-bump MR per
repo that never merges, piling up until a manual sweep.
renovate-merge does the merge Renovate can't: it re-fetches each candidate's
head sha and PUT …/merges with it — the call that succeeds under FF. It is
belt-and-braces behind Renovate's own (FF-broken) automerge, not a
replacement for it; the preset still correctly marks these MRs
automerge: true. See the
design spec.
What it merges¶
For every open MR in the group, an MR is merged only if all hold:
- its source branch starts with
branch_prefix(defaultrenovate/) — the hard guard that keeps the sweep inside Renovate's namespace, so it can never merge a human's MR; - it is not a draft — Renovate drafts every major, so majors (and anything Renovate is holding) are excluded automatically;
- its
detailed_merge_statusismergeable— green, up to date, no conflicts.
A red, behind-base, or conflicted MR is left alone. The sweep never rebases — that is Renovate's job; a behind-base MR is rebased by Renovate on its next scan and merged by a later sweep. Per-MR merge failures (a repo that just went red, a moved head) are logged and skipped, never fatal. Only an enumeration/auth failure exits non-zero.
Token scope¶
Uses $RENOVATE_TOKEN by default — the same group-wide token
renovate-group uses, which must have api
scope and merge permission on every project swept. On GitLab Free use a
fine-grained personal access token. The token is aliased internally to a
non-colliding variable name (SWEEP_TOKEN) so the default never
self-references — see
Explanation: renovate automation.
Jobs¶
| Job | What it runs |
|---|---|
renovate-merge |
A stdlib-only python3 sweep on the ci-base image: GET /groups/<group>/merge_requests?state=opened (paginated) → filter → GET each candidate for its head sha → PUT …/merge with sha=<head_sha>. |
Inputs¶
| Input | Type | Default | Description |
|---|---|---|---|
image_version |
string | "v0.1.1" |
phpboyscout/images/ci-base tag. The sweep is a stdlib-only python3 script, so ci-base is all it needs. |
stage |
string | renovate |
GitLab CI stage. Consumers must declare it in stages:. |
group |
string | (required) | Group path to sweep, e.g. phpboyscout (subgroups included). No default — a sweep bot must state its scope. The token needs merge rights on every project under it. |
branch_prefix |
string | "renovate/" |
Only MRs whose source branch starts with this are eligible. The safety guard keeping the sweep inside Renovate's namespace. |
exclude |
string | "" |
Comma-separated substrings of a project's full path to skip (e.g. phpboyscout/krites). Empty = sweep everything eligible. For holding a repo out of the sweep. |
dry_run |
boolean | false |
List the MRs that would be merged (with head sha) and merge nothing. Use for the first validation and for previews. |
token |
string | "$RENOVATE_TOKEN" |
Token used to enumerate and merge. Needs group-wide api + merge permission. Aliased internally to avoid self-reference. |
if |
string | '$CI_PIPELINE_SOURCE == "schedule" && $RENOVATE_TASK == "merge"' |
Gating rules:if:. Fires on a schedule with $RENOVATE_TASK=merge, so a merge schedule coexists with the renovate-group scan schedule. |
Usage¶
The merge-sweep bot, dogfooded in the cicd repo (whose phpboyscout scope
includes cicd itself):
include:
- component: gitlab.com/phpboyscout/cicd/[email protected]
inputs:
group: "phpboyscout"
Driven by a separate, frequent renovate-merge pipeline schedule that sets
RENOVATE_TASK=merge — distinct from the renovate-group scan schedule so
the two never collide on one repo.
Preview before arming the schedule
Run one pipeline with dry_run: true (or a one-off with the input
overridden) first — it lists the green renovate/* candidates and merges
nothing, so you can confirm the scope and token before the hourly schedule
starts merging for real.