ADR-0033: Consolidate dependency automation on Renovate¶
| Field | Value |
|---|---|
| Status | Accepted |
| Date | 2026-06-14 |
| Authors | Roman Mednitzer |
Context¶
Two bots were raising dependency PRs against this repository. Renovate ran from a
bare renovate.json (extends: ["config:recommended"]) and GitHub's repo-level
Dependabot security updates raised their own PRs for the same advisories. There
was no .github/dependabot.yml — Dependabot version updates were never configured —
so the overlap was confined to security updates, but it was real: the cryptography
v46 advisory produced a duplicate pair (Renovate #55 and Dependabot #54) for one fix.
The bare Renovate config also did not maintain the uv-compiled, hashed
requirements-dev.txt lock the way this repository needs. The lock's autogenerated
header recorded the short -o output flag, which Renovate's pip-compile manager
option allowlist rejects, so Renovate skipped the lock; #55's bump landed incomplete
in the dev extra and needed the #57 follow-up. Separately, the container-image build
work (ADR-0032) added a Dockerfile with a digest-pinned base image, a new ecosystem
that should be kept current by the same single tool.
The rest of the fleet standardised on a single dependency-automation tool. This repository was the lone two-bot configuration for security updates and carried an unconfigured Renovate.
Decision¶
-
Renovate is the single dependency-automation tool.
renovate.jsonis replaced by a curatedrenovate.json5extendingconfig:best-practices, with semantic commits, theEurope/Viennatimezone, adependencieslabel, andrmednitzeras reviewer.enabledManagersis restricted to the three ecosystems in use:github-actions,dockerfile, andpip-compile. The list is load-bearing — a manager that overlapped a re-introduceddependabot.ymlwould resurrect duplicate PRs. -
The hashed-lock invariant is preserved and made Renovate-maintainable.
requirements-dev.txtis auv pip compile pyproject.toml --extra dev --generate-hashes --universallock. Its header is normalised from the short-oto the long-form--output-file requirements-dev.txt, because Renovate'suvoption allowlist rejects-oand would otherwise skip the lock. Renovate'spip-compilemanager replays the recorded command, regenerating a universal, fully-hashed lock on each update. Amake locktarget records the canonical command so local regenerations keep the long form. The locked pins and hashes are unchanged by this ADR.pip-compileupdates requireuvin the Renovate runtime (present in the Mend-hosted app; ensure it on any self-hosted runner). -
Action and base-image digest pinning are preserved.
pinDigests: truewithconfig:best-practiceskeeps GitHub Actions and theDockerfilebase image digest-pinned (ADR-0032's posture, maintained by Renovate). Minor/patch/digest action updates are grouped, majors stay individual; Actions are scheduled Monday, the Dockerfile and the pip lock Wednesday (Europe/Vienna). -
Dependabot security updates are turned off; alerts stay on. GitHub's repo-level Dependabot security updates (the auto-PRs) are disabled, ending the duplicate security PRs. Dependabot vulnerability alerts (detection, surfaced in the Security tab) remain enabled: Renovate reads them and raises the fix PRs through its own vulnerability handling, so security coverage is unchanged and single-sourced.
Consequences¶
Positive
- One tool, one config (
renovate.json5), one PR-author identity for version and security updates across Actions, the Dockerfile, and the Python lock. The #54/#55-class duplicate is removed at the source. - The dev lock is maintained by Renovate with the hash-regeneration discipline the
repository already documents, rather than by a second bot — and the
-oskip that left #55 incomplete is fixed. - The dependency-automation story matches the rest of the fleet.
Negative / accepted trade-offs
- Renovate's
pip-compilemanager depends onuvin the runtime; a self-hosted Renovate withoutuvwould silently stop maintaining the lock. Mitigation: documented here, inrenovate.json5, and in themake locktarget; the Mend-hosted app shipsuv. - Security-fix PRs now come only from Renovate. The GitHub-native Dependabot security update path is no longer a redundant second source; the Dependabot alert feed is kept, so detection is unchanged and only the duplicate PR creation is removed.
Neutral
- The repository's own image (
deploy/helm/praxis/values.yaml) is set at deploy time, not a third-party dependency, so nohelm-valuesmanager is enabled; theDockerfilebase image it builds from is covered by thedockerfilemanager.
Alternatives considered and rejected¶
- Keep both bots (mirror only the version-update retirement). Rejected: it leaves the security-update overlap that produced #54/#55 in place.
- Disable Renovate's vulnerability handling and keep Dependabot for security. Rejected: it splits the automation across two tools and two configs again — the cost this ADR removes — when Renovate already maintains the lock and can raise the security PR.
- Leave Renovate on the bare
config:recommended. Rejected: it skips the-olock (the #55/#57 cause) and carries none of the grouping, scheduling, labelling, or digest discipline the rest of the fleet uses.
Revisit triggers¶
- A new ecosystem enters the repository (e.g. a runtime lock or Helm chart dependencies): add the matching Renovate manager rather than a second bot.
- Renovate's
uv/pip-compileoption allowlist changes such that the recorded command form must change again. - A published
ghcr.io/rmednitzer/praxisimage with a tracked digest would justify a scopedhelm-valuesmanager.