From a86a599fbb3912e5c31a6dabae73a247eab0f7ca Mon Sep 17 00:00:00 2001 From: Bryan Joshua Pedini Date: Sat, 10 Oct 2026 11:09:04 +0200 Subject: [PATCH] ci: prebuild the debian toolchain as a container image --- .dockerignore | 4 ++ .gitea/workflows/build-image.yaml | 67 +++++++++++++++++++++++++++++++ dockerfile | 46 +++++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitea/workflows/build-image.yaml create mode 100644 dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..a45c1da --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +# The image is a toolchain only -- the dockerfile COPYs nothing, and the +# scripts arrive via actions/checkout at run time. Keep the build context empty. +* +!dockerfile diff --git a/.gitea/workflows/build-image.yaml b/.gitea/workflows/build-image.yaml new file mode 100644 index 0000000..cba9902 --- /dev/null +++ b/.gitea/workflows/build-image.yaml @@ -0,0 +1,67 @@ +--- +name: Build Autoupdater Image + +concurrency: + group: build-image + cancel-in-progress: false + +on: + schedule: + # Monthly, to pick up bookworm point releases and security updates; + # :latest is overwritten each time. + - cron: "0 3 1 * *" + push: + branches: + - main + paths: + - dockerfile + - .dockerignore + - .gitea/workflows/build-image.yaml + workflow_dispatch: + +defaults: + run: + shell: bash + +jobs: + build: + # No Debian needed here -- this only drives docker. The *image* is Debian. + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Log in to the Gitea container registry + env: + GIT_HOST: ${{ vars.GIT_HOST || 'git.bjphoster.com' }} + REGISTRY_USER: ${{ vars.REGISTRY_USER }} + GIT_TOKEN: ${{ secrets.GIT_TOKEN }} + run: | + set -euo pipefail + # NB: this is the Gitea *username*, not vars.GIT_NAME -- that one is + # the display name used for git commit authorship and contains spaces. + printf '%s' "${GIT_TOKEN}" \ + | docker login "${GIT_HOST}" \ + --username "${REGISTRY_USER}" \ + --password-stdin + + - name: Build and push + env: + GIT_HOST: ${{ vars.GIT_HOST || 'git.bjphoster.com' }} + run: | + set -euo pipefail + # The repo is `.autoupdate`, but OCI names cannot start with a dot. + image="${GIT_HOST}/deb/autoupdate" + + # --pull so a monthly rebuild actually picks up a new base image + # rather than reusing a cached one. + docker build --pull --tag "${image}:latest" . + docker push "${image}:latest" + + echo "pushed ${image}:latest" + + - name: Log out + if: always() + env: + GIT_HOST: ${{ vars.GIT_HOST || 'git.bjphoster.com' }} + run: docker logout "${GIT_HOST}" || true diff --git a/dockerfile b/dockerfile new file mode 100644 index 0000000..5dd6c42 --- /dev/null +++ b/dockerfile @@ -0,0 +1,46 @@ +# Build environment for the Debian autoupdater. +# +# Rebuilt monthly by .gitea/workflows/build-image.yaml and pushed as :latest, so +# the nightly package jobs start with the toolchain already in place instead +# of each running a full apt transaction first. +# +# bookworm on purpose: a package built against the older dpkg/debhelper installs +# on bookworm and on everything newer, never the other way round. +FROM debian:bookworm-slim + +LABEL org.opencontainers.image.title="deb-autoupdate" +LABEL org.opencontainers.image.description="Debian build environment for the Debian package autoupdater" +LABEL org.opencontainers.image.source="https://git.bjphoster.com/deb/.autoupdate" + +ARG DEBIAN_FRONTEND=noninteractive + +# nodejs actions/checkout is a JavaScript action; the runner executes it +# with `node` from inside this image, and debian-slim ships none. +# dpkg-dev dpkg-buildpackage, dpkg-parsechangelog +# debhelper dh, for debian/rules +# build-essential dpkg-checkbuilddeps implicitly requires it, even for arch:all +# fakeroot for packages without Rules-Requires-Root: no +# devscripts dch and friends, for working on a package by hand in here +# lintian advisory lint of the built package +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + nodejs \ + git \ + curl \ + jq \ + ca-certificates \ + dpkg-dev \ + debhelper \ + build-essential \ + fakeroot \ + devscripts \ + lintian \ + && rm -rf /var/lib/apt/lists/* + +# The nightly job drops to this user rather than building as root (CI +# containers are root by default). Baked in here rather than created per run. +RUN useradd --create-home --shell /bin/bash builder + +# Sanity check: fail the image build rather than the nightly job if the +# toolchain ever stops working in this environment. +RUN runuser -u builder -- bash -c 'dpkg-buildpackage --version | head -n1 && lintian --version && command -v dpkg-parsechangelog node'