Skip to content

feat(ci): self-host Renovate, and auto-merge only what CI can vouch for - #10

Merged
andreszorro merged 2 commits into
mainfrom
chore/renovate-automerge
Aug 17, 2026
Merged

feat(ci): self-host Renovate, and auto-merge only what CI can vouch for#10
andreszorro merged 2 commits into
mainfrom
chore/renovate-automerge

Conversation

@andreszorro

@andreszorro andreszorro commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

Two things, and the second is why the first changed shape: auto-merge was never configured, and the hosted Renovate app cannot be given a ruleset bypass.

Why self-hosted

Searching the main ruleset's bypass picker for "Renovate" returns No suggestions. That picker only lists apps installed on this repository, and the hosted Mend app at github.com/apps/renovate is not installed — nor would installing it be the end of it, since it also needs org approval for a third-party app.

Without a bypass, Renovate's pull requests sit forever with a green ci check: the ruleset requires an approving review and a code-owner review, and no automation can satisfy a review requirement.

An App we install ourselves can be added to that list. So Renovate now runs from .github/workflows/renovate.yml on a daily cron, authenticating as the same App release.yml already needs. One App, one bypass actor, one pair of secrets — and the Renovate version is pinned in this repo rather than being whatever the hosted service ships today.

Because that App merges directly, platformAutomerge is now false: Renovate waits for ci and merges through the API itself, which means the repository's Allow auto-merge setting never has to be turned on.

What auto-merges

Group Auto-merge Reasoning
github actions pins ✅ digest, pin, patch, minor A digest refresh moves a SHA to a newer commit of the same action. Majors change inputs — excluded.
dev tooling (Biome, TypeScript, @types/**, commitlint, husky, lint-staged, czg) ✅ patch, minor Build-time only; if it breaks, lint + typecheck fails and the merge does not happen. Biome 1.x → 2.x is a config migration, so majors stay manual.
rendering runtime — jquery, @joint/**, @dagrejs/**, markdown-it, highlight.js, history, vite ❌ never Inlined into the page a user publishes.
lockFileMaintenance ❌ unchanged Widest blast radius, least signal.

automerge is false at the top level, so anything not named above stays manual. The "never" rule is deliberately the last rule mentioning those packages so it wins over any broader rule added later — asserted programmatically, not just intended.

What you need to do

  1. Create one GitHub App under FormulaMonks: Contents RW, Pull requests RW, Issues RW (dependency dashboard), Workflows: write (Renovate edits the pinned action digests — no other permission covers that). Install on renderizr only.
  2. Add repository variable AUTOMATION_APP_ID and secret AUTOMATION_APP_PRIVATE_KEY.
  3. Then add the App to the main ruleset bypass list — it appears only once installed.

Both workflows skip themselves and post a warning annotation while AUTOMATION_APP_ID is unset, so the Actions tab stays green rather than red in the meantime.

Variables are renamed RELEASE_APP_*AUTOMATION_APP_*, since one App now serves both workflows. Nothing was configured under the old names, so this costs nothing.

The trade, plainly. With the bypass, dependency updates that pass the full suite and both render modes merge without a human, and the same App merges release pull requests. Three things bound it, all load-bearing once the bypass exists: top-level automerge: false, minimumReleaseAge: "3 days", and the rule keeping the rendering runtime out of that path. Skip step 3 if you would rather keep reviewing everything — nothing else breaks.

Also

Corrects MAINTAINERS.md, which claimed main was unprotected and cited a 404 as evidence. It is protected by ruleset — and that paragraph now notes the RepositoryRole bypass, and any app added to the bypass list, keeps the self-imposed rules a promise for those actors.

biome ci clean · renovate-config-validator passes · both pinned action SHAs verified against their upstream repos · workflow YAML parses.

🤖 Generated with Claude Code

andreszorro and others added 2 commits August 16, 2026 19:44
…time

Nothing auto-merged before: the only automerge key was `automerge: false` on
lockFileMaintenance. Every dependency bump waited for a human, including digest
refreshes that move a pinned SHA to a newer commit of the same action.

Now scoped rather than switched on wholesale. Action pins and dev tooling
auto-merge on digest, pin, patch and minor — none of it reaches a rendered
workspace, and `ci` runs the whole suite and both render modes before anything
merges. Majors stay manual; a Biome 1.x to 2.x is a config migration, not a
bump.

The rendering runtime — jquery, @joint/*, @dagrejs/*, markdown-it, highlight.js,
history, vite — is inlined into the page a user publishes, so it never
auto-merges. That rule is deliberately the last one mentioning those packages,
so it wins over any broader rule added later. A green CI proves Renderizr still
renders; it cannot prove a JointJS change did not alter how somebody's diagram
looks.

None of this takes effect until two settings change: repository auto-merge is
off, and the main ruleset's review requirement cannot be satisfied by
auto-merge. Both are recorded in MAINTAINERS.md with what they cost. Also
corrects that document's claim that main is unprotected — it is, by ruleset,
since this morning.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The hosted Mend app at github.com/apps/renovate cannot be added to the `main`
ruleset's bypass list, because that picker only lists apps installed on this
repository — searching it for "Renovate" returns nothing. Without a bypass,
Renovate's pull requests sit forever with a green `ci` check: the ruleset
requires a review, and no automation can satisfy a review requirement.

An App we install ourselves can be added. So Renovate now runs from
.github/workflows/renovate.yml on a daily cron, authenticating as the same App
release.yml uses, with the Renovate version pinned here rather than being
whatever the hosted service ships today. The bot identity is derived from the
App slug rather than written down, so renaming the App cannot silently
misattribute its commits.

Because the App merges directly, `platformAutomerge` is now false: Renovate
waits for `ci` and merges through the API itself, which removes the need to
enable the repository's Allow auto-merge setting at all.

The App variables are renamed RELEASE_APP_* -> AUTOMATION_APP_*, since one App
now serves both workflows and neither is only about releases. Nothing had been
configured under the old names yet, so this costs nothing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@andreszorro andreszorro changed the title feat(renovate): auto-merge action pins and dev tooling, never the runtime feat(ci): self-host Renovate, and auto-merge only what CI can vouch for Aug 17, 2026
@andreszorro
andreszorro merged commit 23bd5f1 into main Aug 17, 2026
12 of 18 checks passed
@upwind-code-us

upwind-code-us Bot commented Aug 17, 2026

Copy link
Copy Markdown

Upwind Upwind Code Scan - ✅ Proceed with Deployment

0 newly introduced vulnerabilities · 0 resolved · 1 total in this PR vs main

🔴 1 Critical

View full analysis in Upwind Console

Scan completed in 1m 13s

Scan history (2 scans)
Commit Scanned at New Resolved Net
7ba6abc 2026-08-17 00:59 UTC 0 0 0
346a9bc < 2026-08-17 00:59 UTC 0 0 0

Last scanned: 346a9bc · 2026-08-17 00:59 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant