Renovate presets¶
phpboyscout Renovate policy lives in a set of composable presets hosted in
this repo. A consumer's renovate.json is just the leaves its project is
made of — Renovate merges them. Change a preset here, and every repo that
extends it picks the change up on its next run.
Pair these with the renovate-group bot (which runs
Renovate across the whole group) — the bot decides when and which repos;
these presets decide policy.
How composition works¶
extends is an array. Each leaf's rules are scoped by matchManagers, so
combining leaves never collides — a :go leaf only touches gomod, a
:javascript leaf only npm. A project extends the bag of capabilities it
has:
Every leaf already extends the base, so you never name the base yourself.
The base (root)¶
gitlab>phpboyscout/cicd — extended (directly or via a leaf) by every repo.
It carries the universal policy:
- the custom manager that tracks
gitlab.com/phpboyscout/cicd/<component>@vX.Y.Zpins in.gitlab-ci.yml, and automerges those first-party pins on green; -
two custom managers for tool versions pinned inside
.gitlab-ci.yml, which no stock manager can see —gomodreadsgo.mod, not shell commands, so a CLI a pipeline depends on stays frozen indefinitely and the failure mode is an absence of MRs:go install gitlab.com/phpboyscout/<tool>/cmd/<bin>@vX.Y.Z— matched directly, withdepNamecaptured from the module path so one rule covers every first-party tool;- any CI variable carrying a version, when annotated on the line above:
This is the escape hatch for the common
GTB_VERSIONshape, where the variable name says nothing about which module it pins and thego installbelow references it as${GTB_VERSION}. It is opt-in by annotation — an unannotated variable is untouched, so the rule is inert wherever it is not wanted, and the annotation is not restricted to Go or to GitLab (datasource=docker depName=alpineworks the same way); -osvVulnerabilityAlerts+ security-fix fast-tracking (no soak, automerge); - patch + minor automerge on green (platformAutomerge), majors drafted for review; - thepre-commitmanager, enabled — Renovate ships it opt-in (documented as beta and off unless a config turns it on), so without this a repo with a.pre-commit-config.yamlgets no hook updates and no signal that it is missing them: the failure mode is an absence of MRs, indistinguishable from "nothing to update". It sits in the base rather than an ecosystem leaf because.pre-commit-config.yamlis language-agnostic — the repos carrying one span the Go, Tofu and mixed tracks. It is a no-op where no such file exists. See spec 0062; - house posture: semantic commits, immediate PRs, strict internal checks, a 3-day soak for third-party updates (first-party is exempt),dependencieslabel.
Leaves¶
| Leaf | Extends | Adds |
|---|---|---|
:go |
base | group all gomod into one MR (rangeStrategy: bump); postUpdateOptions: [gomodTidy, gomodUpdateImportPaths] so major bumps rewrite /vN import paths + land a tidy manifest |
:rust |
base | group all cargo into one MR |
:javascript |
base | group all npm into one MR |
:tofu |
base | group terraform providers/modules; prHourlyLimit: 4; re-point required_version at OpenTofu and track .opentofu-version — see OpenTofu, not Terraform |
:docker |
base | group Dockerfile/compose image bumps |
:python |
base | group pip/poetry/pipenv — bolt onto any repo with stray Python |
:mise |
base | group patch-level mise tool bumps — for image-build repos that pin their toolchain via mise |
:hugo |
:javascript |
+ Hugo modules (gomod) for a Hugo site |
:zensical |
:javascript |
a Zensical site (toolchain baked into infra-tools) |
:library |
base | keep version ranges flexible (replace) — reusable modules |
:application |
base | pin version ranges — reproducible builds / executables |
OpenTofu, not Terraform¶
Renovate's terraform manager hardcodes hashicorp/terraform as the
depName for every required_version constraint. From the shipped extractor:
dep.depType = 'required_version';
dep.datasource = GithubReleasesDatasource.id;
dep.depName = 'hashicorp/terraform'; // not a default — hardcoded
No manager option changes it, so an OpenTofu estate gets its core constraint
bumped against a different product on a different version line. On 2026-08-17
Terraform was at 1.15.8 and OpenTofu at 1.12.5, so the offered
~> 1.15.0 was a constraint no OpenTofu release satisfies — it broke
tofu init, validate and plan on every stack in phpboyscout/infra.
:tofu fixes it two ways:
required_versionis re-pointed, not disabled, withoverrideDepName/overridePackageName. Everything else the extractor set is already right for OpenTofu —github-releases,v-prefixedextractVersion,hashicorpversioning — so only the repository changes, and the merge request is namedrenovate/opentofu-opentofu-1.xrather than claiming to update Terraform..opentofu-versionis tracked by a custom manager. That is the filetenv/miseactually read, no built-in manager sees it, and before this it received no update merge requests at all.
Declaring customManagers in a leaf is safe: the option is mergeable: true,
so it concatenates with the base preset's rather than replacing them. The
base component-pin tracker keeps working. (labels and extends are not
mergeable and genuinely are replaced.)
See spec 0072.
Ecosystem and role are orthogonal: pick one ecosystem (or more), plus one role.
Recipes¶
// go library
{ "extends": ["gitlab>phpboyscout/cicd:go", "gitlab>phpboyscout/cicd:library"] }
// go CLI with a JS frontend
{ "extends": ["gitlab>phpboyscout/cicd:go", "gitlab>phpboyscout/cicd:javascript", "gitlab>phpboyscout/cicd:application"] }
// rust crate
{ "extends": ["gitlab>phpboyscout/cicd:rust", "gitlab>phpboyscout/cicd:library"] }
// tofu module
{ "extends": ["gitlab>phpboyscout/cicd:tofu", "gitlab>phpboyscout/cicd:library"] }
// hugo site
{ "extends": ["gitlab>phpboyscout/cicd:hugo"] }
// a go service that also has a python helper
{ "extends": ["gitlab>phpboyscout/cicd:go", "gitlab>phpboyscout/cicd:python", "gitlab>phpboyscout/cicd:application"] }
Anything genuinely repo-specific still goes in that repo's own renovate.json
below the extends — it is applied last and wins.
See also¶
renovate-group— the autodiscover bot that runs Renovate over the group.renovate-self— the single-repo runner.- Explanation: renovate automation
- Spec:
0050-centralized-renovate-presets