fix(ci): deploy atomico no Forgejo (symlink)

This commit is contained in:
esdrasrenan 2025-12-17 01:44:00 -03:00
parent 2bdc5ae882
commit 380b2e44e9

View file

@ -189,48 +189,38 @@ jobs:
chown -R 1000:1000 /target
echo "Permissoes do build corrigidas"
- name: Publish build to stable APP_DIR directory
- name: Atualizar symlink do APP_DIR estavel (deploy atomico)
run: |
set -e
DEST="$HOME/apps/sistema"
PARENT_DIR="$HOME/apps"
set -euo pipefail
ROOT="$HOME/apps"
STABLE_LINK="$ROOT/sistema.current"
# SOLUCAO DEFINITIVA: Limpar completamente o destino usando Docker (root)
# Isso evita erros de permissao de arquivos criados por Docker em deploys anteriores
if [ -d "$DEST" ]; then
echo "Limpando diretorio destino: $DEST"
# Preservar apenas o .env (configuracoes de producao)
if [ -f "$DEST/.env" ]; then
docker run --rm -v "$DEST":/src -v /tmp:/backup alpine:3 \
cp /src/.env /backup/.env.backup
echo ".env salvo em /tmp/.env.backup"
fi
# Remover o diretorio COMPLETAMENTE usando Docker Alpine como root
docker run --rm -v "$PARENT_DIR":/parent alpine:3 \
rm -rf /parent/sistema
echo "Diretorio removido"
mkdir -p "$ROOT"
# Sanidade: se esses arquivos nao existirem, o container vai falhar no boot.
test -f "$EFFECTIVE_APP_DIR/scripts/start-web.sh" || { echo "ERROR: scripts/start-web.sh nao encontrado em $EFFECTIVE_APP_DIR" >&2; exit 1; }
test -f "$EFFECTIVE_APP_DIR/stack.yml" || { echo "ERROR: stack.yml nao encontrado em $EFFECTIVE_APP_DIR" >&2; exit 1; }
test -d "$EFFECTIVE_APP_DIR/node_modules" || { echo "ERROR: node_modules nao encontrado em $EFFECTIVE_APP_DIR (necessario para next start)" >&2; exit 1; }
test -d "$EFFECTIVE_APP_DIR/.next" || { echo "ERROR: .next nao encontrado em $EFFECTIVE_APP_DIR (build nao gerado)" >&2; exit 1; }
PREV=""
if [ -L "$STABLE_LINK" ]; then
PREV="$(readlink -f "$STABLE_LINK" || true)"
fi
echo "PREV_APP_DIR=$PREV" >> "$GITHUB_ENV"
ln -sfn "$EFFECTIVE_APP_DIR" "$STABLE_LINK"
# Compat: mantem $HOME/apps/sistema como symlink quando possivel (nao mexe se for pasta).
if [ -L "$ROOT/sistema" ] || [ ! -e "$ROOT/sistema" ]; then
ln -sfn "$STABLE_LINK" "$ROOT/sistema"
fi
# Recriar o diretorio (sera criado com permissoes do usuario runner)
mkdir -p "$DEST"
# Restaurar .env antes do rsync
if [ -f /tmp/.env.backup ]; then
cp /tmp/.env.backup "$DEST/.env"
rm /tmp/.env.backup
echo ".env restaurado"
fi
# Copiar build completo (sem conflitos de permissao agora)
rsync -a --no-owner --no-group \
--exclude '.pnpm-store' --exclude '.pnpm-store/**' \
"$EFFECTIVE_APP_DIR"/ "$DEST"/
echo "Published build to: $DEST"
echo "APP_DIR estavel -> $(readlink -f "$STABLE_LINK")"
- name: Swarm deploy (stack.yml)
run: |
APP_DIR_STABLE="$HOME/apps/sistema"
APP_DIR_STABLE="$HOME/apps/sistema.current"
if [ ! -d "$APP_DIR_STABLE" ]; then
echo "ERROR: Stable APP_DIR does not exist: $APP_DIR_STABLE" >&2; exit 1
fi
@ -261,8 +251,24 @@ jobs:
fi
sleep 10
done
echo "AVISO: Timeout aguardando servicos. Status atual:"
docker service ls --filter "label=com.docker.stack.namespace=sistema"
echo "ERRO: Timeout aguardando servicos. Status atual:"
docker service ls --filter "label=com.docker.stack.namespace=sistema" || true
docker service ps sistema_web --no-trunc || true
docker service logs sistema_web --since 5m --raw 2>/dev/null | tail -n 200 || true
if [ -n "${PREV_APP_DIR:-}" ]; then
echo "Rollback: revertendo APP_DIR estavel para: $PREV_APP_DIR"
ln -sfn "$PREV_APP_DIR" "$HOME/apps/sistema.current"
cd "$HOME/apps/sistema.current"
set -o allexport
if [ -f .env ]; then
. ./.env
fi
set +o allexport
APP_DIR="$HOME/apps/sistema.current" RELEASE_SHA=${{ github.sha }} docker stack deploy --with-registry-auth -c stack.yml sistema || true
fi
exit 1
- name: Cleanup old build workdirs (keep last 2)
run: |
@ -270,7 +276,7 @@ jobs:
ROOT="$HOME/apps"
KEEP=2
PATTERN='web.build.*'
ACTIVE="$HOME/apps/sistema"
ACTIVE="$(readlink -f "$HOME/apps/sistema.current" 2>/dev/null || true)"
echo "Scanning $ROOT for old $PATTERN dirs"
LIST=$(find "$ROOT" -maxdepth 1 -type d -name "$PATTERN" | sort -r || true)
echo "$LIST" | sed -n "1,${KEEP}p" | sed 's/^/Keeping: /' || true