257 lines
8.9 KiB
Markdown
257 lines
8.9 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
|