pi setup

Releases

Dependency updates: sandbox

Every version in this repo and in pi-config is pinned, and a self-hosted Renovate keeps them current by opening pull requests on Codeberg. Each repo has its own, scoped Renovate run that processes only that repo. The brain repos are not included.

What is updated#

DependencyPinned inSource Renovate checks
Base image node:24-bookworm-slim (tag + digest)Dockerfile FROMDocker Hub
pi (@earendil-works/pi-coding-agent)Dockerfile ARG PI_VERSIONnpm
Hermit hermit (with the SHA-256 of its .gz)Dockerfile ARG HERMIT_VERSION, HERMIT_SHA256_<ARCH>GitHub releases (cashapp/hermit)
Hermit package index cashapp/hermit-packages (archive at a fixed commit, with its SHA-256)Dockerfile ARG HERMIT_PACKAGES_COMMIT, HERMIT_PACKAGES_SHA256by hand: no Renovate rule; compute the archive’s SHA-256 with the new commit
AWS MCP proxy mcp-proxy-for-aws-cli (pins its Python dependencies exactly)Dockerfile ARG MCP_PROXY_FOR_AWS_VERSIONPyPI
STACKIT CLI stackit, Hetzner Cloud CLI hcloud, GitHub CLI gh, ghorg, RTK rtk, kubectl, talosctl (with checksums)Dockerfile ARG <TOOL>_VERSION, <TOOL>_SHA256_<ARCH>GitHub releases (kubectl: kubernetes/kubernetes, talosctl: siderolabs/talos)
rtk build stage (compiles RTK for arm64; not in the image)Dockerfile FROM rust (tag + digest); ARG RTK_COMMIT (tag commit, rewritten with the checksums)Docker Hub; GitHub releases of rtk-ai/rtk
uv build stage (installs the proxy; not in the image)Dockerfile FROM ghcr.io/astral-sh/uv (tag + digest)GitHub container registry
Debian packages of the image (git, ripgrep, fd-find, jq, curl, ca-certificates, less, python3, python3-yaml, python3-jsonschema, make, g++, yamllint, chromium)Dockerfile ARG <PKG>_VERSIONDebian bookworm, bookworm-updates, bookworm-security
Release tooling (semantic-release + plugins)package.json, package-lock.jsonnpm (+ weekly lockfile maintenance)
Forgejo actions (checkout, setup-node).forgejo/workflows/*.ymlcode.forgejo.org tags
Node.js for CI jobs.forgejo/workflows/*.yml node-versionNode.js releases
Renovate itself.forgejo/workflows/renovate.ymlnpm
just, gitleaks (with checksums)scripts/ci-install-tools.shGitHub releases
Docker CLI, compose, buildxscripts/ci-install-tools.shDocker’s Debian repo
podman clientscripts/ci-install-tools.shDebian bookworm
pi packages (npm:<name>@<x.y.z>)pi-config/agent/settings.json + docs/config-reference.mdnpm

Versions that are not in a standard file format carry a # renovate: datasource=… depName=… comment on the line above; the regex manager in renovate.json reads those.

How updates arrive#

  • Commit types decide releases. Image contents (base image, pi, Debian packages) and pi packages are committed as build(deps): … → patch release (and a new image here). CI and release tooling is ci(deps): … → no release.
  • Grouping: all Debian packages in one PR; semantic-release and its plugins in one PR.
  • No minimum release age (bleeding edge): a new version is proposed in the first nightly run after it is published (owner decision 2026-10-04; the former 3-day wait is gone). Accepted risk: a compromised or withdrawn release can reach a PR the same night — the review before merging is the safeguard, and nothing is merged automatically.
  • Checksums: when Renovate bumps just or gitleaks, it runs scripts/update-ci-checksums.sh in the PR branch, which fetches the new release’s published checksums and rewrites the pinned SHA-256 values; for stackit, hcloud, ghorg, gh, rtk, kubectl and talosctl in the image it runs scripts/update-image-checksums.sh the same way.
  • Held back: conventional-changelog-conventionalcommits stays below 10 until semantic-release ships conventional-changelog-writer 9.
  • Dependency Dashboard: an issue in each repo lists every pending and open update.
  • PR checks (.forgejo/workflows/check.yml) run on every PR: just check, and here also an amd64 build of the image, so a Debian version that was superseded fails before merge. Both repos also validate renovate.json with the pinned Renovate version (renovate-config-validator --strict, same pin as renovate.yml, bumped together), so a config error fails the PR instead of the nightly run.
  • Nothing is merged automatically. Review the PR, merge it, and the release pipeline does the rest.

The Renovate jobs#

Each repo runs its own .forgejo/workflows/renovate.yml on the runner pi at night — workflow cron times are UTC: pi-docker-sandbox at 01:17 UTC (03:17 CEST / 02:17 CET), pi-config at 01:47 UTC (03:47 CEST / 02:47 CET) — and on demand (Actions → renovate → Run workflow in that repo). Each job runs npx renovate@<pinned> with platform forgejo against https://codeberg.org/api/v1 and RENOVATE_REPOSITORIES set to ${{ github.repository }}, so it can only work on its own repo; the concurrency group is per repo. The only post-upgrade commands allowed are scripts/update-ci-checksums.sh and scripts/update-image-checksums.sh.

Keep both runs before 06:00 Berlin time: renovate.json’s weekly lockfile maintenance only happens in its before 6am on monday window (timezone Europe/Berlin).

One-time setup#

  1. Bot account (recommended): a separate Codeberg user, e.g. pi-renovate-bot, added to the black0ut-pi-setup organisation with write access to both repos.
  2. Token of that account (Settings → Applications) with: repository read+write, issue read+write, organisation read, user read. Store it as the Actions secret RENOVATE_TOKEN — once at organisation level, or per repo (both repos need it). Per-repo secrets let you use a different token for each repo.
  3. GitHub token — RENOVATE_GITHUB_COM_TOKEN: a fine-grained GitHub token with no permissions (public read only). Needed for Node.js, just and gitleaks lookups and release notes; without it those dependencies are skipped.
  4. Issues must be enabled in both repos (for the Dependency Dashboard).
  5. Run the workflow once by hand in each repo. Because renovate.json already exists, there is no onboarding PR: Renovate creates the Dependency Dashboard issue and the first update PRs.