--- date: 2026-10-30 branch: fix/renovate-run-hygiene title: Renovate's first completed dry runs, audited; it would have opened red PRs for every app and missed the databases. Config fixed --- ## What changed **`renovate.json5` only.** Each change carries a comment quoting the measurement behind it. 1. **Three new regex managers, so updates edit the SOURCE.** - `catalog/*.yaml` `source.image`. - `catalog/render.py` `OAUTH2_PROXY_IMAGE`. - CNPG `imageName:` under `platform/` and `apps/`. The first two match the rendered line's depName, so the catalog edit and the generated `apps/wave-*` edit land in **one** branch. 2. **`allowedVersions` mirroring each ServiceDefinition's `update.range`:** - gitea/gitea `<2.0.0` - nextcloud `<32.0.0` - qbittorrent `<6.0.0` - radarr `<6.0.0` - sonarr `<5.0.0` - semaphore `<3.0.0` Plus CNPG postgresql `<17.0.0`, because a Postgres major is a migration, not a bump. 3. **The blast-radius never-automerge list gains** `gitea/gitea`, `gitea/act_runner` and `ghcr.io/cloudnative-pg/postgresql`. 4. **HelmRelease range widening** (`matchManagers: flux`, ranged currentValue) is never auto-merged and is labelled `range-widen`. 5. **Majors need a Dependency Dashboard tick** (`dependencyDashboardApproval`) before a PR opens. 6. **`flux` manager docker deps are disabled.** These are duplicates of `kubernetes` manager extractions. 7. **`velero/velero-plugin-for-aws` uses `semver` versioning**, so its RC pin can reach a stable release. 8. **`python` minors are not auto-merged.** 9. **Two false comments are corrected.** - Ranges "cap Renovate at patches": false, Renovate widens them. - `nextcloud:31-apache` and `docker:27-dind` "cannot be maintained": false, they were. PR #85 is merged, so nothing here overlaps an open branch. ### The audit: dispatch runs 353 (07:12 UTC) and 354 (07:23 UTC), on 593d0fa Both runs ended `success`, Renovate `"result": "done"`, `exitCode 0`. Both were at `info` level, so I reproduced the per-dependency detail with a debug-level local dry run of the same commit (see below). The runs were inside the 03:00–06:00 America/New_York window, so branches were processed: - run 353: 37 "Would commit" branches; - run 354: 40, because the operator had added `RENOVATE_GITHUB_COM_TOKEN` 9 s before it. Gitea's router log for the act-runner pod during both runs shows 317 2xx responses. The only non-2xx were all expected: - `/v2/` 401: the registry challenge; - `/admin/orgs` 403: the #85 scope probe, by design; - 6× `HEAD …/manifests/sha256:000…` 404: the placeholder digests. | # | Class | Count | Cause | Severity | Fix | |---|---|---|---|---|---| | 1 | App-image PRs edit only generated `apps/wave-*` | 9 branches | A ServiceDefinition has no `apiVersion`, so the `kubernetes` manager extracts 0 deps from `catalog/`. The oauth2-proxy sidecar is a Python constant (`catalog/render.py:132`) | **Real problem.** Every such PR fails `ci/render-golden.sh` (reproduced: rc 1 "GOLDEN DRIFT"), stays red and holds a PR slot | git (1) | | 2 | CNPG `imageName` untracked | 3 Clusters | The `kubernetes` manager reads `image:` only. The one tracked postgres line was the grant Job (`nextcloud-db.yaml:303`, "keep in step with spec.imageName") | **Real problem.** A real run bumps the Job and leaves the databases behind | git (1) | | 3 | Bogus or out-of-policy majors | 5 branches: gitea 28.2.0, qbittorrent 20.04.1, radarr 6.x, nextcloud 35, postgresql 18.6 | Odd legacy tags, plus `update.range` in `catalog/` not being read by Renovate | Risk if run for real: unmergeable PRs, which hold slots | git (2) | | 4 | Auto-merge of the merge gate's own host | gitea 1.24.3→1.27.3, act_runner 0.2.11→0.6.1, both "minor" | Not in the blast-radius list. A 0.x minor is breaking by semver | **Risk if run for real** | git (3) | | 5 | Range widening auto-merged | external-dns, headlamp (minor); longhorn (blast radius); kube-prometheus-stack (major) | Renovate widens `>=a .yaml` + `apps/wave-*/.yaml`. - **The oauth2-proxy branch** carries `catalog/render.py` plus the 5 rendered apps and `platform/crafty`. - **The postgresql-16.x branch** carries all three Clusters. - The 2 flux docker duplicates report `disabled`. - **render==golden holds for the new branch shape.** - In the toolbox, I applied the gitea branch edit (catalog + apps) and the oauth2-proxy branch edit (`render.py` constant + 5 apps) textually. `./ci/render-golden.sh` reported `all 10 onboarded service golden(s) reproduce`, rc 0. - Negative control, the old shape with only `apps/wave-0/gitea.yaml` bumped: rc 1, `GOLDEN DRIFT`. - Both edits were reverted afterwards. ## What I did NOT verify - **The effect of the automerge, label and dashboard-approval rules (3, 4, 5, 8). UNVERIFIED in a run.** `--platform=local` stops before branch processing, so I saw only which updates exist, not their merged flags. The matchers are standard (`matchPackageNames`, `matchManagers`, `matchCurrentValue`, `matchUpdateTypes`). The next dispatch's debug log shows them per branch. - **`allowedVersions` under docker versioning** used Renovate's "Falling back to npm semver syntax" path (16 debug lines). That it filters is shown by the five removed branches. - **render==golden for the other app branches** (qbittorrent, radarr, sonarr, semaphore, seerr). I proved it only for gitea and oauth2-proxy. They have the same shape: one `source.image` line ↔ one rendered `image:` line. - **The `allowedVersions` rules duplicate `catalog/*/update.range`** and can drift from it. Nothing checks them against each other. A lint comparing the two is the obvious follow-up. - **Any real (non-dry) run.** None has happened. PR creation, labels, auto-merge through Gitea's API and the Dependency Dashboard issue are all unobserved. - **Sensitive path?** `renovate.json5` is not in `infra/gitea/approval-policy.json`, as far as I know. CI's `approval-policy` result on the PR is the measurement.