From 321bf93e5ff452ed39dd0c7e1c9081f94d43dbb9 Mon Sep 17 00:00:00 2001 From: kert Date: Thu, 29 Oct 2026 17:00:39 -0400 Subject: [PATCH] fix(renovate): land updates on main without PRs, daily, with github.com lookups The 10-27 fix made Renovate process the repo, and a manual run proved it: it opened 2 PRs and a Dependency Dashboard (#1396). But most lookups failed on the anonymous api.github.com limit, it was capped at 2 new branches an hour, and its PRs could never merge, because main still required Woodpecker checks that stopped reporting when CI moved to Gitea Actions. (Fixed in the Gitea branch protection: the CI lint/test/ notebooks-smoke push checks are now the required ones.) - automergeType=branch: once CI is green, minor/patch updates fast-forward onto main as plain commits, with no PRs, matching the main-only workflow. Majors still open PRs for review; automergeStrategy=fast-forward keeps any PR merge free of merge commits. - prHourlyLimit 0; the workflow runs daily, because branch automerge lands on the run after CI goes green. - GITHUB_COM_TOKEN passed to Renovate (secret still to be added). - Leave marimo to marimo_latest.py, hold duckdb <2 like the pyproject cap, and skip the vendored traefik plugin source. - marimo_latest.py fast-forwards the checkout when Renovate has moved the server's main, instead of aborting. --- .gitea/workflows/renovate.yml | 9 ++++++++- dev/scripts/marimo_latest.py | 9 ++++++++- renovate.json | 24 ++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/renovate.yml b/.gitea/workflows/renovate.yml index 2889d7a..39ddf8d 100644 --- a/.gitea/workflows/renovate.yml +++ b/.gitea/workflows/renovate.yml @@ -2,7 +2,9 @@ name: Renovate on: schedule: - - cron: "0 4 * * 1" # Weekly Monday 4am + # Daily: with automergeType=branch, Renovate merges a branch whose CI is + # green on its *next* run, so a weekly run took two weeks per update. + - cron: "0 4 * * *" workflow_dispatch: jobs: @@ -24,5 +26,10 @@ jobs: RENOVATE_ENDPOINT: http://git:3000/api/v1 RENOVATE_REPOSITORIES: homelab/stack RENOVATE_TOKEN: ${{ secrets.RENOVATE_TOKEN }} + # github.com lookups (github-tags/-releases pins, action pins, the + # uv/node tools Renovate installs to update lock files). Without it + # the anonymous 60/h API limit fails them all ("Package lookup + # failures", artifactErrors). A read-only token is enough. + GITHUB_COM_TOKEN: ${{ secrets.GITHUB_COM_TOKEN }} RENOVATE_GIT_AUTHOR: "Renovate Bot " LOG_LEVEL: "info" diff --git a/dev/scripts/marimo_latest.py b/dev/scripts/marimo_latest.py index ed6819a..b361be1 100644 --- a/dev/scripts/marimo_latest.py +++ b/dev/scripts/marimo_latest.py @@ -231,7 +231,14 @@ def preflight() -> None: raise Failed("preflight", f"uncommitted changes in {', '.join(IMAGE_INPUTS)}") git("fetch", "-q", "gitea", "main") if git("rev-list", "--count", "HEAD..gitea/main") != "0": - raise Failed("preflight", "main is behind gitea/main; pull first") + # Renovate automerges onto the server's main. Fast-forward only: git + # refuses if that would touch files someone has modified here. + r = run(["git", "merge", "--ff-only", "gitea/main"], check=False) + if r.returncode: + raise Failed( + "preflight", f"can't fast-forward to gitea/main: {r.stderr[-300:]}" + ) + log(f"fast-forwarded main to {git('rev-parse', '--short=7', 'HEAD')}") def upgrade(old: str, new: str) -> None: diff --git a/renovate.json b/renovate.json index b1983f2..b71bcba 100644 --- a/renovate.json +++ b/renovate.json @@ -3,7 +3,21 @@ "extends": ["config:recommended"], "labels": ["dependencies"], "automerge": false, + "automergeType": "branch", + "automergeStrategy": "fast-forward", + "prHourlyLimit": 0, "minimumReleaseAge": "7 days", + "ignorePaths": [ + "**/node_modules/**", + "**/bower_components/**", + "**/vendor/**", + "**/examples/**", + "**/__tests__/**", + "**/test/**", + "**/tests/**", + "**/__fixtures__/**", + "infra/traefik/plugins/src/**" + ], "osvVulnerabilityAlerts": true, "vulnerabilityAlerts": { "labels": ["dependencies", "security"] @@ -27,6 +41,16 @@ "matchPackageNames": ["pymupdf"], "allowedVersions": "<2" }, + { + "description": "Every service shares the same .duckdb files; a new duckdb major is a coordinated migration, not a bump (see pyproject's notebooks extra).", + "matchPackageNames": ["duckdb"], + "allowedVersions": "<2" + }, + { + "description": "dev/scripts/marimo_latest.py (nightly timer) owns the notebooks image's marimo pin end to end: bump, build, gate, roll. A Renovate bump would land the pin without rolling, and the timer would then see it as current.", + "matchDepNames": ["marimo-team/marimo"], + "enabled": false + }, { "description": "Generated-workflow tool pins: gen_config.py must re-emit .gitea/workflows after the bump, so a human merges these.", "matchFileNames": ["dev/scripts/backends/gitea.py"],