CI/CD para WordPress: automatizar o deployment em 2026

CI/CD para WordPress: automatizar o deployment em 2026

Última verificação: 22 de setembro de 2026
8 min de leitura
Guia
Desenvolvedor full-stack

Arrastar temas por FTP em 2026 costuma acabar igual: falta um ficheiro de inc/, o composer.lock veio de outro portátil, e a produção cai porque alguém sobrescreveu o wp-config.php. Continuous Integration e Continuous Deployment não são teatro de enterprise - são a forma de cada alteração no Git passar pelo mesmo build, pelos mesmos testes e pelo mesmo caminho até ao servidor.

Este guia é para WordPress com tema ou plugin no repositório (Composer, npm, eventualmente Docker), não para sites que só vivem no painel. Se o código custom ainda só existe na base de dados e nos media, leve temas e código próprio para o Git primeiro - sem isso, o CI/CD não tem o que construir.

Documentação dos runners: GitHub Actions. Em paralelo: Hardening WordPress. Para comandos pós-deploy: WP-CLI.

#Porque o FTP e o «só carregar» falham em auditorias

Três problemas voltam em lojas WooCommerce portuguesas e em entregas de agência em Lisboa ou Porto:

  1. Deriva de ambiente - localmente PHP 8.2 e Composer 2.7; no VPS PHP 8.1 sem intl. O composer install local «funciona»; a produção morre com class not found.
  2. Sem rasto de auditoria - depois de um incidente não se sabe qual commit estava live. O painel do hosting mostra a data do ficheiro, não o SHA do Git.
  3. Segredos no disco - passwords SFTP no FileZilla, ou um .env commitado «só um momento», continuam a ser o caminho clássico de fuga - e caro sob o RGPD.

O CI/CD resolve isto mecanicamente: build numa imagem conhecida (shivammathur/setup-php ou Docker próprio), artefacto versionado por SHA, deploy por SSH com chave em Secrets.

#Pipeline mínimo: push, build, test, deploy

Fluxo típico para tema custom mais plugins via Composer:

  1. Trigger - push para main ou merge de pull request revisto. O develop costuma ir só para staging.
  2. Build - composer install --no-dev --optimize-autoloader, npm ci, npm run build. Fixe PHP e Node no workflow (php-version: '8.2', node-version: '20').
  3. Test - PHPUnit para plugins, eventualmente Playwright no checkout. Fail = paragem, zero deploy.
  4. Artefacto - empacote a release sem .git, sem node_modules, com vendor/ e assets/dist/ compilado.
  5. Deploy - rsync/SCP para releases/<run_id>/, depois troca atómica do symlink.

Esboço curto em GitHub Actions:

name: deploy-production
on:
  push:
    branches: [main]
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'
      - run: composer install --no-dev --optimize-autoloader
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: npm
      - run: npm ci && npm run build
      - name: rsync release
        env:
          SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
        run: |
          # gravar chave, rsync para releases/$GITHUB_SHA, ln -sfn

O script completo do symlink fica no repo como bin/release.sh - o workflow só o chama. O mesmo script funciona a partir do portátil se o Actions estiver em baixo.

#Deploys atómicos em vez de sobrescrever ficheiros

Sobrescrever ficheiros «no sítio» em public_html significa que durante alguns segundos metade dos pedidos vê um functions.php antigo com um template novo. No WooCommerce, numa campanha de Natal ou Black Friday, isso pode corromper sessões de carrinho.

Layout atómico:

  • base: /var/www/site/
  • releases: /var/www/site/releases/20260920-142211/
  • shared: uploads, wp-config.php, object cache - fora da release
  • current → symlink para a release ativa

Após rsync bem sucedido:

ln -sfn /var/www/site/releases/20260920-142211 /var/www/site/current

O root do Nginx aponta para .../current/public (ou equivalente). A troca é imediata. Apague releases antigas após N dias, ou guarde as três últimas para rollback.

Os uploads do WordPress têm de viver fora da release - caso contrário cada deploy apaga media ou copia gigabytes. Padrão clássico: shared/uploads ligado a wp-content/uploads em cada release.

#Staging, previews e matriz de estratégias

