Files
scoreodonto.com/.gitea/workflows/build.yml
T
VPS 4 Builder 715b2dc81e
build-and-promote / build (push) Has been skipped
build-and-promote / promote (push) Successful in 1m8s
ci(build): desbloqueia build — SCOREO_DB_PASS placeholder na interpolação
O compose interpola environment: (com fail-fast `:?` em SCOREO_DB_PASS)
mesmo só no `docker compose build`, e o runner não tem .env → build abortava
(run #29, commit 8a27f3b). SCOREO_DB_PASS é runtime-only (environment:, não
build-arg), então um placeholder satisfaz a interpolação sem entrar na imagem.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 00:00:16 +02:00

126 lines
5.5 KiB
YAML

name: build-and-promote
# Passo 5 — Build Once → Promote → Deploy:
# • push na main → job BUILD: builda 1x e publica por COMMIT (:<sha> + :latest). NÃO deploya.
# • tag vX.Y.Z → job PROMOTE: re-tagueia a imagem do commit como :vX.Y.Z (SEM rebuild),
# valida integridade e deploya na VPS1.
# A versão semântica NÃO entra no build: nasce da tag e é injetada no deploy em runtime
# (docker-compose.prod.yml). Não há mais APP_VERSION/constants.ts.
on:
push:
branches: [main]
tags: ['v*']
jobs:
# ───────────────────────── BUILD (só em push de branch) ─────────────────────────
build:
if: startsWith(github.ref, 'refs/heads/')
runs-on: self-hosted
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Vars (commit + data)
id: vars
run: |
echo "commit=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
echo "build_time=$(date -u +'%Y-%m-%d %H:%M UTC')" >> "$GITHUB_OUTPUT"
- name: Login no registry
run: |
if [ -n "${{ secrets.REGISTRY_TOKEN }}" ]; then
echo "${{ secrets.REGISTRY_TOKEN }}" | docker login git.clube67.com -u ruicesar --password-stdin
else
echo "REGISTRY_TOKEN ausente — usando a credencial já presente no host."
fi
- name: Build (carimba commit/data; versão vem da tag no deploy, não aqui)
env:
COMPOSE_PROJECT_NAME: scoreodontocom
GIT_COMMIT: ${{ steps.vars.outputs.commit }}
BUILD_TIME: ${{ steps.vars.outputs.build_time }}
APP_ENV: PROD
# SCOREO_DB_PASS tem fail-fast `:?` no compose (runtime). No build é só interpolado,
# nunca entra na imagem (é `environment:`, não build-arg) — placeholder satisfaz o compose.
SCOREO_DB_PASS: build-placeholder
run: docker compose build scoreodonto-backend scoreodonto-frontend
- name: Publicar por COMMIT (:<sha> + :latest), com retry p/ 499
run: |
set -e
REG=git.clube67.com/ruicesar
C="${{ steps.vars.outputs.commit }}"
for app in backend frontend; do
SRC="scoreodontocom-scoreodonto-${app}:latest"
DST="${REG}/scoreodonto-${app}"
docker tag "$SRC" "$DST:$C"
docker tag "$SRC" "$DST:latest"
for tag in "$C" "latest"; do
n=0
until docker push "$DST:$tag"; do
n=$((n+1)); [ $n -ge 4 ] && { echo "push falhou: $DST:$tag"; exit 1; }
echo "retry $n (499 transitório) em $DST:$tag"; sleep 3
done
done
done
echo "Publicado: scoreodonto-{backend,frontend}:$C (+ :latest). Push NÃO deploya."
# ─────────────────────── PROMOTE (só em tag vX.Y.Z) ───────────────────────
promote:
if: startsWith(github.ref, 'refs/tags/v')
runs-on: self-hosted
steps:
- name: Checkout (na tag)
uses: actions/checkout@v4
- name: Vars (tag + commit)
id: vars
run: |
echo "version=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT"
echo "commit=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
- name: Login no registry
run: |
if [ -n "${{ secrets.REGISTRY_TOKEN }}" ]; then
echo "${{ secrets.REGISTRY_TOKEN }}" | docker login git.clube67.com -u ruicesar --password-stdin
fi
- name: Integridade — a imagem do commit existe? (nunca buildar na tag)
run: |
set -e
REG=git.clube67.com/ruicesar
C="${{ steps.vars.outputs.commit }}"
for app in backend frontend; do
if ! docker buildx imagetools inspect "${REG}/scoreodonto-${app}:$C" >/dev/null 2>&1; then
echo "ERRO: ${REG}/scoreodonto-${app}:$C não existe no registry."
echo " Faça 'git push origin main' (que builda o commit $C) ANTES de criar a tag."
exit 1
fi
done
echo "OK: backend:$C e frontend:$C presentes — mesmo commit $C (front+back atômicos)."
- name: Promover — re-tag commit → versão (SEM rebuild) + conferir digest
run: |
set -e
REG=git.clube67.com/ruicesar
C="${{ steps.vars.outputs.commit }}"; V="${{ steps.vars.outputs.version }}"
for app in backend frontend; do
DST="${REG}/scoreodonto-${app}"
docker buildx imagetools create -t "$DST:$V" "$DST:$C"
dC=$(docker buildx imagetools inspect "$DST:$C" --format '{{.Manifest.Digest}}')
dV=$(docker buildx imagetools inspect "$DST:$V" --format '{{.Manifest.Digest}}')
[ "$dC" = "$dV" ] || { echo "ERRO: digest divergiu em $app ($V=$dV != $C=$dC)"; exit 1; }
echo "$app: $V -> $C (digest $dV)"
done
echo "Promovido sem rebuild: a imagem :$V E a imagem :$C (mesmo artefato)."
- name: Deploy na VPS1 (pull :versao + up --no-build; versao injetada em runtime)
run: |
set -e
V="${{ steps.vars.outputs.version }}"
scp -o StrictHostKeyChecking=accept-new \
docker-compose.prod.yml deploy-prod.sh \
deploy@10.99.0.1:/home/deploy/stack/scoreodonto.com/
ssh -o StrictHostKeyChecking=accept-new deploy@10.99.0.1 \
"/home/deploy/stack/scoreodonto.com/deploy-prod.sh $V"