Skip to content

feat(autosave): SMTP rework + recruitment + string[] type + persist t… #63

feat(autosave): SMTP rework + recruitment + string[] type + persist t…

feat(autosave): SMTP rework + recruitment + string[] type + persist t… #63

name: Deploy develop → testes
# Sync da branch `develop` pro servidor de testes via SSH + rsync.
# Dispara em cada push em `develop` (após merge de PR ou push direto).
# Pré-requisitos operacionais documentados em CLAUDE.md (seção
# "Develop branch workflow"): SSH habilitado na hospedagem, par de
# chaves gerado, 4 secrets cadastrados no GitHub.
on:
push:
branches: [develop]
workflow_dispatch:
# Manual re-deploy útil quando o servidor de testes foi resetado
# ou o último push falhou e o estado da develop não mudou.
concurrency:
# Cancelar pushes consecutivos: só o último vence. Evita corrida
# de dois rsync paralelos sobre o mesmo destino.
group: deploy-develop-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
deploy:
name: rsync to testes
runs-on: ubuntu-latest
# Sem environment gating — develop é território livre por design.
# Se um dia esse workflow virar `deploy-prod`, aí sim entra
# `environment: production` com required reviewers.
steps:
- uses: actions/checkout@v6
with:
# Shallow clone OK — rsync envia working tree, não histórico.
fetch-depth: 1
- name: Configure SSH
env:
SSH_KEY: ${{ secrets.TESTES_SSH_KEY }}
SSH_HOST: ${{ secrets.TESTES_SSH_HOST }}
SSH_PORT: ${{ secrets.TESTES_SSH_PORT }}
run: |
mkdir -p ~/.ssh
echo "$SSH_KEY" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
# `TESTES_SSH_PORT` é opcional — VPS padrão usa 22; hospedagem
# gerenciada (Hostinger, KingHost) costuma usar porta alta.
PORT="${SSH_PORT:-22}"
# Best-effort: keyscan pode falhar (firewall, host atrás de
# CDN, etc.) sem derrubar o deploy. O step de rsync abaixo usa
# `StrictHostKeyChecking=accept-new` como fallback TOFU.
ssh-keyscan -p "$PORT" -H "$SSH_HOST" >> ~/.ssh/known_hosts 2>/dev/null || true
- name: Rsync to testes
env:
SSH_HOST: ${{ secrets.TESTES_SSH_HOST }}
SSH_USER: ${{ secrets.TESTES_SSH_USER }}
SSH_PORT: ${{ secrets.TESTES_SSH_PORT }}
REMOTE_PATH: ${{ secrets.TESTES_REMOTE_PATH }}
run: |
PORT="${SSH_PORT:-22}"
# `--delete` remove arquivos no destino que não existem na
# origem (idempotência total). Exclusões abaixo cobrem:
# - VCS / CI metadata que não pertence ao runtime do plugin.
# - Dependências de dev (composer require-dev only, node_modules).
# - Testes e ferramentas de análise estática.
# - Manifests de build/lint (composer.json, package.json e locks
# não servem runtime do WordPress; analisadores externos não
# precisam deles na pasta do plugin em produção).
# - Docs de repositório (CONTRIBUTING.md, SECURITY.md) que vivem
# no GitHub e não no runtime. `CHANGELOG.md` é mantido por
# preferência — consulta histórica via SSH.
# - Saídas de coverage / build intermediário.
# `StrictHostKeyChecking=accept-new`: TOFU — aceita a chave do
# host na primeira conexão e exige match em conexões futuras.
# Mais seguro que `no` (vulnerável a MITM); funciona quando o
# `ssh-keyscan` acima falhou silenciosamente.
rsync -avz --delete \
--exclude='.git/' \
--exclude='.github/' \
--exclude='.githooks/' \
--exclude='.gitignore' \
--exclude='.gitattributes' \
--exclude='.distignore' \
--exclude='vendor/' \
--exclude='node_modules/' \
--exclude='tests/' \
--exclude='coverage-js/' \
--exclude='coverage/' \
--exclude='build/' \
--exclude='dist/' \
--exclude='.phpunit.result.cache' \
--exclude='phpunit.xml' \
--exclude='phpunit.xml.dist' \
--exclude='phpstan.neon' \
--exclude='phpstan.neon.dist' \
--exclude='phpstan-stubs.php' \
--exclude='phpcs.xml' \
--exclude='phpcs.xml.dist' \
--exclude='patchwork.json' \
--exclude='.eslintrc*' \
--exclude='eslint.config.*' \
--exclude='.stylelintrc*' \
--exclude='vitest.config.*' \
--exclude='composer.json' \
--exclude='composer.lock' \
--exclude='package.json' \
--exclude='package-lock.json' \
--exclude='CLAUDE.md' \
--exclude='CONTRIBUTING.md' \
--exclude='SECURITY.md' \
--exclude='html/' \
-e "ssh -i ~/.ssh/deploy_key -p $PORT -o StrictHostKeyChecking=accept-new" \
./ "${SSH_USER}@${SSH_HOST}:${REMOTE_PATH}/"
- name: Cleanup SSH key
if: always()
run: rm -f ~/.ssh/deploy_key