Files
website/.gitea/workflows/build-images.yml
Claude 4f24959d49 ci: build & publish app + bot images to Gitea registry on merge
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/<owner>/website-app  (./Dockerfile — server+client)
      gitea.whitlocktech.com/<owner>/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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0114TpmrNW4wNXsHq5CR72jQ
2026-07-11 17:59:55 -05:00

88 lines
3.1 KiB
YAML

# 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/<owner>/ :
# 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