Skip to main content

Renovate Reference

Companion to /platform-skills:renovate. Deep-dive on managers, presets, security, GitOps integration, private registries, custom regex managers, pre-commit hooks, and troubleshooting.


1. Manager Catalog​

ManagerFile patternsNotes
github-actions.github/workflows/*.ymlAlways pinDigests: true — commit SHA instead of tag
terraform*.tf, *.tfvarsCovers required_providers and module blocks
helmv3Chart.yaml, requirements.yamlHelm 3 chart dependencies
gomodgo.modGo module dependencies; use gomodTidy in postUpdateOptions
npmpackage.json, package-lock.json, yarn.lockNode packages; use npmDedupe in postUpdateOptions
pip_requirementsrequirements*.txtPinned Python packages
pip-compilerequirements*.inpip-tools input files
pipenvPipfile, Pipfile.lockPipenv-managed projects
poetrypyproject.toml (Poetry)Poetry-managed projects
dockerfileDockerfile, Dockerfile.*FROM image tags
docker-composedocker-compose*.ymlService image tags
kubernetesManifests with kind: Deployment/StatefulSet/DaemonSet/Job/CronJobContainer image tags in spec.containers[].image
cargoCargo.tomlRust crate dependencies
custom.regexAny file via managerFilePatternsCustom version strings — no native manager support

2. Preset Reference​

config:recommended includes:

PresetEffect
config:recommendedBase: semantic PR titles, dependency dashboard, labels, schedule
:dependencyDashboardCreates a GitHub Issue listing all pending/blocked updates
:semanticCommitsCommit messages follow Conventional Commits format
:separateMajorReleasesMajor version bumps get their own PR, never grouped

Useful add-ons:

PresetWhen to add
:pinDigestsGlobal digest pinning — prefer scoped to github-actions only
:automergeMinorAutomerge all minor updates — use only if CI is comprehensive
:automergeDigestAutomerge digest-only updates (no version change)
security:openssf-scorecardAdds OpenSSF Scorecard checks to PRs
helpers:pinGitHubActionDigestsShorthand for GitHub Actions digest pinning

3. Package Rules Patterns​

Automerge strategy by ecosystem​

EcosystemRecommended automergeReason
github-actionsNeverSHA pinning means every update is significant
terraform providersMinor + patchProviders are stable; breaking changes follow semver
terraform modulesNeverModule updates may change resource topology
helmv3Patch onlyCharts may have templating changes in minor
gomodMinor + patchGo semver is well-respected
npmMinor + patchWith minimumReleaseAge: "3 days" to avoid supply chain risk
pipMinor + patchSame — pin to minimumReleaseAge
docker/kubernetesNeverImage updates may include breaking app changes
cargoMinor + patchCargo semver is well-respected

Grouping recipes​

Group related updates into one PR to reduce noise:

{
"description": "Group all AWS provider updates",
"matchManagers": ["terraform"],
"matchPackageNames": ["hashicorp/aws"],
"groupName": "AWS provider"
},
{
"description": "Group all patch updates across ecosystems",
"matchUpdateTypes": ["patch"],
"matchCurrentVersion": "!/^0/",
"groupName": "Patch updates",
"automerge": true,
"minimumReleaseAge": "3 days"
}

Schedule recipes​

Weekly, low disruption:

{ "schedule": ["before 6am on monday"] }

Nightly, non-work hours:

{ "schedule": ["after 10pm every weekday"] }

Immediate (vulnerability alerts):

{ "schedule": ["at any time"] }

minimumReleaseAge for supply chain safety​

Always set on automerge rules to prevent typosquatting and freshly-published malicious packages:

{
"matchUpdateTypes": ["minor", "patch"],
"automerge": true,
"minimumReleaseAge": "3 days"
}

4. Dependency Dashboard​

Renovate creates a GitHub Issue titled "Renovate Dependency Dashboard" when dependencyDashboard: true.

What it shows:

  • All pending updates grouped by status (Awaiting Schedule / Open PRs / Rate-limited / Ignored)
  • Checkboxes to trigger individual updates on-demand

How to trigger a selective update:

  1. Open the Dependency Dashboard issue
  2. Check the box next to the package you want updated now
  3. Save the issue — Renovate detects the change within minutes and creates the PR

How to find the dashboard:

gh issue list --label "renovate" --state open

Resetting the dashboard: Close and reopen the issue — Renovate recreates it on the next run.

Enable explicitly (already in config:recommended but good to be explicit):

{
"dependencyDashboard": true,
"dependencyDashboardTitle": "Renovate Dependency Dashboard"
}

5. GitOps Integration​

Renovate vs Flux Image Reflector Controller​

Both can update container image references. Running both on the same files causes conflicts.

Recommended split:

ResponsibilityOwner
Helm chart versions in HelmReleaseRenovate (helmv3 manager)
Terraform provider/module versionsRenovate (terraform manager)
Language dep versions (go.mod, package.json)Renovate
GitHub Actions versionsRenovate (github-actions manager)
Running workload image tags (Deployment/StatefulSet)Flux Image Reflector Controller
OCI artifact digest pinning in FluxInstanceFlux (ImagePolicy)

Rule: Renovate owns anything in source control that follows semver. Flux Image Reflector owns runtime image tags for deployed workloads where you want continuous delivery without a PR.

Avoiding conflicts:

If Flux Image Reflector manages spec.containers[].image in a manifest, exclude that manifest from Renovate:

{
"ignorePaths": [
"clusters/**",
"flux-system/**"
]
}

Or scope the kubernetes manager to only non-Flux paths:

{
"matchManagers": ["kubernetes"],
"matchPaths": ["apps/**", "workloads/**"],
"automerge": false
}

6. Security Hardening​

Digest pinning for GitHub Actions​

{
"matchManagers": ["github-actions"],
"pinDigests": true
}

This converts uses: actions/checkout@v4 → uses: actions/checkout@<sha> # v4.x.x, making the action tamper-proof.

OSV vulnerability alerts​

{
"osvVulnerabilityAlerts": true,
"vulnerabilityAlerts": {
"enabled": true,
"labels": ["security"],
"schedule": ["at any time"]
}
}

osvVulnerabilityAlerts uses the OSV database (broader coverage than GitHub Advisory Database).

minimumReleaseAge — supply chain defence​

Prevents automerging packages published less than N days ago, reducing exposure to typosquatting and fast-follow malicious releases:

{
"matchUpdateTypes": ["minor", "patch"],
"automerge": true,
"minimumReleaseAge": "3 days"
}

rangeStrategy: pin​

Pin exact versions instead of ranges for reproducibility:

{
"matchManagers": ["npm"],
"rangeStrategy": "pin"
}

Use "bump" instead if the project publishes a library (ranges in peerDependencies must stay flexible).

Private registry auth​

{
"hostRules": [
{
"matchHost": "ghcr.io",
"username": "{{ secrets.GHCR_USERNAME }}",
"password": "{{ secrets.GHCR_TOKEN }}"
}
]
}

Store secrets in Renovate's encrypted secrets (Mend Renovate App) or as env vars when self-hosted.


7. Regex Managers​

Use customManagers (customType: "regex") when no native manager supports the file format.

Terraform version in GitHub Actions workflows​

{
"customManagers": [
{
"customType": "regex",
"description": "Track Terraform CLI version in workflow YAML",
"managerFilePatterns": ["/^\\.github/workflows/.*\\.ya?ml$/"],
"matchStrings": [
"terraform_version:\\s*['\"]?(?<currentValue>[^'\"\\s]+)['\"]?"
],
"depNameTemplate": "hashicorp/terraform",
"datasourceTemplate": "github-releases",
"extractVersionTemplate": "^v(?<version>.*)$"
}
]
}

Tool version in shell scripts​

{
"customManagers": [
{
"customType": "regex",
"description": "Track kubectl version in install scripts",
"managerFilePatterns": ["/scripts/.*\\.sh$/"],
"matchStrings": [
"KUBECTL_VERSION=['\"]?(?<currentValue>[^'\"\\s]+)['\"]?"
],
"depNameTemplate": "kubernetes/kubernetes",
"datasourceTemplate": "github-releases",
"extractVersionTemplate": "^v(?<version>.*)$"
}
]
}

Flux version in documentation​

{
"customManagers": [
{
"customType": "regex",
"description": "Track Flux CLI version in docs",
"managerFilePatterns": ["/^docs/.*\\.md$/", "/^examples/.*\\.md$/"],
"matchStrings": [
"Flux CLI \\((?<currentValue>[^)]+)\\)"
],
"depNameTemplate": "fluxcd/flux2",
"datasourceTemplate": "github-releases",
"extractVersionTemplate": "^v(?<version>.*)$"
}
]
}

8. Troubleshooting​

renovate-config-validator errors​

ErrorCauseFix
Invalid preset: config:baseDeprecated presetChange to config:recommended
matchManagers must be arrayScalar instead of array"matchManagers": ["terraform"] not "matchManagers": "terraform"
Unknown option: pinDigestTypo — missing sUse pinDigests (plural)
extends: invalidPreset not foundCheck preset name at docs.renovatebot.com/presets

Coverage scan false positives​

The /platform-skills:renovate workflow coverage scan checks for manager name strings in renovate.json. False positives occur when:

  • A file type is present but intentionally excluded via ignorePaths
  • A monorepo subdirectory is managed by a separate renovate.json

Suppress by adding the path to ignorePaths and noting it in the description field of the relevant packageRule.

Rate limiting​

Renovate enforces prConcurrentLimit (open PRs at once) and prHourlyLimit (PRs per hour). If updates are being skipped:

{
"prConcurrentLimit": 10,
"prHourlyLimit": 0
}

Set prHourlyLimit: 0 to disable hourly cap entirely (use with caution on large repos).

Dependency Dashboard not appearing​

  1. Confirm "dependencyDashboard": true is in renovate.json
  2. Check that the Renovate App has Issues write permission on the repo
  3. Trigger a manual run via the App settings or by pushing a trivial change

9. Private Registries​

Renovate uses hostRules to authenticate with private registries. Credentials are injected at runtime via env-var templating — they never appear in renovate.json in plaintext.

AWS ECR​

{
"hostRules": [
{
"matchHost": "123456789012.dkr.ecr.us-east-1.amazonaws.com",
"hostType": "docker",
"username": "AWS",
"password": "{{ env.AWS_ECR_TOKEN }}"
}
]
}

Pre-authenticate on self-hosted Renovate:

export AWS_ECR_TOKEN=$(aws ecr get-login-password --region us-east-1)

Recommended for Renovate App: attach an IAM role to the Renovate App installation and use the built-in ECR credential helper — no static token needed.

Google GCR / Artifact Registry​

{
"hostRules": [
{
"matchHost": "gcr.io",
"hostType": "docker",
"username": "_json_key",
"password": "{{ env.GCR_SERVICE_ACCOUNT_KEY }}"
}
]
}

For Artifact Registry replace gcr.io with <region>-docker.pkg.dev.

Azure ACR​

{
"hostRules": [
{
"matchHost": "myregistry.azurecr.io",
"hostType": "docker",
"username": "{{ env.ACR_CLIENT_ID }}",
"password": "{{ env.ACR_CLIENT_SECRET }}"
}
]
}

Use a service principal with the AcrPull role. Set ACR_CLIENT_ID and ACR_CLIENT_SECRET in the Renovate App environment or self-hosted runner secrets.

Harbor / self-hosted​

{
"hostRules": [
{
"matchHost": "registry.example.com",
"hostType": "docker",
"username": "{{ env.REGISTRY_USERNAME }}",
"password": "{{ env.REGISTRY_PASSWORD }}"
}
]
}

Private Helm — OCI registry​

{
"hostRules": [
{
"matchHost": "registry.example.com",
"hostType": "docker",
"username": "{{ env.HELM_REGISTRY_USERNAME }}",
"password": "{{ env.HELM_REGISTRY_PASSWORD }}"
}
],
"packageRules": [
{
"matchManagers": ["helmv3"],
"registryUrls": ["oci://registry.example.com"],
"groupName": "Private Helm charts (OCI)"
}
]
}

Private Helm — HTTP registry​

{
"hostRules": [
{
"matchHost": "charts.example.com",
"username": "{{ env.HELM_REGISTRY_USERNAME }}",
"password": "{{ env.HELM_REGISTRY_PASSWORD }}"
}
],
"packageRules": [
{
"matchManagers": ["helmv3"],
"registryUrls": ["https://charts.example.com"],
"groupName": "Private Helm charts (HTTP)"
}
]
}

Private Terraform registry​

Module sources of the form <hostname>/<namespace>/<module>/<provider> with a version = "..." attribute are handled natively by the terraform manager for any hostname (not just registry.terraform.io) via the terraform-module datasource — no custom manager needed. Add a hostRules entry for authentication:

{
"hostRules": [
{
"matchHost": "app.terraform.io",
"token": "{{ env.TF_REGISTRY_TOKEN }}"
}
]
}

Set TF_REGISTRY_TOKEN to a Terraform Cloud team token with read access.

Internal GitHub org Terraform modules​

Module sources of the form github.com/<org>/<repo>//<path>?ref=<tag> are also handled natively by the terraform manager, under the github-tags datasource with packageName set to <org>/<repo> — no custom manager needed. Use packageRules to group and gate them:

{
"packageRules": [
{
"matchManagers": ["terraform"],
"matchPackageNames": ["/^myorg\\//"],
"automerge": false,
"groupName": "Internal Terraform modules (myorg)"
}
]
}

Replace myorg with your GitHub org. Renovate will open PRs that update ?ref=v1.2.3 to the latest tag on the referenced repo.


10. Custom Regex Managers​

Use customManagers (customType: "regex") when a dependency version appears in a file format that Renovate's built-in managers do not parse — pinned tool versions in scripts, or version strings in YAML/JSON config files. regexManagers and fileMatch are deprecated aliases for customManagers/managerFilePatterns — Renovate auto-migrates them with a WARN, but write new configs with the current keys directly. managerFilePatterns treats bare strings as globs; existing regex patterns must be wrapped in /.../ delimiters.

Terraform version pinned in GitHub Actions workflows​

{
"customManagers": [
{
"customType": "regex",
"description": "Update Terraform version pinned in GitHub Actions workflows",
"managerFilePatterns": ["/^\\.github/workflows/.*\\.ya?ml$/"],
"matchStrings": [
"terraform_version:\\s*['\"]?(?<currentValue>[^'\"\\s]+)['\"]?"
],
"depNameTemplate": "hashicorp/terraform",
"datasourceTemplate": "github-releases",
"extractVersionTemplate": "^v(?<version>.*)$"
}
]
}

Tool versions in .tool-versions (asdf)​

{
"customManagers": [
{
"customType": "regex",
"description": "Update tools pinned in .tool-versions (asdf)",
"managerFilePatterns": ["/^\\.tool-versions$/"],
"matchStrings": [
"(?<depName>[a-z0-9_-]+)\\s+(?<currentValue>[\\d\\.]+)"
],
"datasourceTemplate": "github-releases",
"packageNameTemplate": "asdf-vm/asdf-{{{depName}}}"
}
]
}

kubectl version in CI scripts​

{
"customManagers": [
{
"customType": "regex",
"description": "Update kubectl version pinned in CI scripts",
"managerFilePatterns": ["/^\\.github/workflows/.*\\.ya?ml$/", "/^scripts/.*\\.sh$/"],
"matchStrings": [
"kubectl_version[=:]\\s*['\"]?v?(?<currentValue>[\\d\\.]+)['\"]?"
],
"depNameTemplate": "kubernetes/kubectl",
"datasourceTemplate": "github-releases",
"extractVersionTemplate": "^v(?<version>.*)$"
}
]
}

Debugging regex managers​

Test your matchStrings pattern against actual file content:

# Install renovate locally
npm install -g renovate

# Dry-run against a single file — prints what Renovate would extract
LOG_LEVEL=debug renovate --dry-run --print-config 2>&1 | grep -A5 "customManagers"

Common mistakes:

  • Forgetting to double-escape backslashes in JSON strings (\\s not \s)
  • Using (?<version>) instead of (?<currentValue>) — the named capture must be currentValue
  • Missing datasourceTemplate — required when there is no built-in datasource inference

11. Pre-commit Hook​

Run renovate-config-validator locally before every commit using the official pre-commit hook. This catches config errors before they reach CI.

Setup​

Add to .pre-commit-config.yaml (create the file if it does not exist):

repos:
- repo: https://github.com/renovatebot/pre-commit-hooks
rev: 43.150.0
hooks:
- id: renovate-config-validator

Install and activate:

pip install pre-commit # or: brew install pre-commit
pre-commit install
pre-commit run renovate-config-validator --all-files

Keeping the rev up to date​

The rev pin tracks the Renovate release version. Once Renovate is running on the repo, it updates the rev automatically via a PR — the same way it updates any other dependency. No manual maintenance needed.

To pin with the digest for maximum supply chain security:

pre-commit autoupdate --freeze

This replaces the semver tag with the commit SHA:

rev: 43.150.0 # frozen: sha256:<digest>

Skipping the hook for a single commit​

SKIP=renovate-config-validator git commit -m "wip: draft config"