Deploy CI/CD

GitHub Actions para Deploy Automático de WordPress

Depois de configurar mais de 300 sites WordPress para clientes ao longo de 15 anos, a Weboption chegou a uma conclusão simples: deploy manual é a maior fonte de erros evitáveis em projetos WordPress.…

Daniel Paz Daniel Paz Daniel Paz atua no mercado de
Publicado 30 jun 2026 Atualizado 24 jul 2026 8 min de leitura
Headless WordPress. Liberdade de front, poder de WP

Depois de configurar mais de 300 sites WordPress para clientes ao longo de 15 anos, a Weboption chegou a uma conclusão simples: deploy manual é a maior fonte de erros evitáveis em projetos WordPress. Um arquivo sobrescrito errado, uma versão de tema desatualizada, um plugin ativado antes do banco migrar. Com o GitHub Actions para deploy automático de WordPress, esses problemas deixam de existir.

Neste guia você vai ver como montar um pipeline real, do push ao servidor de produção, com SSH, rsync, WP-CLI e testes automatizados.

Por que GitHub Actions faz sentido para WordPress

GitHub Actions resolve um problema que FTP e plugins de deploy nunca resolveram: rastreabilidade. Cada deploy fica registrado, com log completo, quem disparou e quando. Isso vale mais do que parece em projetos com múltiplos desenvolvedores.

Segundo o relatório State of DevOps 2023 do DORA, times que usam CI/CD têm 4x menos falhas em deploy do que times com processos manuais. No contexto WordPress, isso se traduz em menos manutenção emergencial e menos horas de suporte cobradas ao cliente.

O GitHub Actions é gratuito para repositórios públicos e oferece 2.000 minutos por mês no plano gratuito para repositórios privados. Para a maioria dos projetos WordPress de agência, esse limite raramente é atingido. Um workflow de deploy completo com testes leva entre 3 e 8 minutos por execução.

Estrutura do workflow de deploy para WordPress

O arquivo de workflow fica em .github/workflows/deploy.yml na raiz do repositório. A estrutura básica tem quatro etapas: checkout do código, instalação de dependências, execução de testes e envio para o servidor via rsync.

Um workflow funcional começa assim:

name: Deploy WordPress

on:
 push:
 branches:
 - main

jobs:
 deploy:
 runs-on: ubuntu-latest
 steps:
 - name: Checkout
 uses: actions/checkout@v4

 - name: Setup PHP
 uses: shivammathur/setup-php@v2
 with:
 php-version: '8.2'

 - name: Install Composer dependencies
 run: composer install --no-dev --optimize-autoloader

 - name: Deploy via rsync
 uses: easingthemes/ssh-deploy@v5
 with:
 SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
 REMOTE_HOST: ${{ secrets.REMOTE_HOST }}
 REMOTE_USER: ${{ secrets.REMOTE_USER }}
 SOURCE: "./"
 TARGET: "/var/www/html/wp-content/themes/meu-tema/"
 EXCLUDE: "/node_modules/, /.git/, /tests/"

O campo EXCLUDE é crítico. Enviar node_modules para produção além de desnecessário aumenta o tempo de deploy em minutos e pode causar conflitos com versões do servidor.

Imagem editorial para GitHub Actions para Deploy Automático de WordPress

Configurando SSH Keys nos Secrets do GitHub

A autenticação SSH é o ponto onde a maioria dos times trava na primeira vez. O processo é direto quando você sabe a ordem correta.

Primeiro, gere um par de chaves dedicado para CI. Nunca use a chave pessoal do desenvolvedor:

ssh-keygen -t ed25519 -C "github-actions-deploy" -f ~/.ssh/github_actions_deploy

A chave pública vai para o servidor de produção, no arquivo ~/.ssh/authorized_keys do usuário de deploy. A chave privada vai para o GitHub. No repositório, acesse Settings, depois Secrets and variables, depois Actions. Crie três secrets:

SSH_PRIVATE_KEY com o conteúdo completo da chave privada, incluindo as linhas -----BEGIN... e -----END.... REMOTE_HOST com o IP ou domínio do servidor. REMOTE_USER com o usuário SSH de deploy.

Um erro que vemos com frequência: secrets configurados com espaços extras no final, copiados de editores que adicionam newline automático. Isso gera falha de autenticação silenciosa que pode levar horas para diagnosticar.

Usando WP-CLI no pipeline de CI

WP-CLI dentro do GitHub Actions abre possibilidades que nenhum plugin de deploy oferece. Você pode executar migrações de banco, atualizar opções, ativar plugins na ordem correta e limpar cache, tudo como parte do pipeline.

Para instalar WP-CLI no runner:

 - name: Install WP-CLI
 run: |
 curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
 chmod +x wp-cli.phar
 sudo mv wp-cli.phar /usr/local/bin/wp

Para executar comandos no servidor remoto via SSH após o rsync:

 - name: Post-deploy WP-CLI
 uses: appleboy/ssh-action@v1
 with:
 host: ${{ secrets.REMOTE_HOST }}
 username: ${{ secrets.REMOTE_USER }}
 key: ${{ secrets.SSH_PRIVATE_KEY }}
 script: |
 cd /var/www/html
 wp cache flush
 wp rewrite flush
 wp plugin activate meu-plugin --allow-root

