From 67d8a095a5e0050f3ad6cb8da8c419e486b7e0e2 Mon Sep 17 00:00:00 2001 From: lilleman Date: Sat, 4 Jul 2026 21:51:04 +0200 Subject: [PATCH] CI: Renovate for gated, self-hosted dependency updates --- .gitea/workflows/renovate.yml | 22 +++++++++++++++++++++ README.md | 17 +++++++++++++++++ renovate.json | 36 +++++++++++++++++++++++++++++++++++ todo.md | 3 ++- 4 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 .gitea/workflows/renovate.yml create mode 100644 renovate.json diff --git a/.gitea/workflows/renovate.yml b/.gitea/workflows/renovate.yml new file mode 100644 index 0000000..8ee6a84 --- /dev/null +++ b/.gitea/workflows/renovate.yml @@ -0,0 +1,22 @@ +name: Renovate +on: + schedule: + - cron: '17 4 * * *' + workflow_dispatch: + +jobs: + renovate: + runs-on: docker-host + steps: + - name: Run Renovate against this repo + env: + RENOVATE_TOKEN: ${{ secrets.RENOVATE_TOKEN }} + run: | + docker run --rm \ + -e LOG_LEVEL=info \ + -e RENOVATE_ENDPOINT=https://gitea.larvit.se/api/v1 \ + -e RENOVATE_GIT_AUTHOR="Renovate Bot " \ + -e RENOVATE_PLATFORM=gitea \ + -e RENOVATE_REPOSITORIES=${{ github.repository }} \ + -e RENOVATE_TOKEN \ + renovate/renovate:43.251.0 diff --git a/README.md b/README.md index 81fc826..ee5a583 100644 --- a/README.md +++ b/README.md @@ -1177,6 +1177,7 @@ Gitea Actions (`.gitea/workflows/`) runs the pipeline; the test job runs | `release.yml` | push of a `vX.Y.Z` tag | re-tag that commit's image as `X.Y.Z`, `X.Y`, `X`, `latest`; sync those tags to Docker Hub | | `mirror.yml` | push to `main` or any tag, or manual | force-push `main` + tags to the [GitHub mirror](https://github.com/larvit/plainpages) | | `registry-cleanup.yml` | nightly cron, or manual | delete registry images that are neither release-tagged nor a branch head | +| `renovate.yml` | nightly cron, or manual | open dependency-update PRs and automerge them once the gate is green | `main` is not re-tested on push — its commits are meant to arrive already green from a gated branch, so the status check to gate a merge on is `CI / full-gate (push)`. @@ -1238,6 +1239,22 @@ as the Gitea Actions secret `MIRROR_GITHUB_TOKEN` (repo Settings → Actions → rejects secret names starting with `GITHUB_`/`GITEA_`). Trigger the workflow manually for the first sync — until the secret exists, the mirror job fails loud on each merge. +**Dependency updates** — `renovate.yml` runs [Renovate](https://docs.renovatebot.com) +nightly (self-hosted, this repo only) against [`renovate.json`](renovate.json), opening PRs +that bump npm deps (both `package.json`s), Docker base images (both Dockerfiles + +`compose*.yml`), Gitea action versions, and the image tags pinned inside workflow `run:` +steps (a custom regex manager, so nothing pinned drifts unmanaged). Version-locked sets move +together in one PR — the Ory images (kratos/keto/hydra) and the Playwright runner + its +browser image — and every bump keeps the existing **exact semver pin** exact, never widening +to a range or adding a digest. Each PR +runs through the normal gate on its `renovate/*` branch and, with `"automerge": true`, +Renovate merges it once `CI / full-gate (push)` is green (rebasing stale branches so the +fast-forward-only merge still holds) — routine bumps land untouched; only a red gate needs a +human. One-time setup: reuse the shared `renovate@larvit.se` bot — give it write access to +this repo and store its Gitea PAT as the Actions **secret** `RENOVATE_TOKEN`. Until it +exists, the nightly job fails loud (and, like the other secrets, a `GITEA_` prefix is +rejected). + **One-time server setup** — register an [act_runner](https://docs.gitea.com/usage/actions/act-runner) in host mode with the label `docker-host` (config: `labels: ["docker-host:host"]`) on a machine with Docker Engine + diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..d66dbf4 --- /dev/null +++ b/renovate.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": ["config:recommended"], + "automerge": true, + "packageRules": [ + { + "description": "Ory services share one release train - update kratos, keto and hydra together", + "matchDatasources": ["docker"], + "matchPackageNames": ["oryd/kratos", "oryd/keto", "oryd/hydra"], + "groupName": "Ory stack" + }, + { + "description": "Playwright runner and its browser image are version-locked - bump together", + "matchPackageNames": ["@playwright/test", "mcr.microsoft.com/playwright"], + "groupName": "Playwright" + } + ], + "customManagers": [ + { + "customType": "regex", + "description": "Pin the Renovate image the Renovate workflow runs", + "managerFilePatterns": [".gitea/workflows/renovate.yml"], + "matchStrings": ["renovate/renovate:(?[0-9][^\\s\"']*)"], + "depNameTemplate": "renovate/renovate", + "datasourceTemplate": "docker" + }, + { + "customType": "regex", + "description": "Pin the node image registry-cleanup runs cleanup.ts in", + "managerFilePatterns": [".gitea/workflows/registry-cleanup.yml"], + "matchStrings": ["\\snode:(?[0-9][^\\s\"']*)"], + "depNameTemplate": "node", + "datasourceTemplate": "docker" + } + ] +} diff --git a/todo.md b/todo.md index 8d756f1..33b8d83 100644 --- a/todo.md +++ b/todo.md @@ -10,7 +10,8 @@ - [x] CI/CD - Re-tag docker images from git hash to semver when a semver git tag is pushed. (`release.yml` on a `vX.Y.Z` tag pulls the commit-hash image and re-tags it `X.Y.Z`/`X.Y`/`X`/`latest`, failing loud if the gated image is missing; tag pushes also trigger the GitHub mirror; documented in README → CI/CD.) - [x] CI/CD - Sync docker images to docker hub after each re-tag to git tags. (`release.yml` pushes the same `X.Y.Z`/`X.Y`/`X`/`latest` tags to `docker.io/larvit/plainpages` after the Gitea re-tag — releases only, no hash tags; auth via the `DOCKERHUB_USER` variable + `DOCKERHUB_TOKEN` secret; documented in README → CI/CD.) - [x] Write a short text on how to use this docker image to publish on docker hub and save it to README-dockerhub.md (tagline, tags, clone-free quick start — the image ships the Ory config, extracted via `docker run … tar` + a self-contained compose.yml — env table, first plugin; pasted into the Docker Hub overview by hand — noted in README → CI/CD.) -- [ ] CI/CD - Setup renovate bot. Check how other repos on this Gitea is setup you can get access to, there should be a number of renovate bot activated ones. +- [x] CI/CD - Setup renovate bot. Check how other repos on this Gitea is setup you can get access to, there should be a number of renovate bot activated ones. (`renovate.yml` runs the self-hosted `renovate/renovate` image nightly against `renovate.json` — this repo only, via the shared `renovate@larvit.se` bot + `RENOVATE_TOKEN` secret, mirroring the `pwrpln/core` pattern; standard managers cover npm/Dockerfiles/compose/gitea-action pins, two custom regex managers cover the image tags embedded in workflow `run:` steps, the Ory + Playwright lockstep sets are grouped, every bump stays an exact pin, and each PR automerges once the gate is green; documented in README → CI/CD.) +- [ ] CI/CD - When renovate updates a dependency - also release a new version of plainpages based on what got updated with Renovate. Major typescript? New apiVersion + new major. A tiny patch to ejs? Only patch release etc. - [ ] Add an e2e test for the admin plugin's OAuth2-clients (Hydra) screen. The full-flow e2e suite runs without Hydra (compose.full.yml), so /admin/clients register/detail/delete is only unit-covered (src/http/app.test.ts); wire Hydra into an e2e stack and drive the screen in the browser. - [ ] Build and publish docker image as CI/CD. - [ ] Add i18n support.