# Builds the image the nightly `tracker-live` run executes in: Debian, the packaged Super # Productivity, a virtual display and the tools the suite needs (Gitea #156). It lives in # this Gitea instance's registry as `gitea.nehmer.net/torben/chemenu-sp-live`. # # The image follows the update channel, not a pin. Installed desktop apps update themselves, # so a pinned old version would be tested while users already run the new one. Every day this # workflow asks `latest-linux.yml` (`.gitea/sp-live/resolve-version.sh`) which release is # current, and builds only when the registry does not hold that tag yet. It also rebuilds once # a month regardless, so the Debian layers behind the app do not age unnoticed. # # Tags: `:` always, `:latest` only when that version is what the channel says. # A manual run with `sp_version` builds an older release (to reproduce a red night against # the version it went red on) and therefore never moves `:latest`. # # Runner shape follows torben/gitea-mcp, `.gitea/workflows/binford-release.yaml`: the # `container-builder` label, a remote BuildKit on the runner host, and the registry login from # 1Password. `OP_SERVICE_ACCOUNT_TOKEN` is a user-level secret that covers `torben/*`. # # After the very first push the package has to be linked to this repository once, by hand, in # the Gitea UI - a step no workflow can do. Until then the image builds and pulls fine; only # the package page shows no repository. name: SP live image on: schedule: # 04:10 UTC, an hour after `nightly` and well before `tracker-live` (05:00), so a new # release is in the registry by the time the suite looks for it. - cron: '10 4 * * *' workflow_dispatch: inputs: sp_version: description: 'Super Productivity release to build (default: the current one)' required: false force: description: 'Rebuild even if the tag already exists (true/false)' required: false default: 'false' env: REGISTRY: gitea.nehmer.net/torben IMAGE_NAME: chemenu-sp-live jobs: build-and-push: runs-on: container-builder container: image: debian:trixie-slim steps: - name: Install CI dependencies # `nodejs` is for act_runner's JavaScript actions, not for us - see ci.yml. `unzip` is for # 1password/load-secrets-action, which unpacks its CLI with it and fails with exit 127 # without it. run: | set -eu apt-get update -qq apt-get install -y --no-install-recommends \ git nodejs curl docker-cli docker-buildx unzip ca-certificates iproute2 gawk - uses: actions/checkout@v7 - name: Resolve the Super Productivity release id: sp env: REQUESTED: ${{ inputs.sp_version }} run: | set -eu channel="$(.gitea/sp-live/resolve-version.sh latest)" channel_version="$(printf '%s\n' "$channel" | sed -n 's/^version=//p')" if [ -n "${REQUESTED:-}" ]; then wanted="$(.gitea/sp-live/resolve-version.sh "$REQUESTED")" else wanted="$channel" fi { printf '%s\n' "$wanted" echo "channel_version=$channel_version" } >> "$GITHUB_OUTPUT" printf '%s\n' "$wanted" - name: Load secrets from 1Password uses: 1password/load-secrets-action@v2 with: export-env: true env: OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} REGISTRY_USER: op://CI-CD/gitea-package-token/username REGISTRY_PAT: op://CI-CD/gitea-package-token/password - name: BuildKit setup (remote builder) run: | HOST_IP=$(ip route | awk '/default/ { print $3 }') docker buildx create --name remote-builder --driver remote tcp://$HOST_IP:1234 --use --bootstrap - name: Log in to the container registry run: | echo "$REGISTRY_PAT" | docker login gitea.nehmer.net -u "$REGISTRY_USER" --password-stdin - name: Decide whether to build id: decide env: SP_VERSION: ${{ steps.sp.outputs.version }} CHANNEL_VERSION: ${{ steps.sp.outputs.channel_version }} FORCE: ${{ inputs.force }} run: | set -eu ref="$REGISTRY/$IMAGE_NAME:$SP_VERSION" build=false why="" if [ "${FORCE:-false}" = true ]; then build=true; why="forced" elif [ "$(date -u +%d)" = 01 ]; then build=true; why="monthly rebuild" elif ! docker buildx imagetools inspect "$ref" > /dev/null 2>&1; then build=true; why="$ref is not in the registry yet" fi tags="$ref" if [ "$SP_VERSION" = "$CHANNEL_VERSION" ]; then tags="$tags $REGISTRY/$IMAGE_NAME:latest" fi { echo "build=$build" echo "tags<> "$GITHUB_OUTPUT" echo "build=$build ${why:+($why)}; tags: $tags" - name: Build and push if: steps.decide.outputs.build == 'true' uses: docker/build-push-action@v6 with: context: .gitea/sp-live file: .gitea/sp-live/Dockerfile platforms: linux/amd64 push: true tags: ${{ steps.decide.outputs.tags }} build-args: | SP_VERSION=${{ steps.sp.outputs.version }} SP_SHA512=${{ steps.sp.outputs.sha512 }}