mirror of
https://github.com/melgarafael/DeskcommCRM.git
synced 2026-10-02 01:28:34 +08:00
fix(ci): tira o deploy da VPS deste fork do PR
A cerca de gatilhos reprova job que nao esta no mapa. Esse workflow e customizacao do fork e o proprio arquivo pede para nao ir ao upstream.
This commit is contained in:
@@ -1,121 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Atualiza ESTA VPS para o commit que o GitHub Actions acabou de publicar
|
||||
# em ghcr.io/<dono>/…:develop. Não builda nada aqui — só puxa imagem pronta.
|
||||
#
|
||||
# Variáveis (vêm do job, não ficam no disco):
|
||||
# GH_TOKEN GITHUB_TOKEN do job (login no GHCR + fetch do fork, se privado)
|
||||
# GH_USER github.actor
|
||||
# SHA commit que acabou de construir
|
||||
# DONO dono do GHCR em minúsculas (ex.: iancouto)
|
||||
#
|
||||
# NÃO chame gravar_imagens: ela pinaria o namespace do upstream, que
|
||||
# não é o registro deste fork.
|
||||
set -euo pipefail
|
||||
|
||||
PROJECT_DIR="${PROJECT_DIR:-/root/deskcommcrm}"
|
||||
SHA="${SHA:?falta SHA}"
|
||||
DONO="${DONO:?falta DONO}"
|
||||
GH_USER="${GH_USER:?falta GH_USER}"
|
||||
GH_TOKEN="${GH_TOKEN:?falta GH_TOKEN}"
|
||||
|
||||
cleanup() {
|
||||
docker logout ghcr.io >/dev/null 2>&1 || true
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
# Uma atualização por vez. O mesmo arquivo que o agent.sh usa: se alguém
|
||||
# clicar em "Atualizar agora" no meio, o segundo espera ou recusa.
|
||||
exec 9> "${PROJECT_DIR}/.update.lock"
|
||||
if ! flock -n 9; then
|
||||
echo "outro update já está rodando neste servidor — tente de novo em alguns minutos"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# shellcheck source=../../hostgator-setup-kit/_common.sh
|
||||
source "${PROJECT_DIR}/hostgator-setup-kit/_common.sh"
|
||||
enter_project
|
||||
recusar_projeto_de_outra_arvore \
|
||||
|| die "Atualização interrompida para não quebrar a instalação que está no ar."
|
||||
|
||||
step "Backup de segurança (antes de mexer no banco)"
|
||||
if bash "${PROJECT_DIR}/hostgator-setup-kit/backup.sh"; then
|
||||
c_grn "✓ backup feito"
|
||||
else
|
||||
c_ylw "⚠ o backup falhou — sigo, mas o ideal é ter um. Continuo em 5s."
|
||||
sleep 5
|
||||
fi
|
||||
|
||||
step "Login no registro de imagens"
|
||||
printf '%s' "$GH_TOKEN" | docker login ghcr.io -u "$GH_USER" --password-stdin
|
||||
|
||||
step "Código deste commit"
|
||||
# Repo público: fetch pela URL, sem token. Bearer no extraHeader faz o git
|
||||
# cair no prompt de usuário na VPS (exit 128, "No such device or address").
|
||||
GIT_TERMINAL_PROMPT=0 git fetch --depth 1 \
|
||||
"https://github.com/${DONO}/DeskcommCRM.git" "$SHA"
|
||||
git reset --hard FETCH_HEAD
|
||||
|
||||
# Relê o kit DEPOIS do reset: o _common.sh deste commit é o que vale.
|
||||
# shellcheck source=../../hostgator-setup-kit/_common.sh
|
||||
source "${PROJECT_DIR}/hostgator-setup-kit/_common.sh"
|
||||
enter_project
|
||||
|
||||
step "Apontar o app para as imagens deste fork"
|
||||
set_env_var .env APP_IMAGE "ghcr.io/${DONO}/deskcommcrm:develop"
|
||||
set_env_var .env WORKER_IMAGE "ghcr.io/${DONO}/deskcomm-worker:develop"
|
||||
set_env_var .env SCHEDULER_IMAGE "ghcr.io/${DONO}/deskcomm-scheduler:develop"
|
||||
# Tag móvel: tem que puxar. Depois do pull, voltamos para missing — senão um
|
||||
# `up -d` à mão, sem login no GHCR, morre quando o pacote ainda é privado.
|
||||
set_env_var .env APP_PULL_POLICY always
|
||||
set_env_var .env WORKER_PULL_POLICY always
|
||||
set_env_var .env SCHEDULER_PULL_POLICY always
|
||||
load_env .env
|
||||
|
||||
step "Atualizando o banco de dados"
|
||||
if [ -f supabase/baseline.sql ]; then
|
||||
docker run --rm postgres:17-alpine psql "$(url_do_schema)" -c \
|
||||
"create extension if not exists vector with schema public; create extension if not exists citext with schema public; create extension if not exists pg_trgm with schema public;" \
|
||||
>/dev/null 2>&1 || true
|
||||
raw="$(docker run --rm -i -v "$PROJECT_DIR/supabase/baseline.sql:/b.sql:ro" \
|
||||
postgres:17-alpine psql "$(url_do_schema)" -f /b.sql 2>&1 || true)"
|
||||
benign='already exists|multiple primary keys|multiple default values|is already a member|already a partition'
|
||||
unexpected="$(printf '%s\n' "$raw" | grep -iE 'ERROR|FATAL' | grep -viE "$benign" || true)"
|
||||
if [ -n "$unexpected" ]; then
|
||||
c_ylw "⚠ avisos inesperados no banco:"
|
||||
printf '%s\n' "$unexpected" | head -20
|
||||
else
|
||||
c_grn "✓ banco atualizado"
|
||||
fi
|
||||
else
|
||||
c_ylw "⚠ supabase/baseline.sql não encontrado — pulei a parte do banco."
|
||||
fi
|
||||
|
||||
step "Baixando a imagem nova e reiniciando"
|
||||
if ! dc pull; then
|
||||
die "Não consegui puxar as imagens ghcr.io/${DONO}/*:develop. O job publicou?"
|
||||
fi
|
||||
garantir_rede_do_proxy
|
||||
dc up -d
|
||||
|
||||
if [ "${REVERSE_PROXY:-caddy}" = "traefik" ]; then
|
||||
c_grn "✓ proxy externo (Traefik): o Caddy não é usado aqui"
|
||||
else
|
||||
dc up -d --force-recreate --no-deps caddy >/dev/null 2>&1 \
|
||||
&& c_grn "✓ proxy recarregado" \
|
||||
|| c_ylw "⚠ não consegui recriar o proxy"
|
||||
fi
|
||||
|
||||
# Já está no disco desta VPS. Sem always, um up -d posterior não depende do GHCR.
|
||||
set_env_var .env APP_PULL_POLICY missing
|
||||
set_env_var .env WORKER_PULL_POLICY missing
|
||||
set_env_var .env SCHEDULER_PULL_POLICY missing
|
||||
|
||||
step "Conferindo se o app voltou no ar"
|
||||
if wait_app_healthy 20 3 >/dev/null; then
|
||||
c_grn "✓ deploy do ${SHA:0:7} no ar e saudável"
|
||||
else
|
||||
c_ylw "⚠ atualizei, mas o app não respondeu ok. Veja: docker compose $(dc_files) logs --tail=50 app"
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,218 +0,0 @@
|
||||
name: Deploy da develop na VPS
|
||||
|
||||
# Customização DESTE fork (IanCouto/DeskcommCRM). Não abra PR disto para o
|
||||
# upstream: o `publish-image.yml` de lá só publica `main` e tags `v*`, e é
|
||||
# assim de propósito — `develop` aqui é um canal móvel da instalação desta VPS,
|
||||
# não do parque inteiro.
|
||||
#
|
||||
# Doutrina: a VPS NÃO builda. Os runners do GitHub constroem as três imagens,
|
||||
# publicam em ghcr.io/<dono>/…:develop, e o servidor só faz `docker compose pull`.
|
||||
#
|
||||
# Secrets (Settings → Secrets and variables → Actions), neste repositório:
|
||||
# VPS_HOST IP da VPS
|
||||
# VPS_PORT porta do SSH (nesta HostGator não é 22)
|
||||
# VPS_USER usuário SSH (root)
|
||||
# VPS_SSH_KEY chave privada ed25519 só para este job (não a chave pessoal)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [develop]
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: deploy-vps-develop
|
||||
cancel-in-progress: false
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
if: github.repository == 'IanCouto/DeskcommCRM' && github.ref == 'refs/heads/develop'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: deskcommcrm
|
||||
dockerfile: Dockerfile
|
||||
title: DeskcommCRM
|
||||
- name: deskcomm-worker
|
||||
dockerfile: Dockerfile.worker
|
||||
title: DeskcommCRM worker
|
||||
- name: deskcomm-scheduler
|
||||
dockerfile: Dockerfile.scheduler
|
||||
title: DeskcommCRM scheduler
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Resolver APP_VERSION
|
||||
id: ver
|
||||
run: echo "value=${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Docker metadata (tags/labels)
|
||||
id: meta
|
||||
uses: docker/metadata-action@v6
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ matrix.name }}
|
||||
tags: |
|
||||
type=raw,value=develop
|
||||
type=raw,value=${{ github.sha }}
|
||||
labels: |
|
||||
org.opencontainers.image.title=${{ matrix.title }}
|
||||
|
||||
- name: Set up Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Build e push
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
file: ${{ matrix.dockerfile }}
|
||||
platforms: linux/amd64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
APP_VERSION=${{ steps.ver.outputs.value }}
|
||||
cache-from: type=gha,scope=develop-${{ matrix.name }}
|
||||
cache-to: type=gha,mode=max,scope=develop-${{ matrix.name }}
|
||||
|
||||
- name: Tornar o pacote público (a VPS precisa puxar)
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PKG: ${{ matrix.name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
gh api --method PUT \
|
||||
"/user/packages/container/${PKG}/visibility" \
|
||||
-f visibility=public \
|
||||
|| echo "::warning::não consegui tornar ${PKG} público — o deploy faz login com o token do job"
|
||||
|
||||
imagem-do-app-sobe:
|
||||
if: github.repository == 'IanCouto/DeskcommCRM' && github.ref == 'refs/heads/develop'
|
||||
needs: [build-and-push]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
steps:
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Puxar a imagem que acabou de publicar
|
||||
run: |
|
||||
set -euo pipefail
|
||||
dono=$(echo "${GITHUB_REPOSITORY_OWNER}" | tr '[:upper:]' '[:lower:]')
|
||||
docker pull "${REGISTRY}/${dono}/deskcommcrm:${GITHUB_SHA}"
|
||||
docker tag "${REGISTRY}/${dono}/deskcommcrm:${GITHUB_SHA}" deskcomm-smoke:develop
|
||||
|
||||
- name: O container chega a servir?
|
||||
run: |
|
||||
set -euo pipefail
|
||||
docker run -d --name smoke -p 3000:3000 \
|
||||
-e NEXT_PUBLIC_SUPABASE_URL=https://exemplo.supabase.co \
|
||||
-e NEXT_PUBLIC_SUPABASE_ANON_KEY=chave-de-mentira \
|
||||
-e SUPABASE_SERVICE_ROLE_KEY=chave-de-mentira \
|
||||
-e SUPABASE_DB_URL=postgres://u:p@127.0.0.1:5432/postgres \
|
||||
-e SENTRY_DSN=off \
|
||||
deskcomm-smoke:develop
|
||||
|
||||
pronto=nao
|
||||
for _ in $(seq 1 40); do
|
||||
if ! docker ps --filter name=smoke --filter status=running -q | grep -q .; then
|
||||
echo "::error::o container do app MORREU durante o boot"
|
||||
docker logs smoke 2>&1 | tail -40
|
||||
exit 1
|
||||
fi
|
||||
if docker logs smoke 2>&1 | grep -qE "Ready in|started server on"; then
|
||||
pronto=sim
|
||||
break
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
|
||||
if [ "$pronto" != "sim" ]; then
|
||||
echo "::error::o app não chegou a servir em 120s"
|
||||
docker logs smoke 2>&1 | tail -40
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if docker logs smoke 2>&1 | grep -q "MODULE_NOT_FOUND"; then
|
||||
echo "::error::falta módulo no standalone"
|
||||
docker logs smoke 2>&1 | grep -A5 MODULE_NOT_FOUND | head -20
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "o app chegou a servir:"
|
||||
docker logs smoke 2>&1 | grep -E "Ready in|Next.js" | head -3
|
||||
|
||||
- name: Encerrar
|
||||
if: always()
|
||||
run: docker rm -f smoke 2>/dev/null || true
|
||||
|
||||
deploy-vps:
|
||||
if: github.repository == 'IanCouto/DeskcommCRM' && github.ref == 'refs/heads/develop'
|
||||
needs: [build-and-push, imagem-do-app-sobe]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: SSH na VPS e atualizar
|
||||
env:
|
||||
VPS_HOST: ${{ secrets.VPS_HOST }}
|
||||
VPS_PORT: ${{ secrets.VPS_PORT }}
|
||||
VPS_USER: ${{ secrets.VPS_USER }}
|
||||
VPS_SSH_KEY: ${{ secrets.VPS_SSH_KEY }}
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GH_USER: ${{ github.actor }}
|
||||
SHA: ${{ github.sha }}
|
||||
DONO: ${{ github.repository_owner }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
for v in VPS_HOST VPS_PORT VPS_USER VPS_SSH_KEY; do
|
||||
eval "val=\${$v:-}"
|
||||
if [ -z "$val" ]; then
|
||||
echo "::error::falta o secret $v (Settings → Secrets and variables → Actions)"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
umask 077
|
||||
printf '%s\n' "$VPS_SSH_KEY" > ~/.ssh/id_ed25519
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
ssh-keyscan -p "$VPS_PORT" "$VPS_HOST" >> ~/.ssh/known_hosts 2>/dev/null
|
||||
|
||||
# scp usa -P (maiúsculo) para a porta; ssh usa -p. Misturar os dois
|
||||
# numa array só faz o scp ler `-p` como "preservar timestamp".
|
||||
ident=(-o IdentitiesOnly=yes -o StrictHostKeyChecking=yes -i ~/.ssh/id_ed25519)
|
||||
scp -P "$VPS_PORT" "${ident[@]}" .github/scripts/deploy-vps-develop.sh \
|
||||
"${VPS_USER}@${VPS_HOST}:/tmp/deploy-vps-develop.sh"
|
||||
|
||||
dono=$(printf '%s' "$DONO" | tr '[:upper:]' '[:lower:]')
|
||||
# Token vai por stdin (uma linha), não na linha de comando do ssh.
|
||||
printf '%s\n' "$GH_TOKEN" | ssh -p "$VPS_PORT" "${ident[@]}" "${VPS_USER}@${VPS_HOST}" \
|
||||
"read GH_TOKEN; export GH_TOKEN GH_USER=$(printf '%q' "$GH_USER") SHA=$(printf '%q' "$SHA") DONO=$(printf '%q' "$dono"); bash /tmp/deploy-vps-develop.sh"
|
||||
@@ -1,28 +0,0 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
const RAIZ = process.cwd();
|
||||
const SCRIPT = readFileSync(join(RAIZ, ".github/scripts/deploy-vps-develop.sh"), "utf8");
|
||||
|
||||
describe("deploy da develop na VPS não puxa o registro do upstream", () => {
|
||||
const semComentario = SCRIPT.split("\n")
|
||||
.filter((l) => !l.trimStart().startsWith("#"))
|
||||
.join("\n");
|
||||
|
||||
it("não chama gravar_imagens — aquilo pinaria o namespace do upstream, que este fork não publica", () => {
|
||||
expect(semComentario).not.toMatch(/\bgravar_imagens\b/);
|
||||
});
|
||||
|
||||
it("grava as três imagens a partir do DONO do job, não de um literal", () => {
|
||||
expect(SCRIPT).toContain("ghcr.io/${DONO}/deskcommcrm:develop");
|
||||
expect(SCRIPT).toContain("ghcr.io/${DONO}/deskcomm-worker:develop");
|
||||
expect(SCRIPT).toContain("ghcr.io/${DONO}/deskcomm-scheduler:develop");
|
||||
});
|
||||
|
||||
it("puxa o código pela URL pública — Bearer no extraHeader faz o git da VPS pedir usuário", () => {
|
||||
expect(semComentario).toContain("GIT_TERMINAL_PROMPT=0");
|
||||
expect(semComentario).not.toMatch(/http\.extraHeader/);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user