Renovate for Automated Dependency Updates¶
Einordnung ins Overtime-Projekt
Die Overtime-Codebasis hat mehrere Abhängigkeits-Oberflächen – Python-Pakete, Container-Base-Images und in CI-Pipelines gepinnte Tool-Versionen. Dieses ADR beschreibt, wie Renovate diese automatisiert aktuell hält, ohne dass Updates unbeobachtet einfließen.
1. Kontext & Problemstellung (Deutsch)¶
Das fiktive B2B-Kollaborations-Projekt Overtime basiert auf einem Python/Django-Backend und verschiedenen Microservices, die in gehärteten K3s-Clustern betrieben werden. Die Plattform hat drei unterschiedliche Abhängigkeits-Oberflächen, die regelmäßig aktualisiert werden müssen:
- Python-Pakete – definiert in
pyproject.tomlbzw.uv.lock(z. B. Django, Gunicorn, structlog). - Container-Base-Images – definiert über
ARG-Direktiven in den Dockerfiles (z. B.[registry.suse.com/bci/python:3.14-micro](https://registry.suse.com/bci/python:3.14-micro)). - CI-Tool-Versionen – inline gepinnt in den YAML-Dateien der Pipelines (z. B. Trivy, Buildah, Semgrep, uv, Kustomize).
Ohne Automatisierung veralten diese Abhängigkeiten unbemerkt ("Configuration Drift"). Eine einzelne, nicht gepatchte Abhängigkeit ist eine häufige Ursache für Supply-Chain-Vorfälle. Manuelle Update-Zyklen über mehrere Repositories hinweg sind zudem langsam und fehleranfällig.
2. Architecture Decision Record (English)¶
ADR-007: Renovate for Automated Dependency Updates¶
Status¶
Accepted
Context and Problem Statement¶
The stack relies on three distinct dependency surfaces that require regular updates: Python packages, container base images, and CI tool versions. Without automation, these drift silently, and manual update rounds are slow and error-prone across multiple repositories. A reliable system is needed to track and remediate vulnerabilities in a timely manner.
Decision Drivers¶
- Observability: Updates must be proposed as Merge Requests (MRs) so they are observable and reviewable, rather than being silently applied.
- Urgency for Vulnerabilities: Vulnerability-flagged updates must arrive immediately (0-day stability wait).
- Controlled Automation: Major version bumps (e.g., Django, Python) require human review, while minor and patch updates can automerge if CI tests pass.
- Custom Parsing: CI tool version pins reside in non-standard YAML variables, requiring custom regex manager support.
Considered Options¶
- Dependabot — Native GitHub integration, but lacks cross-repo configuration sharing and has limited support for custom package managers.
- Manual update process — Ad-hoc, lacks an audit trail, and is highly unreliable at scale.
- Renovate — Highly configurable, natively supports regex custom managers, is self-hostable, and provides strong GitLab support.
Decision Outcome¶
Chosen: Renovate.
Renovate seemed the most configurable and versatile. I implement Renovate using specific renovate.json configurations per repository. The configuration extends standard best practices and explicitly pins Docker digests (config:best-practices, docker:pinDigests). Renovate also created a nice dashboard in the repositories where one can see the state of things.
I did not check Dependabot in depth so it might be a viable option especially if on GitHub, where it has native integration.
Consequences & Trade-offs¶
Positive Consequences¶
- Automated Quality Gating: Every dependency update generates an MR accompanied by a CI pipeline run, ensuring no change is applied without tests passing.
- Rapid Security Patching: Vulnerability patches arrive within hours (0-day stability) and automerge once CI passes.
- Cooldown Periods Many Supply-Chain attacks were discovered within the first week, so I want to introduce a cooldown period for non-critical updates. See this Datadog blog post for more info.
- Supply Chain Hardening: The
docker:pinDigestspreset locks Docker images to SHA-256 digests in addition to tags, preventing malicious tag mutation attacks.
Negative Consequences / Trade-offs¶
- Token Management: Renovate requires a GitLab token with API and write permissions to repositories, which introduces a secret that must be securely rotated.
- Immediate Downstream Impact: Because Renovate acts on the
overtime-ci-templatesrepository, automerged changes to CI templates immediately affect all consuming service pipelines. This mandates highly reliable CI tests in the template repository.
3. Pipeline Implementation & Code Snippet (English)¶
The implementation consists of two parts: the CI runner job executing Renovate (housed in the central templates repository) and the specific renovate.json rules defined in the downstream service (e.g., the Django backend).
CI/CD Pipeline Template (.gitlab-ci.yml)¶
The following job definition resides in overtime-ci-templates/.gitlab-ci.yml. It ensures Renovate runs securely within an ephemeral container via schedule or manual web triggers.
renovate:
stage: renovate
image: renovate/renovate:42@sha256:55257c9f54eff5382abacb0a119ba2357566cb01cdbf0a35f152e24729ab8e64
variables:
LOG_LEVEL: info
RENOVATE_CONFIG_FILE: renovate/config.js
# Required CI/CD variables (set in GitLab project Settings → CI/CD → Variables):
# RENOVATE_TOKEN — GitLab token with api + write_repository scopes
# GITHUB_COM_TOKEN — GitHub PAT (read-only) to avoid rate limits on changelog fetching
script:
- renovate
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
- if: '$CI_PIPELINE_SOURCE == "web"'
Dependency Configuration (renovate.json)¶
The following configuration is deployed in /overtime-django-backend/renovate.json. It translates the decision drivers into actionable rules: pinning digests, automerging minor/patch updates, and strictly requiring human approval for major upgrades.
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:best-practices",
"docker:pinDigests"
],
"minimumReleaseAge": "14 days",
"vulnerabilityAlerts": {
"enabled": true,
"minimumReleaseAge": null,
"automerge": true
},
"packageRules": [
{
"description": "DHI images maintain exact semantic versioning rules",
"matchPackageNames": [
"dhi.io/**"
],
"versioning": "docker"
},
{
"description": "Automerge minor and patch updates for app code & base images",
"matchUpdateTypes": [
"minor",
"patch"
],
"automerge": true,
"automergeType": "branch"
},
{
"description": "Strictly require manual review for major updates (e.g. Django/Python upgrades)",
"matchUpdateTypes": [
"major"
],
"automerge": false
},
{
"description": "Never pin digests for the CI templates repo, rely on tags.",
"matchPackageNames": [
"alexb-overtime/overtime-ci-templates"
],
"pinDigests": false
}
]
}
4. Compliance Einordnung (Deutsch)¶
Das detaillierte Mapping auf BSI IT-Grundschutz, CRA und CIS Benchmarks wird in später ergänzt.