Em 2026, feature branch → PR → staging → main/produção não é opcional para lojas e páginas de captura. O staging deve ter:

  • a mesma versão de PHP e as mesmas extensões que a produção
  • uma cópia da base (anonimizada quando há dados pessoais sob o RGPD)
  • segredos de pagamento só em modo sandbox

URLs de preview por PR ajudam em redesign e CSS; migrações de esquema continuam a precisar de staging com dump real.

EstratégiaRiscoCusto de manutençãoQuando faz sentido
FTP manualMuito altoArranque barato, falhas carasSó sandbox / aprendizagem
Git hook no servidorMédioBaixoPortfólio pequeno, um programador
CI + rsync atómicoBaixoMédioNegócio, WooCommerce, agências
Blue/green ou dois VPSMínimoAltoMuito tráfego, SLA, pagamentos

Blue/green (dois ambientes completos, troca no load balancer) raramente compensa abaixo de centenas de sessões em paralelo. A maioria das lojas PT-PT fica bem com symlink atómico e rollback de diretório - em VPS (Hetzner, DigitalOcean) ou hosting gerido com SSH.

#Segredos, WP-CLI e base de dados

Nunca faça commit de:

  • chaves SSH
  • passwords da base de dados
  • AUTH_KEY / SECURE_AUTH_KEY do wp-config.php
  • tokens de API de gateways (MB Way, Stripe, PayPal)

No GitHub: Settings → Secrets and variables → Actions. Injete-os como env no passo de deploy. No servidor, o wp-config.php vive em shared/ e não faz parte do artefacto de CI.

WP-CLI depois da troca do symlink:

  • wp cache flush se houver object cache
  • wp rewrite flush após alterações de CPT
  • wp plugin list como linha de smoke no log

Planeie migrações de base de dados à parte do deploy de ficheiros. O rollback do symlink não desfaz ALTER TABLE. Em migrações destrutivas: backup primeiro (wp db export em staging e produção), depois migração, depois tráfego para o código que precisa do esquema - ou feature flag em PHP.

Dependências PHP: Composer install - em CI sempre --no-dev para produção e composer.lock bloqueado.

#O que costuma partir o primeiro pipeline WordPress

Da prática em VPS (Hetzner, DigitalOcean, OVH) e hosting gerido com SSH:

  • .gitignore come o vendor/ - a produção recebe o tema sem autoloader. Ou constrói o vendor no runner e mete-o no artefacto, ou corre Composer no servidor após o rsync (aí o servidor precisa de Composer e acesso ao Packagist).
  • Caminhos errados - o script assume /var/www/html e o hosting usa /home/user/domains/.... Fixe caminhos em Secrets por ambiente.
  • Opcache mantém código antigo - após ln -sfn, faça reload do PHP-FPM ou chame opcache_reset via WP-CLI/mu-plugin só para o utilizador de deploy.
  • Cron e filas - o Action Scheduler do WooCommerce pode correr jobs com código antigo durante alguns minutos; após releases grandes, observe failed jobs um pouco.

Smoke test pós-deploy (curl a partir do runner ou job separado):

  • homepage HTTP 200
  • /wp-login.php 200
  • um URL crítico de produto ou formulário
  • HEAD opcional ao CDN se os assets tiverem hash no nome

Se o smoke falhar, o rollback automático do symlink custa menos do que o telefonema do cliente às 23:00.

#Temas de blocos, must-use plugins e exceções ao Git «completo»

Nem todo o WordPress cabe no mesmo pipeline. Conteúdo na base (artigos, grupos ACF sem export JSON, CSS do Elementor) continua fora da release. O CI/CD protege código; não substitui backups da base.

Divisões práticas:

  • Tema clássico ou híbrido com Vite - build completo em CI, artefacto com style.css + dist/.
  • Tema de blocos (FSE) - mantenha theme.json e templates HTML no Git; alterações do Site Editor voltam por PR, senão produção e Git divergem após o primeiro «Guardar».
  • Must-use plugins - vão com a release; não os atualize pelo painel. Bom sítio para healthchecks de deploy e para desativar o editor de ficheiros.
  • Plugins de wordpress.org - fixe versões via Composer (wpackagist) ou atualize-os num job revisto. Misturar «Update no painel» com «CI sobrescreveu plugins/» produz uma árvore aleatória.

