Files
redefined-designs/.gitea/workflows/spike-registry.yml
T
bermudalamb a73f7017f2
Linting / lint (pull_request) Successful in 2m7s
SonarQube Analysis / sonarqube (pull_request) Successful in 19m45s
spike(ci): install a docker CLI so the registry probe can get past login (#237)
The first run answered Question 1 with a flat no. The job container has no docker binary, so login died with exit 127 and the three steps that mattered were skipped — no answer on whether the registry accepts a push, and no build time.

What it did establish is that /var/run/docker.sock is mounted. The daemon is reachable; only the client is missing. That is a gap a step can close without reconfiguring the runner, so it is worth one more iteration before deciding anything.

The static binary rather than apt: one download, no package index to refresh, no repository to add, and only the CLI is wanted since the daemon already exists on the other side of that socket.

The architecture is resolved with uname rather than hardcoded. Nothing in this repository has ever confirmed what the NAS is, and assuming x86_64 would waste a whole run on the one machine everything else queues behind — the same class of mistake as assuming Portainer's build context contained .git in #235.

This step is deliberately not continue-on-error, unlike the diagnostics above it. If the client cannot be installed there is nothing left to measure, and one clear failure reads better than three skipped steps.

Still workflow_dispatch only, still bounded by timeout-minutes, still deleted when #237 is answered.

Ref #237
2026-08-30 14:54:53 -05:00

149 lines
6.9 KiB
YAML

name: SPIKE — registry build and push
# THROWAWAY. Delete this file when #237 is answered, whichever way it goes.
#
# It exists to answer three questions that cannot be answered by reading
# anything in this repository, before a design is built on assumptions about
# them. #233 was designed on an assumption about the build context and broke
# every Portainer deploy; this is the correction to that habit.
#
# 1. Can a job on this runner run `docker build` at all? The other workflows
# use `services:`, which proves the runner can *start* containers, not
# that a job can build images. That needs a Docker socket or buildx.
# 2. Can it push to this Gitea's container registry? The packages API answers
# and lists nothing, so the registry has never been used here and
# "enabled" is unconfirmed.
# 3. How long does the real image take to build here? Not a nice-to-know:
# backend-integration.yml is manual because a job once held this runner
# for 3h12m, and any design that builds on every merge to main lands on
# the same runner.
#
# workflow_dispatch only. It cannot fire on push or pull request, so merging it
# changes nothing until someone presses the button.
on:
workflow_dispatch:
env:
REGISTRY: gitea.bermudalamb.synology.me
# Gitea's container registry namespaces by owner: <host>/<owner>/<image>.
IMAGE: gitea.bermudalamb.synology.me/bermudalamb/redefined-designs
jobs:
spike:
runs-on: ubuntu-latest
# The same reasoning as backend-integration.yml: not a performance budget,
# a stop so that a hang costs minutes rather than hours of a runner that
# everything else queues behind.
timeout-minutes: 25
steps:
- name: Checkout
uses: actions/checkout@v4
# First, and never failing, so that a failure in any later step is still
# informative rather than just "it did not work".
- name: Question 1 — what can this runner do?
continue-on-error: true
run: |
echo "--- docker client/daemon ---"
docker version || echo "NO DOCKER CLI OR DAEMON"
echo "--- buildx ---"
docker buildx version || echo "NO BUILDX"
echo "--- socket ---"
ls -l /var/run/docker.sock || echo "NO DOCKER SOCKET"
echo "--- disk ---"
df -h / | tail -1
# Iteration 2. The first run answered Question 1 with "no": the job
# container has no `docker` binary and login died with exit 127. What it
# also showed is that /var/run/docker.sock IS mounted, so the daemon is
# reachable and only the client is missing — which is a gap this step can
# close without changing how the runner itself is configured.
#
# The static binary rather than apt: it is one download with no package
# index to refresh and no repository to add, and only the CLI is wanted.
# The daemon already exists on the other side of that socket.
#
# Not continue-on-error. If this fails there is nothing left to measure,
# and a clear failure here is more useful than three skipped steps.
- name: Install the docker CLI, since the runner has none
run: |
DOCKER_VERSION=27.3.1
# Resolved rather than assumed. The NAS's architecture has never been
# confirmed anywhere in this repository, and hardcoding x86_64 would
# waste a whole run on a machine that everything else queues behind.
case "$(uname -m)" in
x86_64) DOCKER_ARCH=x86_64 ;;
aarch64|arm64) DOCKER_ARCH=aarch64 ;;
*) echo "unsupported architecture $(uname -m) — no static docker build for it"; exit 1 ;;
esac
echo "runner architecture: $(uname -m) -> downloading $DOCKER_ARCH"
curl -fsSL "https://download.docker.com/linux/static/stable/${DOCKER_ARCH}/docker-${DOCKER_VERSION}.tgz" -o /tmp/docker.tgz
tar -xzf /tmp/docker.tgz -C /tmp
install -m 0755 /tmp/docker/docker /usr/local/bin/docker
docker version
echo "--- can it reach the daemon through the socket? ---"
docker info --format 'server {{.ServerVersion}}, {{.Driver}}, {{.Architecture}}'
# Reported as a boolean, never printed. If this says NO, the login below
# will fail and the fix is to add the secret, not to change the workflow.
- name: Is a token available?
continue-on-error: true
run: |
if [ -n "${{ secrets.GITEA_TOKEN }}" ]; then
echo "GITEA_TOKEN is present"
else
echo "GITEA_TOKEN is EMPTY — add a repo secret with package write scope"
fi
- name: Question 2a — log in to the registry
run: |
echo "${{ secrets.GITEA_TOKEN }}" \
| docker login "$REGISTRY" -u "${{ github.actor }}" --password-stdin
# A trivial image first, deliberately. It separates "can this runner build
# and push anything" from "does our real Dockerfile work here" — if the
# real build fails later, this having passed says the plumbing is fine and
# the problem is ours.
- name: Question 2b — build and push a trivial image
run: |
mkdir -p /tmp/spike
printf 'FROM alpine:3.20\nRUN echo spike > /spike.txt\n' > /tmp/spike/Dockerfile
docker build -t "$IMAGE:spike-trivial" /tmp/spike
docker push "$IMAGE:spike-trivial"
echo "pushed $IMAGE:spike-trivial"
# The real thing, timed. The tag records the commit so that the pulled
# image can be checked against what was built — which is the whole point
# of the design this spike is testing.
- name: Question 3 — build the real image and time it
run: |
SHORT_SHA="$(git rev-parse --short HEAD)"
echo "building $IMAGE:spike-$SHORT_SHA"
START=$(date +%s)
docker build -t "$IMAGE:spike-$SHORT_SHA" .
END=$(date +%s)
echo "REAL BUILD TOOK $((END - START)) SECONDS"
docker push "$IMAGE:spike-$SHORT_SHA"
echo "pushed $IMAGE:spike-$SHORT_SHA"
# Proves the commit can actually be baked in, which is the reason for the
# whole exercise. In a Gitea Actions checkout .git is present, unlike in
# Portainer's build context — that difference is exactly what #235 was.
- name: Does the built image know its own commit?
continue-on-error: true
run: |
SHORT_SHA="$(git rev-parse --short HEAD)"
echo "git says: $SHORT_SHA"
echo "image says:"
docker run --rm "$IMAGE:spike-$SHORT_SHA" cat dist/buildInfo.json || echo "no stamp"
- name: What to do next
if: always()
run: |
echo "If the pushes succeeded, try pulling from Portainer:"
echo " 1. Portainer > Registries > Add registry > Custom"
echo " URL: $REGISTRY (username + a token with package read)"
echo " 2. docker pull $IMAGE:spike-trivial"
echo "Then delete this workflow and the spike-* packages. See #237."