From d174e3cf78034763dfa2f373b27e3f6f0fcff53f Mon Sep 17 00:00:00 2001 From: Miccy Date: Sat, 22 Aug 2026 23:57:55 +0200 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=93=9D=20docs:=20name=20the=20auto-me?= =?UTF-8?q?rge=20repo=20setting=20as=20a=20prerequisite?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The preset sets platformAutomerge, which needs "Allow auto-merge" turned on in the consuming repo. With it off, Renovate silently falls back to merging through its own bot -- it works, but not the way this preset describes, and nothing tells you. Found on the preset's own repo after the transfer: allow_auto_merge was false while the preset advertised platform automerge. If it was wrong here it is wrong in every repo that adopts this by reading the README. --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f88a11a..bf48e32 100644 --- a/README.md +++ b/README.md @@ -91,8 +91,14 @@ Drop this file into a new repo and you are done: That is the whole setup. The preset carries the schedule, grouping, automerge policy and ecosystem coverage — there is nothing else to configure per repo. -The one prerequisite is that the **Mend Renovate App** is installed for the -account or org and has access to the repo. +Two prerequisites, both one-time: + +1. The **Mend Renovate App** is installed for the account or org and has access + to the repo. +2. **Allow auto-merge** is enabled in the repo's settings. This preset sets + `platformAutomerge`, which uses GitHub's native auto-merge. With the repo + setting off, Renovate silently falls back to merging through its own bot + instead — it still works, but not the way this preset describes. ### What to expect on a fresh repo From cd6975de528ea645a18d4d3d14ade569333e7d0b Mon Sep 17 00:00:00 2001 From: Miccy Date: Sun, 23 Aug 2026 00:04:50 +0200 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=91=B7=20ci:=20move=20the=20validator?= =?UTF-8?q?=20into=20a=20script=20both=20CI=20and=20humans=20run?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI on the org is billing-locked, so nothing has validated the presets since the transfer. tooling/validate.sh runs the same checks locally, and can be wired up as a pre-push hook. It is a convenience, not a boundary -- a local hook is skippable and CI stays the real gate. The workflow now calls the same script rather than repeating the file list, so the two cannot drift. The pinned renovate version lives only in the script now; renovate.json carries a custom manager to keep that pin updated, since the built-in githubActionsVersions manager only scans workflow files. The script fails loudly on a missing preset instead of validating a shorter list, which is the failure mode that would otherwise pass silently after a rename. --- .github/workflows/validate.yml | 11 +++-------- README.md | 16 ++++++++++++++++ renovate.json | 15 +++++++++++++-- tooling/validate.sh | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 10 deletions(-) create mode 100755 tooling/validate.sh diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 18649af..f845c64 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -32,12 +32,7 @@ jobs: with: node-version: 22 - # Pinned so CI does not silently execute whatever renovate publishes next. + # The pinned renovate version lives in the script, so CI and a local run + # cannot drift. renovate.json keeps that pin updated. - name: Validate all presets - env: - # renovate: datasource=npm depName=renovate - RENOVATE_VERSION: 44.39.1 - run: | - npx --yes --package "renovate@${RENOVATE_VERSION}" -- \ - renovate-config-validator --strict default.json renovate.json \ - lockdown.json aggressive.json no-automerge.json + run: ./tooling/validate.sh diff --git a/README.md b/README.md index bf48e32..e3fab8b 100644 --- a/README.md +++ b/README.md @@ -199,6 +199,22 @@ lockfile refreshes are performed by the incumbent package manager, not by nub. | `vulnerabilityAlerts` | ✅ enabled | With security labels | | `lockFileMaintenance` | ✅ weekly | Review required — the age gate does not apply here | +## Validating locally + +```bash +./tooling/validate.sh +``` + +Same list of presets CI checks. Wire it up as a pre-push hook if you want it to +run on its own: + +```bash +ln -s ../../tooling/validate.sh .git/hooks/pre-push +``` + +A local hook is a convenience, not a boundary — anyone can skip it. CI stays the +real gate. + ## Testing locally You can test this config locally before deploying: diff --git a/renovate.json b/renovate.json index ee8bd08..0a27d99 100644 --- a/renovate.json +++ b/renovate.json @@ -2,7 +2,18 @@ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "description": "This repo eats its own dog food: it consumes the preset it publishes. Without this, the action digests and the pinned renovate version in .github/workflows/ would rot, and a stale pin is worse than a floating tag.", "extends": [ - "local>ownctrl/supply-chain", - "customManagers:githubActionsVersions" + "local>ownctrl/supply-chain" + ], + "customManagers": [ + { + "description": "Keep the validator pin in tooling/validate.sh updated", + "customType": "regex", + "managerFilePatterns": [ + "/^tooling/validate\\.sh$/" + ], + "matchStrings": [ + "# renovate: datasource=(?\\S+) depName=(?\\S+)\\s+RENOVATE_VERSION=\"\\$\\{RENOVATE_VERSION:-(?[^}\"]+)\\}\"" + ] + } ] } diff --git a/tooling/validate.sh b/tooling/validate.sh new file mode 100755 index 0000000..a569c38 --- /dev/null +++ b/tooling/validate.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# Validate every preset in this repo. +# +# This mirrors what .github/workflows/validate.yml runs in CI. It exists so the +# gate still works when CI does not -- run it before pushing, or wire it up as +# a pre-push hook: +# +# ln -s ../../tooling/validate.sh .git/hooks/pre-push +# +# It is a convenience, not an enforcement boundary: anyone can skip a local +# hook. CI remains the real gate. +set -euo pipefail + +# renovate: datasource=npm depName=renovate +RENOVATE_VERSION="${RENOVATE_VERSION:-44.39.1}" + +cd "$(dirname "$0")/.." + +presets=(default.json renovate.json lockdown.json aggressive.json no-automerge.json) + +missing=() +for f in "${presets[@]}"; do + [[ -f "$f" ]] || missing+=("$f") +done +if [[ ${#missing[@]} -gt 0 ]]; then + printf 'missing preset(s): %s\n' "${missing[*]}" >&2 + echo "if a preset was renamed, update this list and the CI workflow together" >&2 + exit 1 +fi + +echo "validating ${#presets[@]} presets against renovate@${RENOVATE_VERSION}" +npx --yes --package "renovate@${RENOVATE_VERSION}" -- \ + renovate-config-validator --strict "${presets[@]}" From 6d3ec77446f2cb6ad17202dd8800da249a55d3cf Mon Sep 17 00:00:00 2001 From: Miccy Date: Sun, 23 Aug 2026 00:34:15 +0200 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=93=9D=20docs:=20say=20where=20Renova?= =?UTF-8?q?te=20actually=20runs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "Reference it and you are done" is true on GitHub.com and nowhere else. Every other forge needs Renovate self-hosted, which is the largest prerequisite this README had and the one it did not mention. Corrects an assumption made earlier in this work: GitLab has no hosted Mend app either. Renovate's own docs point Bitbucket, Forgejo, Gitea and GitLab all at self-hosting. Also states what a mirror is for, since the two get conflated: mirroring makes local>ownctrl/supply-chain resolvable on that forge. Nothing runs on a mirror. --- README.md | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e3fab8b..5f1f67f 100644 --- a/README.md +++ b/README.md @@ -93,13 +93,31 @@ policy and ecosystem coverage — there is nothing else to configure per repo. Two prerequisites, both one-time: -1. The **Mend Renovate App** is installed for the account or org and has access - to the repo. +1. **Renovate reaches the repo.** On GitHub.com that is the Mend Renovate App, + installed for the account or org. On every other forge you run Renovate + yourself — see below. 2. **Allow auto-merge** is enabled in the repo's settings. This preset sets `platformAutomerge`, which uses GitHub's native auto-merge. With the repo setting off, Renovate silently falls back to merging through its own bot instead — it still works, but not the way this preset describes. +### Where Renovate runs + +The preset is only JSON; it works wherever Renovate does. Getting Renovate to +run is the part that differs, and only GitHub.com is free of setup: + +| Forge | How Renovate runs | +| --- | --- | +| GitHub.com | Mend Renovate App — hosted, free, nothing to run | +| GitLab | self-hosted; the [`renovate-runner`](https://gitlab.com/renovate-bot/renovate-runner) CI template runs it as a scheduled pipeline | +| Codeberg / Forgejo / Gitea | self-hosted; run the Renovate CLI on a schedule | +| Bitbucket | self-hosted | + +This is a property of the Renovate ecosystem, not of this preset — you would +face it with any preset, or with none. Mirroring this repo to another forge is +about making `local>ownctrl/supply-chain` resolvable there; nothing runs on +the mirror itself. + ### What to expect on a fresh repo - **Nothing happens until Monday.** The schedule is `before 06:00 on monday`