#!/bin/bash # Build and push the JellyTau builder Docker image to your registry set -e # Configuration REGISTRY_HOST="${REGISTRY_HOST:-gitea.tourolle.paris}" REGISTRY_USER="${REGISTRY_USER:-dtourolle}" IMAGE_NAME="jellytau-builder" IMAGE_TAG="${1:-latest}" FULL_IMAGE_NAME="${REGISTRY_HOST}/${REGISTRY_USER}/${IMAGE_NAME}:${IMAGE_TAG}" echo "🐳 Building JellyTau Builder Image" echo "==================================" echo "Registry: $REGISTRY_HOST" echo "User: $REGISTRY_USER" echo "Image: $FULL_IMAGE_NAME" echo "" # Step 1: Build locally echo "🔨 Building Docker image locally..." docker build -f Dockerfile.builder -t ${IMAGE_NAME}:${IMAGE_TAG} . # Step 2: Tag for registry echo "🏷️ Tagging for registry..." docker tag ${IMAGE_NAME}:${IMAGE_TAG} ${FULL_IMAGE_NAME} # Step 3: Login to registry (if not already logged in) # # `docker info | grep Username` only ever reports a Docker Hub session, so for a # private registry it never matched — meaning this branch fired on every push and # dropped into an interactive `docker login`, which hangs any non-interactive run # (a scripted release, or CI). Check the credential store for this specific # registry instead, and refuse rather than prompt when there is no TTY to # prompt on. echo "🔐 Checking registry authentication..." DOCKER_CFG="${DOCKER_CONFIG:-$HOME/.docker}/config.json" if ! grep -q "\"${REGISTRY_HOST}\"" "$DOCKER_CFG" 2>/dev/null; then if [ -t 0 ]; then echo "Not authenticated to ${REGISTRY_HOST}. Logging in..." docker login "${REGISTRY_HOST}" else echo "❌ Not authenticated to ${REGISTRY_HOST}, and stdin is not a TTY." echo " Run this first: docker login ${REGISTRY_HOST}" exit 1 fi else echo " Using stored credentials for ${REGISTRY_HOST}." fi # Step 4: Push to registry # # Two tags, on purpose: # # what the workflows pin (e.g. :2026.08). CI must name an immutable # tag -- while every job said :latest, rebuilding the image silently # changed what every build, including a rebuild of an old release # tag, compiled against. That is the opposite of reproducible. # latest convenience for local `docker compose` runs and for anyone pulling # the image by hand. # # Date tags rather than per-commit SHA tags: the Gitea runner shares a 74 GB # disk with two other projects, and SHA-tagged images accumulated there until it # filled. Keep at most a couple of dated tags live and prune the rest # (`docker image prune -a` on the runner). # # To bump: build+push a new dated tag, then update the `image:` lines in # .gitea/workflows/*.yml in the same commit as whatever needed the new tool. echo "📤 Pushing image to registry..." docker push ${FULL_IMAGE_NAME} if [ "$IMAGE_TAG" != "latest" ]; then echo "🏷️ Also tagging as :latest for local use..." LATEST_IMAGE_NAME="${REGISTRY_HOST}/${REGISTRY_USER}/${IMAGE_NAME}:latest" docker tag ${IMAGE_NAME}:${IMAGE_TAG} ${LATEST_IMAGE_NAME} docker push ${LATEST_IMAGE_NAME} fi echo "" echo "✅ Successfully built and pushed: ${FULL_IMAGE_NAME}" echo "" echo "Workflows must pin the dated tag, not :latest --" echo " container:" echo " image: ${FULL_IMAGE_NAME}" echo "" echo "Currently pinned in .gitea/workflows/:" grep -ho "jellytau-builder:[A-Za-z0-9._-]*" "$(git rev-parse --show-toplevel)"/.gitea/workflows/*.yml 2>/dev/null | sort -u | sed "s/^/ /"