Files
homelab-design/decisions/0036-renovate-dependency-updates.md
Billy D. 51e6cee8ab
All checks were successful
Update README with ADR Index / update-readme (push) Successful in 6s
feat: ADR-0056 custom voice support, ADR-0057 Renovate per-repo configs
- ADR-0056: custom voice support in tts-module (VoiceRegistry)
- ADR-0057: shared Renovate preset rollout to all app repos
- Update ADR-0013: add tts-module and stt-module to CI table
- Update ADR-0036: cross-reference ADR-0057
2026-02-13 15:31:33 -05:00

258 lines
9.0 KiB
Markdown

# 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