Stacks de agência em PT misturam muitas vezes tema custom, WooCommerce via wpackagist e dois zips premium instalados por path repository no Composer. O pipeline tem de conhecer as três fontes, senão staging e produção diferem por um ZIP de há seis meses.

#Checklist antes do primeiro deploy com Actions

Antes de ligar o main à produção, passe esta lista uma vez - poupa um fim de semana:

  1. Repositório privado, ou confirme que o histórico não tem segredos (git log -p não mostra .env antigos).
  2. Proteção de branch: PR obrigatório, workflow test verde obrigatório.
  3. Secrets separados: DEPLOY_HOST_STAGING, DEPLOY_HOST_PROD, chaves SSH distintas.
  4. Staging com a mesma versão de PHP que a produção (não «nós 8.3, o cliente 8.1»).
  5. Backup da base antes da primeira troca atómica - mesmo com rollback de código pronto.
  6. Monitorização de uptime (UptimeRobot, Better Stack ou equivalente) com alerta SMS/Slack no URL de produção.
  7. Runbook de uma página: como fazer ln -sfn manual para a release anterior, quem tem acesso ao servidor.

Só depois ative auto-deploy a partir de main. Até lá, «build + test» em PRs e workflow_dispatch manual para staging chega.

#Resumo

CI/CD para WordPress não é «YAML mágico». É um contrato repetível: o mesmo PHP, o mesmo lockfile, o mesmo artefacto, uma troca sem janela de ficheiros a meio. Começa com Git e staging, acrescenta Actions para builds Composer/npm, termina com current atómico e smoke test. O FTP fica ferramenta de emergência, não o processo.

Se precisa de um programador WordPress que mantenha esse pipeline junto do código do tema para loja ou página de captura, a WPPoland trabalha no stack real - não em slides.

Próximo passo

Transforme o artigo numa implementação real

Este bloco reforça a ligação interna e conduz o leitor para o passo seguinte mais útil dentro da arquitetura do site.

Quer implementar isto no seu site?

Se quer transformar o artigo em melhorias concretas, redesign ou num plano de implementação, posso fechar o escopo e executar.

Cluster relacionado

Explorar outros serviços WordPress e base de conhecimento

Reforce o seu negócio com suporte técnico profissional em áreas-chave do ecossistema WordPress.

FAQ do artigo

Perguntas frequentes

Respostas práticas para aplicar o tema na execução real.

SEO-readyGEO-readyAEO-ready5 Q&A
O CI/CD faz sentido para um freelancer a solo?#
Sim. Quem trabalha sozinho perde mais com um ficheiro PHP esquecido ou um composer.lock gerado noutra versão de PHP. O pipeline força o mesmo build em cada commit e deixa um registo auditável de qual SHA ficou em produção.
O que é deployment zero-downtime no WordPress?#
O código novo chega a releases/. Só depois de um rsync bem sucedido e de um eventual wp cache flush é que se muda o symlink current. PHP-FPM ou Nginx servem via current, a troca demora milissegundos e não precisa de modo de manutenção.
Preciso de um VPS para CI/CD?#
VPS ou contentores dão controlo total (SSH, symlinks, WP-CLI). Em hosting gerido fica muitas vezes uma API de deploy ou SFTP com chave em Secrets - ainda assim melhor do que arrastar ficheiros no FileZilla, mesmo sem blue/green verdadeiro.
O que fazer se o deploy falhar?#
Guarde N diretórios de release anteriores. Se o smoke test devolver 500 ou faltar vendor/, volte a apontar o symlink para a release anterior. Planeie migrações de base de dados à parte - o rollback de código não desfaz ALTER TABLE.
Onde construir temas com Vite ou webpack?#
No runner de CI: checkout, setup Node, npm ci, npm run build, depois empacote dist/ no artefacto com o PHP. Não envie node_modules nem fontes TypeScript para produção - só CSS/JS compilados.

Precisa de FAQ adaptado ao setor e mercado? Criamos uma versão alinhada com os seus objetivos de negócio.

Fale connosco

Artigos Relacionados