Times que adotam WP-CLI no CI reduzem o tempo médio de deploy de 25 minutos para menos de 5 minutos, eliminando os passos manuais de pós-deploy que todo desenvolvedor esquece algum dia.

Rodando testes com PHPUnit e Playwright

Deploy sem testes automatizados é só rsync com mais etapas. Os testes são o que separa um pipeline real de um script de upload glorificado.

Para PHPUnit em temas e plugins WordPress, adicione antes do passo de deploy:

 - name: Run PHPUnit
 run: |
 composer install./vendor/bin/phpunit --configuration phpunit.xml

Para testes E2E com Playwright, que validam o comportamento real do site:

 - name: Run Playwright tests
 run: |
 npm ci
 npx playwright install --with-deps chromium
 npx playwright test
 env:
 BASE_URL: ${{ secrets.STAGING_URL }}

A recomendação da Weboption é rodar PHPUnit em todo push e Playwright antes de qualquer deploy para produção. Playwright demora mais, entre 1 e 4 minutos dependendo do número de specs, e não faz sentido executar em branches de feature.

Um detalhe importante: o Playwright precisa de um ambiente WordPress rodando para testar. Use um ambiente de staging dedicado ou o serviço de WordPress no próprio runner via Docker. A segunda opção custa mais em minutos de CI mas elimina a dependência de infraestrutura externa.

Notificações de falha no deploy

Um pipeline sem notificações é um pipeline que falha em silêncio. A integração com Slack leva menos de 10 minutos e garante que o time saiba imediatamente quando algo quebra.

 - name: Notify Slack on failure
 if: failure()
 uses: slackapi/slack-github-action@v1
 with:
 payload: |
 {
 "text": "Deploy falhou no repositório ${{ github.repository }}. Branch: ${{ github.ref_name }}. Commit: ${{ github.sha }}."
 }
 env:
 SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

A condição if: failure() garante que a notificação só dispara quando algo deu errado. Para deploys bem-sucedidos, notificações opcionais podem ser configuradas com if: success(), mas na prática elas viram ruído rapidamente. Falha sempre notifica. Sucesso, só se o cliente precisar de confirmação.

Para equipes que usam Microsoft Teams no lugar do Slack, o action jdcargile/ms-teams-notification@v1 segue a mesma lógica com um webhook diferente.

O erro mais comum que vemos em projetos de agência

Em revisões de repositórios de clientes que chegam à Weboption para manutenção, um padrão se repete com frequência preocupante: o workflow de deploy envia o tema inteiro para o servidor, incluindo arquivos de desenvolvimento como webpack.config.js, .eslintrc, package.json e pastas node_modules com gigabytes de dependências.

O resultado é um servidor de produção com 3 GB de arquivos desnecessários, deploy que demora 8 minutos em vez de 45 segundos e risco de exposição de configurações de desenvolvimento.

A correção é simples: adicionar um passo de build antes do rsync e enviar apenas os arquivos compilados. Para temas que usam webpack ou Vite:

 - name: Build assets
 run: |
 npm ci
 npm run build

 - name: Deploy via rsync
 uses: easingthemes/ssh-deploy@v5
 with:
 EXCLUDE: "/node_modules/, /src/, /.git/, /tests/, /webpack.config.js"
 SOURCE: "./dist/"

Envie apenas o que o servidor precisa para rodar. O resto fica no repositório.

Perguntas frequentes

GitHub Actions funciona com qualquer hospedagem WordPress?

Funciona com qualquer servidor que aceite conexão SSH, o que inclui VPS, servidores dedicados e planos de hospedagem compartilhada com SSH habilitado. Hospedagens sem acesso SSH, como algumas versões de planos básicos, exigem alternativas via FTP, mas perdem a segurança e confiabilidade do SSH.

Qual o custo mensal para usar GitHub Actions em projetos WordPress?

Para repositórios privados, o plano gratuito oferece 2.000 minutos por mês. Um projeto típico com deploy mais testes usa entre 5 e 10 minutos por push. Isso sustenta cerca de 200 a 400 deploys mensais sem custo adicional. O plano Team do GitHub custa R$ 25 por usuário por mês e inclui 3.000 minutos.

É seguro armazenar chaves SSH nos Secrets do GitHub?

Sim. Os Secrets do GitHub são criptografados em repouso com Libsodium e nunca aparecem nos logs de execução. A recomendação é usar chaves dedicadas para CI com permissões mínimas no servidor, separadas das chaves pessoais dos desenvolvedores.

Como fazer rollback quando um deploy quebra produção?

A forma mais rápida é re-executar o workflow de um commit anterior diretamente pelo painel do GitHub Actions. Para rollbacks que precisam também reverter banco de dados, o WP-CLI no passo de pós-deploy pode restaurar um dump de backup gerado automaticamente antes de cada deploy.

GitHub Actions ou GitLab CI para WordPress?

Para projetos hospedados no GitHub, Actions tem integração nativa e marketplace com centenas de actions prontos. GitLab CI tem vantagem em self-hosting e pipelines mais complexos. Para a maioria das agências que já usam GitHub, não há motivo para mudar.

Guia completo: Deploy WordPress Profissional: Git, Staging e Produção: leia o artigo principal para uma visão abrangente do tema.