From ef386251cffff5e0961e4775a5592f75f9159344 Mon Sep 17 00:00:00 2001 From: Bryan Joshua Pedini Date: Sat, 10 Oct 2026 11:09:04 +0200 Subject: [PATCH] ci: run the reconciler nightly for every package in the matrix --- .gitea/workflows/update.yaml | 119 +++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 .gitea/workflows/update.yaml diff --git a/.gitea/workflows/update.yaml b/.gitea/workflows/update.yaml new file mode 100644 index 0000000..7487572 --- /dev/null +++ b/.gitea/workflows/update.yaml @@ -0,0 +1,119 @@ +--- +name: Update Debian Packages + +on: + schedule: + - cron: "0 0 * * *" + workflow_dispatch: + inputs: + package: + description: "Single package to update (blank = all)" + required: false + type: string + force_rebuild: + description: "Bump the Debian revision even with no new upstream version" + required: false + type: boolean + default: false + force_refresh: + description: "Re-download the source and rebuild even when nothing changed" + required: false + type: boolean + default: false + no_git_push: + description: "Dry run: build, but neither upload nor push" + required: false + type: boolean + default: false + +defaults: + run: + shell: bash + +jobs: + update: + runs-on: ubuntu-latest + # dpkg-buildpackage runs as the unprivileged `builder` user inside a Debian + # bookworm image, so the result installs on bookworm and everything newer. + # + # Prebuilt by build-image.yaml (see dockerfile) so the toolchain is not + # reinstalled in every job every night. + container: + image: git.bjphoster.com/deb/autoupdate:latest + credentials: + username: ${{ vars.REGISTRY_USER }} + password: ${{ secrets.GIT_TOKEN }} + + strategy: + # One broken package must not cancel the rest of the matrix. + fail-fast: false + matrix: + package: + - skeptical-updater + + steps: + # No bootstrap step: node, git, jq, curl and the packaging toolchain all + # come from the prebuilt image above. node in particular has to be present + # before this action runs, since actions/checkout is JavaScript and the + # runner executes it with `node` from the image. + - uses: actions/checkout@v4 + + # The same credential serves git (clone/push of the package repos) and + # the package registry upload, which autoupdate.sh reads back through + # `git credential fill`. GIT_TOKEN therefore needs write:repository AND + # write:package. + - name: Configure git + env: + GIT_NAME: ${{ vars.GIT_NAME }} + GIT_EMAIL: ${{ vars.GIT_EMAIL }} + GIT_HOST: ${{ vars.GIT_HOST || 'git.bjphoster.com' }} + GIT_TOKEN: ${{ secrets.GIT_TOKEN }} + run: | + set -euo pipefail + # Validate HERE rather than letting a missing secret surface as an + # opaque 401 several steps later. + for v in GIT_NAME GIT_EMAIL GIT_TOKEN; do + if [ -z "${!v//[[:space:]]/}" ]; then + echo "::error::${v} is empty or unset (see README: required secrets and variables)" >&2 + exit 1 + fi + done + git config --global user.name "${GIT_NAME}" + git config --global user.email "${GIT_EMAIL}" + git config --global credential.helper store + echo "https://${GIT_EMAIL//@/%40}:${GIT_TOKEN}@${GIT_HOST}" > ~/.git-credentials + chmod 600 ~/.git-credentials + + # The `builder` user is baked into the image; this only hands it the + # workspace and the credentials written by the previous step. + - name: Hand over to the build user + run: | + set -euo pipefail + chown -R builder:builder "${GITHUB_WORKSPACE}" + cp /root/.gitconfig /root/.git-credentials /home/builder/ + chown -R builder:builder /home/builder + + - name: Update ${{ matrix.package }} + env: + GIT_HOST: ${{ vars.GIT_HOST || 'git.bjphoster.com' }} + # Compared against both `true` and 'true' on purpose. A bare + # `${{ inputs.x && '1' || '' }}` is wrong if the runner hands the + # input over as the STRING "false", which is truthy -- that would + # silently enable the flag on every run. + FORCE_REBUILD: ${{ (inputs.force_rebuild == true || inputs.force_rebuild == 'true') && '1' || '' }} + FORCE_REFRESH: ${{ (inputs.force_refresh == true || inputs.force_refresh == 'true') && '1' || '' }} + NO_GIT_PUSH: ${{ (inputs.no_git_push == true || inputs.no_git_push == 'true') && '1' || '' }} + run: | + set -euo pipefail + # workflow_dispatch with a package name runs only that one. + want="${{ inputs.package }}" + if [ -n "${want}" ] && [ "${want}" != "${{ matrix.package }}" ]; then + echo "skipping ${{ matrix.package }} (dispatch asked for ${want})" + exit 0 + fi + runuser -u builder -- env \ + GIT_HOST="${GIT_HOST}" \ + FORCE_REBUILD="${FORCE_REBUILD}" \ + FORCE_REFRESH="${FORCE_REFRESH}" \ + NO_GIT_PUSH="${NO_GIT_PUSH}" \ + ./autoupdate.sh "${{ matrix.package }}"