# Automated Dependency Updates with Renovate * Status: accepted * Date: 2026-02-05 * Deciders: Billy * Technical Story: Automate dependency updates across all homelab repositories ## Context and Problem Statement The homelab consists of 20+ repositories containing: - Kubernetes manifests with container image references - Helm chart versions - Python/Go dependencies - GitHub Actions / Gitea Actions workflow versions Manually tracking and updating dependencies is: - Time-consuming - Error-prone - Often neglected until security issues arise How do we automate dependency updates while maintaining control over what gets updated? ## Decision Drivers * Automated detection of outdated dependencies * PR-based update workflow for review * Support for Kubernetes manifests, Helm, Python, Go, Docker * Self-hosted on existing infrastructure * Configurable grouping and scheduling * Security update prioritization ## Considered Options 1. **Renovate (self-hosted)** 2. **Dependabot (GitHub-native)** 3. **Manual updates with version scripts** 4. **Flux image automation** ## Decision Outcome Chosen option: **Option 1 - Renovate (self-hosted)** Renovate runs as a CronJob in the cluster, scanning all repositories in the Gitea organization and creating PRs for outdated dependencies. It supports more package managers than Dependabot and works with Gitea. ### Positive Consequences * Comprehensive manager support (40+ package managers) * Works with self-hosted Gitea * Configurable grouping (batch minor updates) * Auto-merge for patch/minor updates * Dashboard for update overview * Reusable preset configurations ### Negative Consequences * Additional CronJob to maintain * Configuration complexity * API token management for Gitea access ## Architecture ``` ┌───────────────────────────────────────────────────────────────────┐ │ Renovate CronJob │ │ (ci-cd namespace) │ │ │ │ Schedule: Every 8 hours (0 */8 * * *) │ │ │ │ ┌────────────────────────────────────────────────────────────┐ │ │ │ Renovate Container │ │ │ │ │ │ │ │ 1. Fetch repositories from Gitea org │ │ │ │ 2. Scan each repo for dependencies │ │ │ │ 3. Compare versions with upstream registries │ │ │ │ 4. Create/update PRs for outdated deps │ │ │ │ 5. Auto-merge approved patches │ │ │ └────────────────────────────────────────────────────────────┘ │ └───────────────────────────────────────────────────────────────────┘ │ ▼ ┌───────────────────────────────────────────────────────────────────┐ │ Gitea │ │ │ │ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ │ │ homelab-k8s2 │ │ chat-handler │ │ kuberay-images│ │ │ │ │ │ │ │ │ │ │ │ PR: Update │ │ PR: Update │ │ PR: Update │ │ │ │ flux to 2.5.0 │ │ httpx to 0.28 │ │ ROCm to 6.4 │ │ │ └───────────────┘ └───────────────┘ └───────────────┘ │ └───────────────────────────────────────────────────────────────────┘ ``` ## Configuration ### CronJob ```yaml apiVersion: batch/v1 kind: CronJob metadata: name: renovate namespace: ci-cd spec: schedule: "0 */8 * * *" # Every 8 hours jobTemplate: spec: template: spec: containers: - name: renovate image: renovate/renovate:39 env: - name: RENOVATE_PLATFORM value: "gitea" - name: RENOVATE_ENDPOINT value: "https://git.daviestechlabs.io/api/v1" - name: RENOVATE_TOKEN valueFrom: secretKeyRef: name: renovate-github-token key: token - name: RENOVATE_AUTODISCOVER value: "true" - name: RENOVATE_AUTODISCOVER_FILTER value: "daviestechlabs/*" restartPolicy: OnFailure ``` ### Repository Config (renovate.json) ```json { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ "config:recommended", "group:allNonMajor", ":automergeMinor", ":automergePatch" ], "kubernetes": { "fileMatch": ["\\.ya?ml$"] }, "packageRules": [ { "matchManagers": ["helm-values", "helmv3"], "groupName": "helm charts" }, { "matchPackagePatterns": ["^ghcr.io/"], "groupName": "GHCR images" }, { "matchUpdateTypes": ["major"], "automerge": false, "labels": ["major-update"] } ], "schedule": ["before 6am on monday"] } ``` ## Supported Package Managers | Manager | File Patterns | Examples | |---------|---------------|----------| | kubernetes | `*.yaml`, `*.yml` | Container images in Deployments | | helm | `Chart.yaml`, `values.yaml` | Helm chart dependencies | | helmv3 | HelmRelease CRDs | Flux HelmReleases | | flux | Flux CRDs | GitRepository, OCIRepository | | pip | `requirements.txt`, `pyproject.toml` | Python packages | | gomod | `go.mod` | Go modules | | dockerfile | `Dockerfile*` | Base images | | github-actions | `.github/workflows/*.yml` | Action versions | | gitea-actions | `.gitea/workflows/*.yml` | Action versions | ## Update Strategy ### Auto-merge Enabled | Update Type | Auto-merge | Delay | |-------------|------------|-------| | Patch (x.x.1 → x.x.2) | ✅ Yes | Immediate | | Minor (x.1.x → x.2.x) | ✅ Yes | 3 days stabilization | | Major (1.x.x → 2.x.x) | ❌ No | Manual review | ### Grouping Strategy | Group | Contents | Frequency | |-------|----------|-----------| | `all-non-major` | All patch + minor updates | Weekly (Monday) | | `helm-charts` | All Helm chart updates | Weekly | | `container-images` | Docker image updates | Weekly | | `security` | CVE fixes | Immediate | ## Security Updates Renovate prioritizes security updates: ```json { "vulnerabilityAlerts": { "enabled": true, "labels": ["security"] }, "packageRules": [ { "matchCategories": ["security"], "automerge": true, "schedule": ["at any time"], "prPriority": 10 } ] } ``` ## Dashboard Renovate creates a "Dependency Dashboard" issue in each repository: ```markdown ## Dependency Dashboard ### Open PRs - [ ] Update httpx to 0.28.1 (#42) - [x] Update pillow to 11.0.0 (#41) - merged ### Pending Approval - [ ] Major: Update pydantic to v2 (#40) ### Rate Limited - fastapi (waiting for next schedule window) ``` ## Secrets | Secret | Source | Purpose | |--------|--------|---------| | `renovate-github-token` | Vault | Gitea API access | | `renovate-dockerhub` | Vault | Docker Hub rate limits | ## Monitoring ```promql # Renovate job success rate sum(kube_job_status_succeeded{job_name=~"renovate-.*"}) / sum(kube_job_status_succeeded{job_name=~"renovate-.*"} + kube_job_status_failed{job_name=~"renovate-.*"}) ``` ## Links * [Renovate Documentation](https://docs.renovatebot.com/) * [Renovate Presets](https://docs.renovatebot.com/presets-default/) * [Gitea Platform Support](https://docs.renovatebot.com/modules/platform/gitea/) * Related: [ADR-0013](0013-gitea-actions-for-ci.md) - Gitea Actions for CI * Related: [ADR-0031](0031-gitea-cicd-strategy.md) - Gitea CI/CD Strategy * Extended by: [ADR-0057](0057-renovate-per-repo-configs.md) - Per-Repository Renovate Configurations