diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 497d0b25..5c29d669 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -2,10 +2,10 @@ version: 2 updates: - package-ecosystem: uv + open-pull-requests-limit: 0 directory: / schedule: interval: monthly - open-pull-requests-limit: 20 groups: uv-dependencies: applies-to: version-updates @@ -19,6 +19,7 @@ updates: - worgarside - package-ecosystem: github-actions + open-pull-requests-limit: 0 directory: / schedule: interval: monthly @@ -26,6 +27,7 @@ updates: - worgarside - package-ecosystem: npm + open-pull-requests-limit: 0 directory: / schedule: interval: monthly diff --git a/.github/workflows/_auto-create-pr.yml b/.github/workflows/_auto-create-pr.yml index e944cdc2..e223e006 100644 --- a/.github/workflows/_auto-create-pr.yml +++ b/.github/workflows/_auto-create-pr.yml @@ -6,6 +6,7 @@ on: branches-ignore: - main - dependabot/** + - renovate/** workflow_dispatch: jobs: diff --git a/.github/workflows/_set-pr-auto-merge.yml b/.github/workflows/_set-pr-auto-merge.yml index f2153d58..cc14cab6 100644 --- a/.github/workflows/_set-pr-auto-merge.yml +++ b/.github/workflows/_set-pr-auto-merge.yml @@ -15,7 +15,9 @@ concurrency: jobs: set-auto-merge: name: Set PR Auto Merge - if: ${{ !github.event.pull_request.draft }} + if: >- + !github.event.pull_request.draft && + !startsWith(github.head_ref, 'renovate/') uses: ./.github/workflows/__set-pr-auto-merge.yml with: head-ref: ${{ github.head_ref }} diff --git a/.gitignore b/.gitignore index d4e2647b..531abfcc 100644 --- a/.gitignore +++ b/.gitignore @@ -344,3 +344,7 @@ custom_components resources/gh_cli/ .github_token + +# Renovate repository policy +!/renovate.json +!/renovate-default.json diff --git a/README.md b/README.md index 6dd6a7ce..7acc595d 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ to contributors. |-------------|--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|--------|--------| | **.github/CODEOWNERS** | [.github/CODEOWNERS](.github/CODEOWNERS) | [.github/CODEOWNERS](.github/CODEOWNERS) | | [.github/CODEOWNERS](.github/CODEOWNERS) | [.github/CODEOWNERS](.github/CODEOWNERS) | [.github/CODEOWNERS](.github/CODEOWNERS) | [.github/CODEOWNERS](.github/CODEOWNERS) | | [.github/CODEOWNERS](.github/CODEOWNERS) | [.github/CODEOWNERS](.github/CODEOWNERS) | [.github/CODEOWNERS](.github/CODEOWNERS) | [.github/CODEOWNERS](.github/CODEOWNERS) | [.github/CODEOWNERS](.github/CODEOWNERS) | [.github/CODEOWNERS](.github/CODEOWNERS) | [.github/CODEOWNERS](.github/CODEOWNERS) | | **.github/actionlint.yaml** | [.github/actionlint.yaml](.github/actionlint.yaml) | [.github/actionlint.yaml](.github/actionlint.yaml) | | [.github/actionlint.yaml](.github/actionlint.yaml) | [.github/actionlint.yaml](.github/actionlint.yaml) | [.github/actionlint.yaml](.github/actionlint.yaml) | [.github/actionlint.yaml](.github/actionlint.yaml) | | [.github/actionlint.yaml](.github/actionlint.yaml) | [.github/actionlint.yaml](.github/actionlint.yaml) | [.github/actionlint.yaml](.github/actionlint.yaml) | [.github/actionlint.yaml](.github/actionlint.yaml) | [.github/actionlint.yaml](.github/actionlint.yaml) | [.github/actionlint.yaml](.github/actionlint.yaml) | [.github/actionlint.yaml](.github/actionlint.yaml) | -| **.github/dependabot.yml** | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | +| **.github/dependabot.yml** | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](.github/dependabot.yml) | [gha_sync/configs/dependabot.yml](gha_sync/configs/dependabot.yml) | | **.github/labeler.yml** | [.github/labeler.yml](.github/labeler.yml) | [.github/labeler.yml](.github/labeler.yml) | | [.github/labeler.yml](.github/labeler.yml) | | [.github/labeler.yml](.github/labeler.yml) | [.github/labeler.yml](.github/labeler.yml) | | [.github/labeler.yml](.github/labeler.yml) | [.github/labeler.yml](.github/labeler.yml) | [.github/labeler.yml](.github/labeler.yml) | [.github/labeler.yml](.github/labeler.yml) | [.github/labeler.yml](.github/labeler.yml) | [.github/labeler.yml](.github/labeler.yml) | [.github/labeler.yml](.github/labeler.yml) | | **.github/release-drafter.yml** | | | | | | | | | | | [gha_sync/configs/release-drafter.yml](gha_sync/configs/release-drafter.yml) | [gha_sync/configs/release-drafter.yml](gha_sync/configs/release-drafter.yml) | | | [gha_sync/configs/release-drafter.yml](gha_sync/configs/release-drafter.yml) | | **.github/repo_labels.yml** | [.github/repo_labels.yml](.github/repo_labels.yml) | [.github/repo_labels.yml](.github/repo_labels.yml) | | [.github/repo_labels.yml](.github/repo_labels.yml) | | [.github/repo_labels.yml](.github/repo_labels.yml) | [.github/repo_labels.yml](.github/repo_labels.yml) | | [.github/repo_labels.yml](.github/repo_labels.yml) | [.github/repo_labels.yml](.github/repo_labels.yml) | [.github/repo_labels.yml](.github/repo_labels.yml) | [.github/repo_labels.yml](.github/repo_labels.yml) | [.github/repo_labels.yml](.github/repo_labels.yml) | [.github/repo_labels.yml](.github/repo_labels.yml) | [.github/repo_labels.yml](.github/repo_labels.yml) | @@ -329,10 +329,10 @@ to contributors. |--------|-------------| | [.github/CODEOWNERS](.github/CODEOWNERS) | [.github/CODEOWNERS](https://github.com/worgarside/python-template/.github/CODEOWNERS) | | [.github/actionlint.yaml](.github/actionlint.yaml) | [.github/actionlint.yaml](https://github.com/worgarside/python-template/.github/actionlint.yaml) | -| [.github/dependabot.yml](.github/dependabot.yml) | [.github/dependabot.yml](https://github.com/worgarside/python-template/.github/dependabot.yml) | | [.github/labeler.yml](.github/labeler.yml) | [.github/labeler.yml](https://github.com/worgarside/python-template/.github/labeler.yml) | | [.github/repo_labels.yml](.github/repo_labels.yml) | [.github/repo_labels.yml](https://github.com/worgarside/python-template/.github/repo_labels.yml) | | [.yamllint](.yamllint) | [.yamllint](https://github.com/worgarside/python-template/.yamllint) | +| [gha_sync/configs/dependabot.yml](gha_sync/configs/dependabot.yml) | [.github/dependabot.yml](https://github.com/worgarside/python-template/.github/dependabot.yml) | | [gha_sync/configs/release-drafter.yml](gha_sync/configs/release-drafter.yml) | [.github/release-drafter.yml](https://github.com/worgarside/python-template/.github/release-drafter.yml) | | [gha_sync/workflows/all/auto-create-pr.yml](gha_sync/workflows/all/auto-create-pr.yml) | [.github/workflows/auto-create-pr.yml](https://github.com/worgarside/python-template/.github/workflows/auto-create-pr.yml) | | [gha_sync/workflows/all/manage-pr.yml](gha_sync/workflows/all/manage-pr.yml) | [.github/workflows/manage-pr.yml](https://github.com/worgarside/python-template/.github/workflows/manage-pr.yml) | @@ -417,7 +417,7 @@ BL[["Test"]] BO[["Unit Tests"]] BR("Auto-Create PR") BS{{"PUSH -Branches Ignore: dependabot/**, main +Branches Ignore: dependabot/**, main, renovate/** "}} BV("Manage PR") BW{{"PULL REQUEST diff --git a/docs/renovate.md b/docs/renovate.md new file mode 100644 index 00000000..f1cf6cc6 --- /dev/null +++ b/docs/renovate.md @@ -0,0 +1,76 @@ +# Renovate dependency updates + +The shared policy lives in `renovate-default.json` in this repository. Each +consumer extends `github>worganisation/github-config-files:renovate-default` +in its `renovate.json`; repository-specific overrides stay in that consumer. +Policy changes take effect from this repository's default branch without +copying the policy into each consumer. The Mend Renovate +GitHub App must have access to each repository, and the configuration must be +on its default branch. The app is available at +. + +## Policy + +- Routine update branches are created on Mondays between 00:00 and 06:59 in + `Europe/London`, subject to the hosted app's execution schedule. +- Each repository has at most three concurrent update PRs, with one new PR per + hour. Security updates may bypass Renovate's normal scheduling and limits. +- Major updates require approval in the Dependency Dashboard before a PR opens. +- Updates request review from `worgarside`; Renovate does not enable auto-merge. +- Routine GitHub Actions updates are grouped and action references are pinned + to commit digests. Shared `github-config-files` workflow references remain + owned by the release-driven sync workflow. Other managers use Renovate's + recommended grouping. +- Pre-commit/prek hook updates remain owned by the existing hook auto-update + workflows. Renovate's pre-commit manager is explicitly disabled. +- Dependabot configurations with `open-pull-requests-limit: 0` retain security + updates but do not create scheduled version-update PRs. Existing open PRs + still need individual review. + +The shared auto-create-PR workflow ignores `renovate/**`, allowing Renovate to +own its PR titles and bodies. Shared auto-merge callers exclude those branches. +The sync configuration retains normal Dependabot version updates for repositories +outside the Renovate rollout. + +## Repository coverage + +All active `worganisation` repositories participate, including `vaultpi`. +`dockarr` is the repository for the Compose applications. + +Built-in managers discover supported GitHub Actions, Python manifests and lock +files, Dockerfiles, Compose files, Ansible dependencies, and OpenTofu providers. +Discovery does not imply that arbitrary versions embedded in shell scripts, +Ansible variables, Jinja templates, or device YAML are managed. Floating image +tags are not converted to pinned application versions by this configuration. + +Home Assistant's vendored custom integrations and storage-dashboard exports are +excluded. Tdarr server and node updates are grouped. Infrastructure provider +updates use the OpenTofu registry and require dashboard approval; the Terraform +manager does not change the OpenTofu runtime constraint. Infrastructure deployment +and recovery approvals remain separate from dependency PR review. + +## Adding a repository + +Grant the Renovate app access to the repository and add this `renovate.json`: + +```json +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": ["github>worganisation/github-config-files:renovate-default"] +} +``` + +No central allowlist is required for the hosted app. If installed for all +organization repositories, app access also covers newly created repositories. +Keep local overrides beside `extends`, exclude `renovate/**` from any generic +PR creator and auto-merge workflow, and set existing Dependabot version-update +limits to zero. Retain the separate hook updater. For repositories managed by +GCF file sync, use the same Renovate-compatible workflow and Dependabot sources. + +## Validation and activation + +Run `renovate-config-validator --strict renovate.json` inside a repository. +A local `renovate --platform=local --dry-run=extract` checks discovery without +opening PRs. Review the Dependency Dashboard and hosted app logs after activation +for private-package access or lockfile-generation errors. Passing configuration +validation does not prove hosted registry access or successful lockfile updates. diff --git a/gha_sync/config.yml b/gha_sync/config.yml index bf0ae751..4d2f558b 100644 --- a/gha_sync/config.yml +++ b/gha_sync/config.yml @@ -13,7 +13,6 @@ group: - files: - .github/actionlint.yaml - .github/CODEOWNERS - - .github/dependabot.yml - source: gha_sync/workflows/all/auto-create-pr.yml dest: .github/workflows/auto-create-pr.yml deleteOrphaned: true @@ -41,6 +40,30 @@ group: worganisation/wg-scripts worganisation/wg-utilities + # Renovate owns version updates; Dependabot retains security updates. + - files: + - .github/dependabot.yml + repos: | + worganisation/backplane + worganisation/esphome + worganisation/gpu-worker + worganisation/home-assistant + worganisation/home-assistant-appdaemon + worganisation/home-assistant-config-validator + worganisation/led-matrix-controller + worganisation/pre-commit-hooks-dependency-sync + worganisation/smart-mini-crt-interface + worganisation/very-slow-movie-player + worganisation/wg-scripts + worganisation/wg-utilities + + # The personal template retains its independent Dependabot policy. + - files: + - source: gha_sync/configs/dependabot.yml + dest: .github/dependabot.yml + repos: | + worgarside/python-template + # Prek Auto-Update - identical for every repo on the prek/PSR pattern, no # per-repo variation, so this is a plain synced file rather than a # per-repo template entry. diff --git a/gha_sync/configs/dependabot.yml b/gha_sync/configs/dependabot.yml new file mode 100644 index 00000000..497d0b25 --- /dev/null +++ b/gha_sync/configs/dependabot.yml @@ -0,0 +1,33 @@ +--- +version: 2 +updates: + - package-ecosystem: uv + directory: / + schedule: + interval: monthly + open-pull-requests-limit: 20 + groups: + uv-dependencies: + applies-to: version-updates + patterns: + - '*' + uv-security-dependencies: + applies-to: security-updates + patterns: + - '*' + reviewers: + - worgarside + + - package-ecosystem: github-actions + directory: / + schedule: + interval: monthly + reviewers: + - worgarside + + - package-ecosystem: npm + directory: / + schedule: + interval: monthly + reviewers: + - worgarside diff --git a/gha_sync/workflows/all/auto-create-pr.yml b/gha_sync/workflows/all/auto-create-pr.yml index e6740281..acef481c 100644 --- a/gha_sync/workflows/all/auto-create-pr.yml +++ b/gha_sync/workflows/all/auto-create-pr.yml @@ -6,6 +6,7 @@ on: branches-ignore: - main - dependabot/** + - renovate/** workflow_dispatch: jobs: diff --git a/gha_sync/workflows/all/set-pr-auto-merge.yml b/gha_sync/workflows/all/set-pr-auto-merge.yml index 8cc85f71..dd60c508 100644 --- a/gha_sync/workflows/all/set-pr-auto-merge.yml +++ b/gha_sync/workflows/all/set-pr-auto-merge.yml @@ -15,7 +15,9 @@ concurrency: jobs: set-auto-merge: name: Set PR Auto Merge - if: ${{ !github.event.pull_request.draft }} + if: >- + !github.event.pull_request.draft && + !startsWith(github.head_ref, 'renovate/') uses: worganisation/github-config-files/.github/workflows/__set-pr-auto-merge.yml@0.8.7 with: head-ref: ${{ github.head_ref }} diff --git a/renovate-default.json b/renovate-default.json new file mode 100644 index 00000000..c5d30d8f --- /dev/null +++ b/renovate-default.json @@ -0,0 +1,57 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended", + ":semanticCommits", + "helpers:pinGitHubActionDigests" + ], + "timezone": "Europe/London", + "schedule": [ + "* 0-6 * * 1" + ], + "prConcurrentLimit": 3, + "prHourlyLimit": 1, + "automerge": false, + "dependencyDashboard": true, + "reviewers": [ + "worgarside" + ], + "pre-commit": { + "enabled": false + }, + "packageRules": [ + { + "description": "Keep major upgrades individually reviewable.", + "matchUpdateTypes": [ + "major" + ], + "dependencyDashboardApproval": true + }, + { + "description": "Group routine GitHub Actions updates.", + "matchManagers": [ + "github-actions" + ], + "matchUpdateTypes": [ + "minor", + "patch", + "digest", + "pin", + "pinDigest" + ], + "groupName": "GitHub Actions" + }, + { + "description": "Shared workflow releases are owned by github-config-files sync.", + "matchManagers": [ + "github-actions" + ], + "matchPackageNames": [ + "worganisation/github-config-files", + "worgarside/github-config-files" + ], + "enabled": false + } + ], + "description": "Shared dependency update policy for worganisation repositories." +} diff --git a/renovate.json b/renovate.json new file mode 100644 index 00000000..249249a4 --- /dev/null +++ b/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "github>worganisation/github-config-files:renovate-default" + ] +}