From 4f24959d49e681b7efd9932f2553d049118f3e25 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 11 Jul 2026 17:59:55 -0500 Subject: [PATCH] ci: build & publish app + bot images to Gitea registry on merge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a Gitea Actions workflow (.gitea/workflows/build-images.yml) that fires on push to main (and workflow_dispatch). On the always-on ubuntu-latest runner it: - verifies the host Docker daemon is reachable (socket must be mounted) - logs into gitea.whitlocktech.com with a PAT (REGISTRY_USER / REGISTRY_TOKEN) - builds & pushes both images from the existing Dockerfiles, each tagged :latest and :sha-<7>: gitea.whitlocktech.com//website-app (./Dockerfile — server+client) gitea.whitlocktech.com//website-bot (./bot/Dockerfile) Raw docker CLI (no marketplace actions) for portability on self-hosted Gitea; the shared host daemon gives free layer caching between runs. Registry owner is lowercased for Docker refs. Deploy (compose image: + pull) is a follow-up. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_0114TpmrNW4wNXsHq5CR72jQ --- .gitea/workflows/build-images.yml | 87 +++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 .gitea/workflows/build-images.yml diff --git a/.gitea/workflows/build-images.yml b/.gitea/workflows/build-images.yml new file mode 100644 index 0000000..6acdd24 --- /dev/null +++ b/.gitea/workflows/build-images.yml @@ -0,0 +1,87 @@ +# Build and publish the app + bot container images to Gitea's container registry +# on every merge to main. Production then pulls prebuilt images instead of +# building on the host. +# +# Prerequisites (one-time): +# • An always-on Gitea runner with label `ubuntu-latest` whose jobs have the +# host Docker socket mounted (/var/run/docker.sock), so `docker build` talks +# to the host daemon. This also gives free layer caching between runs. +# • Two repo secrets (Settings → Actions → Secrets): +# REGISTRY_USER — the Gitea username that owns the token below +# REGISTRY_TOKEN — a Gitea access token with `write:package` (+ read:package) +# See the PR description / README for step-by-step token creation. +# +# Produces, in gitea.whitlocktech.com// : +# website-app:latest + website-app:sha-<7> +# website-bot:latest + website-bot:sha-<7> + +name: Build container images + +on: + push: + branches: [main] + workflow_dispatch: {} + +concurrency: + group: images-${{ github.ref }} + cancel-in-progress: true + +env: + REGISTRY: gitea.whitlocktech.com + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Check out the merged commit + uses: actions/checkout@v4 + + - name: Derive image refs (registry owner must be lowercase for Docker) + run: | + set -euo pipefail + OWNER="$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')" + SHORT_SHA="${GITHUB_SHA:0:7}" + echo "APP_IMAGE=${REGISTRY}/${OWNER}/website-app" >> "$GITHUB_ENV" + echo "BOT_IMAGE=${REGISTRY}/${OWNER}/website-bot" >> "$GITHUB_ENV" + echo "TAG=sha-${SHORT_SHA}" >> "$GITHUB_ENV" + + - name: Verify the Docker daemon is reachable + # Fails fast with a clear message if the host socket isn't mounted into + # the job container (the one hard runner prerequisite). + run: | + set -euo pipefail + if ! docker info >/dev/null 2>&1; then + echo "::error::Docker daemon not reachable. Mount /var/run/docker.sock into the runner's job containers." + exit 1 + fi + echo "Docker daemon OK" + + - name: Log in to the Gitea container registry + run: | + set -euo pipefail + echo "${{ secrets.REGISTRY_TOKEN }}" \ + | docker login "${REGISTRY}" -u "${{ secrets.REGISTRY_USER }}" --password-stdin + + - name: Build & push the app image (server + client) + run: | + set -euo pipefail + docker build -f Dockerfile \ + -t "${APP_IMAGE}:latest" \ + -t "${APP_IMAGE}:${TAG}" \ + . + docker push "${APP_IMAGE}:latest" + docker push "${APP_IMAGE}:${TAG}" + + - name: Build & push the bot image + run: | + set -euo pipefail + docker build -f bot/Dockerfile \ + -t "${BOT_IMAGE}:latest" \ + -t "${BOT_IMAGE}:${TAG}" \ + . + docker push "${BOT_IMAGE}:latest" + docker push "${BOT_IMAGE}:${TAG}" + + - name: Log out (clear cached credentials from the runner) + if: always() + run: docker logout "${REGISTRY}" || true -- 2.49.1