ci(azure): repoint dev CI + registry to Azure VM #2076

Merged
sapl-admin merged 2 commits from feat/azure-vm-ci into dev 2026-11-03 16:56:58 +00:00
6 changed files with 49 additions and 42 deletions
+12 -12
View File
@@ -48,15 +48,15 @@ jobs:
}
docker --version
# Helper container with host Docker + registry token. Mount sources
# resolve on the HOST (the daemon), so no runner config change is
# needed. The repo is cloned FRESH inside the helper (depth 1,
# authenticated via the per-run GITHUB_TOKEN) — never touching the
# shared dokploy checkouts, which a concurrent deploy may be
# building from.
# Helper container with host Docker. Mount sources resolve on the HOST
# (the daemon), so no runner config change is needed. Registry auth
# comes from the REGISTRY_TOKEN repo secret (env). The repo is cloned
# FRESH inside the helper (depth 1, authenticated via the per-run
# GITHUB_TOKEN) — never touching the shared deploy checkouts, which
# a concurrent deploy may be building from.
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /root/.hermes/registry-token.txt:/run/secrets/registry-token:ro \
-e REGISTRY_TOKEN=${{ secrets.REGISTRY_TOKEN }} \
-e DISPATCH_REF=${{ github.ref }} \
-e INPUT_REF=${{ github.event.inputs.ref }} \
-e CLONE_TOKEN=${{ secrets.GITHUB_TOKEN }} \
@@ -92,7 +92,7 @@ jobs:
echo "FATAL: CLONE_TOKEN empty - secrets.GITHUB_TOKEN unavailable?" >&2
exit 1
fi
git clone --depth 1 --branch "$BRANCH" "https://oauth2:${CLONE_TOKEN}@gitea.ai-automation-hub.tech/sapl/sapl.git" /work/sapl
git clone --depth 1 --branch "$BRANCH" "https://oauth2:${CLONE_TOKEN}@git.ai-automation-hub.tech/sapl/sapl.git" /work/sapl
unset CLONE_TOKEN
cd /work/sapl
@@ -101,15 +101,15 @@ jobs:
# tag); the sha tag keeps each base build identifiable.
SHA="$(git rev-parse --short=8 HEAD)"
TAG="dev-${SHA}"
REGISTRY="gitea.ai-automation-hub.tech"
REGISTRY="git.ai-automation-hub.tech"
IMAGE="sapl-deploy-bot/sapl-backend-base"
REGISTRY_USER="sapl-deploy-bot"
PLATFORM="linux/amd64"
echo "==> Building backend base for [$BRANCH] @ [$SHA] -> [$REGISTRY/$IMAGE:$TAG]"
REG_TOKEN="$(cat /run/secrets/registry-token 2>/dev/null || true)"
REG_TOKEN="$(cat /run/secrets/registry-token 2>/dev/null || echo "${REGISTRY_TOKEN:-}")"
if [ -z "$REG_TOKEN" ]; then
echo "FATAL: no registry token (/run/secrets/registry-token)" >&2
echo "FATAL: no registry token (REGISTRY_TOKEN secret or /run/secrets/registry-token)" >&2
exit 1
fi
echo "$REG_TOKEN" | docker login "$REGISTRY" -u "$REGISTRY_USER" --password-stdin >/dev/null 2>&1
@@ -117,7 +117,7 @@ jobs:
# Context is backend/ (Dockerfile.base COPYs requirements-base.txt
# from it). The build runs on the HOST daemon, so the image is
# local for every same-VPS tier build afterwards; the push makes
# local for every same-host tier build afterwards; the push makes
# it available to registry-authenticated pulls (dev deploy).
docker build --platform "$PLATFORM" \
-t "$REGISTRY/$IMAGE:$TAG" \
+25 -18
View File
@@ -12,7 +12,7 @@ on:
# One deploy at a time per branch (added for the CI speed milestone, issue #1151).
# Two merges landing close together used to queue two CONCURRENT deploy jobs against the
# one shared checkout (/etc/dokploy/compose/sapl-sapl-dev/code), which produced both of
# one shared checkout (/opt/sapl/dev), which produced both of
# our known deploy failure modes:
# - "fatal: cannot lock ref 'HEAD': Unable to create '.../refs/heads/dev.lock': File exists"
# - "Conflict. The container name '/<hash>_sapl-sapl-dev-backend-1' is already in use"
@@ -62,7 +62,7 @@ jobs:
steps:
- name: Deploy to Dev via Host Docker
run: |
echo "🚀 Deploying sapl Dev — laptop-first frontend build + registry pull..."
echo "🚀 Deploying sapl Dev on the Azure VM host — frontend build + registry push/pull..."
# Install Docker CLI (runner is node:20-bullseye). Debian bullseye is
# EOL (Aug 2026) — debian-security AND main both 404 on deb.debian.org
@@ -83,20 +83,19 @@ jobs:
}
docker --version
# Helper container with host Docker + filesystem access + the
# laptop-build SSH key and registry token. Mount sources resolve on
# the HOST (the daemon), so no runner config change is needed.
# Laptop-first builds: LAPTOP_HOST + LAPTOP_SSH_USER enable the
# laptop build path (see scripts/build-frontend-dev.sh) — the script
# falls back to the VPS automatically when the laptop is offline.
# Helper container with host Docker + filesystem access + the registry
# token (Azure VM host). Mount sources resolve on the HOST (the
# daemon), so no runner config change is needed.
# No laptop build path here: LAPTOP_* stay unset so the script
# always builds locally (see scripts/build-frontend-dev.sh).
# Git auth for the checkout sync comes from the hermes credential
# file (host path, read-only); the checkout stays hermes-owned via
# the chown at the end (the helper runs as root).
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /etc/dokploy/compose/sapl-sapl-dev/code:/code \
-v /root/.hermes/ssh/laptop_build_ed25519:/root/.ssh/id_ed25519:ro \
-v /root/.hermes/ssh/known_hosts:/root/.ssh/known_hosts:ro \
-v /root/.hermes/registry-token.txt:/run/secrets/registry-token:ro \
-e LAPTOP_HOST=100.67.2.63 \
-e LAPTOP_SSH_USER=shridharsabat \
-v /opt/sapl/dev:/code \
-v /home/hermes/.git-credentials:/root/.git-credentials:ro \
-e REGISTRY_TOKEN=${{ secrets.REGISTRY_TOKEN }} \
-w /code \
docker:28-cli \
sh -c '
@@ -110,15 +109,23 @@ jobs:
timeout 60 apk add --no-cache git openssh-client 2>/dev/null && break || echo "⚠️ apk mirror $AM failed, trying next..."
done
command -v git >/dev/null || { echo "❌ all apk mirrors failed — failing fast, please re-run"; exit 1; }
# Helper runs as root on a hermes-owned checkout: allow it + use
# the mounted credential file for the authenticated fetch below.
git config --global --add safe.directory /code
git config --global credential.helper store
# Bootstrap: sync the host checkout BEFORE running the script —
# the script itself re-syncs and self-heals, but must EXIST in the
# checkout first (first run after any workflow/script change).
git -C /code fetch origin dev 2>/dev/null
git -C /code checkout -f dev 2>/dev/null || git -C /code checkout -f FETCH_HEAD
git -C /code reset --hard origin/dev
# Builds frontend (laptop-first, VPS fallback), pushes to the
# Gitea registry, then `compose up -d` with FRONTEND_TAG set.
# Builds frontend locally, pushes to the Azure Gitea registry,
# then `compose up -d` with FRONTEND_TAG set.
sh /code/scripts/build-frontend-dev.sh
# Restore checkout ownership (helper runs as root; .env.dev is
# the hermes-owned reference). BusyBox chown has NO --reference:
# resolve uid:gid via stat first (both exist in docker:28-cli).
chown -R "$(stat -c '%u:%g' /code/.env.dev)" /code
' 2>&1
echo "✅ Dev deploy complete!"
@@ -130,7 +137,7 @@ jobs:
run: |
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /etc/dokploy/compose/sapl-sapl-dev/code:/code \
-v /opt/sapl/dev:/code \
docker:28-cli \
sh -c '
HOST_MD5=$(md5sum /code/backend/routers/tna.py | cut -c1-32)
@@ -141,7 +148,7 @@ jobs:
echo "⚠️ BACKEND CONTAINER STALE vs checkout — compose --build reused the cache."
# refs #2034: worker shares the backend built image (no worker
# build block), so the rebuild is backend-only below.
echo " Fix: cd /etc/dokploy/compose/sapl-sapl-dev/code && docker compose --env-file .env.dev -f docker-compose.dev.yml -p sapl-sapl-dev build backend && docker compose --env-file .env.dev -f docker-compose.dev.yml -p sapl-sapl-dev up -d backend worker"
echo " Fix: cd /opt/sapl/dev && docker compose --env-file .env.dev -f docker-compose.dev.yml -p sapl-sapl-dev build backend && docker compose --env-file .env.dev -f docker-compose.dev.yml -p sapl-sapl-dev up -d backend worker"
fi
'
+1 -1
View File
@@ -12,7 +12,7 @@
# ORDERING: the base image MUST exist in the registry (or the local daemon)
# before this builds. After any base-source change (Dockerfile.base,
# requirements-base.txt), dispatch build-base-image.yml FIRST, then deploy.
FROM gitea.ai-automation-hub.tech/sapl-deploy-bot/sapl-backend-base:dev-latest
FROM git.ai-automation-hub.tech/sapl-deploy-bot/sapl-backend-base:dev-latest
WORKDIR /app
+3 -3
View File
@@ -187,10 +187,10 @@ services:
cpus: '0.75'
frontend:
# Image is built by scripts/build-frontend-dev.sh (laptop-first, VPS
# fallback) and pushed to the Gitea container registry. FRONTEND_TAG is
# Image is built by scripts/build-frontend-dev.sh (local build on the VM host)
# and pushed to the Gitea container registry. FRONTEND_TAG is
# injected by the deploy script; dev-latest keeps a manual `up -d` working.
image: "gitea.ai-automation-hub.tech/sapl-deploy-bot/sapl-frontend:${FRONTEND_TAG:-dev-latest}"
image: "git.ai-automation-hub.tech/sapl-deploy-bot/sapl-frontend:${FRONTEND_TAG:-dev-latest}"
pull_policy: always
depends_on:
backend:
+1 -1
View File
@@ -62,7 +62,7 @@ UAT (User Acceptance Testing) is a **separate, isolated environment** where new
| Service | Production | UAT |
|---------|:----------:|:----:|
| **Web App** | [sapl.ai-automation-hub.tech](https://sapl.ai-automation-hub.tech) | [uat.ai-automation-hub.tech](https://uat.ai-automation-hub.tech) |
| **Gitea** | [gitea.ai-automation-hub.tech](https://gitea.ai-automation-hub.tech) | — |
| **Gitea** | [git.ai-automation-hub.tech](https://git.ai-automation-hub.tech) | — |
| **Dokploy** | [dokploy.ai-automation-hub.tech](https://dokploy.ai-automation-hub.tech) | — |
---
+7 -7
View File
@@ -1,20 +1,20 @@
#!/bin/sh
# build-frontend-dev.sh — laptop-first SAPL frontend image build + registry push,
# with automatic VPS fallback, then compose deploy of the dev stack.
# with automatic local fallback, then compose deploy of the dev stack.
#
# Runs inside the deploy job's docker:28-cli helper container (Alpine). Expected mounts:
# /code → host deploy checkout (e.g. /etc/dokploy/compose/sapl-sapl-dev/code)
# /code → host deploy checkout (e.g. /opt/sapl/dev)
# /var/run/docker.sock → host docker daemon
# /root/.ssh/id_ed25519 → Hermes laptop-build SSH key (read-only)
# /root/.ssh/known_hosts → laptop host key (read-only, may be empty)
# /run/secrets/registry-token → Gitea package token (read-only)
# /run/secrets/registry-token → Gitea package token (read-only; or REGISTRY_TOKEN env)
#
# Flow:
# 1. Reset the checkout to origin/<BRANCH> exactly
# 2. Login to the Gitea container registry
# 3. If LAPTOP_HOST + LAPTOP_SSH_USER are set AND the laptop answers SSH:
# sync frontend/ via tar-over-ssh → build + push ON THE LAPTOP
# else: build + push on the VPS (today's behaviour)
# else: build + push on the host (local fallback)
# 4. `docker compose up -d` with FRONTEND_TAG=<dev-<sha>> so the stack pulls
# the freshly pushed image (compose frontend service has pull_policy: always).
# Also tags/pushes dev-latest so a plain manual `up -d` always works.
@@ -25,7 +25,7 @@ BRANCH="${BRANCH:-dev}"
PROJECT="${PROJECT:-sapl-sapl-dev}"
COMPOSE_FILE="${COMPOSE_FILE:-docker-compose.dev.yml}"
ENV_FILE="${ENV_FILE:-.env.dev}"
REGISTRY="${REGISTRY:-gitea.ai-automation-hub.tech}"
REGISTRY="${REGISTRY:-git.ai-automation-hub.tech}"
IMAGE="${IMAGE:-sapl-deploy-bot/sapl-frontend}" # bot's user namespace (verified push access)
REGISTRY_USER="${REGISTRY_USER:-sapl-deploy-bot}"
PLATFORM="${PLATFORM:-linux/amd64}"
@@ -92,11 +92,11 @@ if [ -n "$LAPTOP_TARGET" ] && ssh $SSHOPTS "$LAPTOP_TARGET" "command -v podman >
"; then
echo "==> Laptop build+push OK"
else
echo "==> Laptop build failed/timed out (exit $?) — building on VPS (fallback)"
echo "==> Laptop build failed/timed out (exit $?) — building locally (fallback)"
build_and_push_local /code/frontend
fi
else
echo "==> Laptop DOWN/unconfigured — building on VPS (fallback)"
echo "==> Laptop DOWN/unconfigured — building locally (fallback)"
build_and_push_local /code/frontend
fi