ci: manual workflow to build and publish the QA image (#25)
SonarQube Analysis / sonarqube (pull_request) Successful in 2m34s
Tests / backend-unit (pull_request) Successful in 36s
Tests / backend-integration (pull_request) Failing after 3h3m42s
Tests / frontend-e2e (pull_request) Failing after 7m32s

Adds a workflow_dispatch job that builds a chosen ref, pushes it to the
Gitea container registry as :qa plus a commit-sha tag, and emails when it
is ready. It deliberately does not restart the QA stack — redeploying
stays a human action in Portainer.

The build runs against a Docker-in-Docker service rather than the NAS's
Docker socket. Mounting the host socket into the runner would give every
workflow on every branch root-equivalent control of the NAS, production
included; pushing to a registry means the image does not need to survive
in the build daemon.

The QA stack now pulls that image instead of requiring a local build. The
previous arrangement meant the image existed only if someone remembered
to build it, which produced two confusing failures already: a Docker Hub
"pull access denied" when the tag was missing, and a silent stale-image
deploy when the build had not been rerun.

Two runner capabilities cannot be verified from here — privileged service
containers for dind, and a docker CLI in the runner image. The workflow
checks both and fails with an explanation rather than a connection
refused, and validates all five required secrets and variables up front
rather than part-way through a build.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-17 19:10:04 -05:00
co-authored by Claude Opus 5
parent db7c61c89d
commit 2a20c0e05b
2 changed files with 164 additions and 12 deletions
+12 -12
View File
@@ -17,23 +17,23 @@
# QA_DB_PASSWORD — deliberately not named DB_PASSWORD, so pasting the
# production stack's variables here does nothing silently.
#
# BUILD THE IMAGE BEFORE DEPLOYING THIS STACK. redefined-designs:qa exists only
# on the NAS and is never pushed to a registry, so deploying first makes Compose
# fall back to pulling from Docker Hub and fail with a misleading
# "pull access denied ... repository does not exist or may require docker login".
# The image comes from the Gitea container registry, built by the manual
# "Build QA Image" workflow. Redeploy this stack with Portainer's
# "Pull latest image" toggle ON, or it will keep running the image it already
# has and the redeploy will appear to do nothing.
#
# sudo docker build --no-cache -t redefined-designs:qa /volume1/docker/redefined-designs
# Portainer needs registry credentials for gitea.bermudalamb.synology.me once
# (Registries > Add registry, custom, with a Gitea token that has read:package).
#
# For the same reason, leave Portainer's "Pull latest image" toggle off.
# `pull_policy: never` below makes a missing image report itself as missing
# rather than as a registry authentication problem. If the Docker Compose
# version on the NAS ever rejects that key, it is safe to delete the line — it
# only improves the error message.
# This replaced a locally-built `redefined-designs:qa` with `pull_policy: never`.
# That arrangement meant the image existed only if someone had remembered to
# build it, which produced two confusing deploy failures: a "pull access denied"
# from Docker Hub when the tag was missing entirely, and a silent stale-image
# deploy when the build had not been rerun.
services:
redefined-designs-qa:
image: redefined-designs:qa
pull_policy: never
image: gitea.bermudalamb.synology.me/bermudalamb/redefined-designs:qa
container_name: redefined-designs-qa-syn
environment:
- TZ=America/Chicago