Automatización de despliegue CI/CD para WordPress
Introducción a la Automatización de Despliegue CI/CD para WordPress
El desarrollo de WordPress moderno ha evolucionado más allá del simple FTP y el plugin de actualización manual. Hoy, los equipos de desarrollo y los SysAdmins buscan implementar prácticas de Integración Continua y Despliegue Continuo (CI/CD) para garantizar que cada cambio en el código pase por pruebas automatizadas, construcción de assets y despliegues predecibles. Automatizar el pipeline de WordPress no solo acelera el time-to-market, sino que elimina el error humano y asegura la consistencia entre entornos (desarrollo, staging, producción).
En este artículo, exploraremos cómo construir un pipeline CI/CD completo para WordPress utilizando GitHub Actions, Docker, y WP-CLI. Cubriremos desde la estructura del repositorio hasta el despliegue en producción, pasando por estrategias de testing y gestión de secretos. Si eres un DevOps que trabaja con WordPress, este artículo es tu guía definitiva.
Fundamentos del Pipeline CI/CD para WordPress
Antes de escribir código, debemos entender los componentes clave de un pipeline CI/CD WordPress:
- Control de Versiones: Git (GitHub, GitLab, Bitbucket).
- Integración Continua (CI): Ejecución automática de pruebas y linters cada vez que se hace push o pull request.
- Construcción (Build): Compilación de assets (CSS/JS), generación de archivos optimizados y preparación del artefacto.
- Despliegue Continuo (CD): Publicación automática en el entorno de staging o producción.
- Infraestructura como Código: Uso de contenedores Docker para entornos reproducibles.
[INFO] Un pipeline CI/CD exitoso para WordPress requiere separar el código del tema/plugin de los archivos de WordPress core, que deben gestionarse mediante Composer o contenedores.
Estructura de repositorio recomendada
Para que el pipeline funcione sin fricciones, organiza tu repositorio de la siguiente manera:
/
├── .github/
│ └── workflows/
│ └── deploy.yml # Pipeline principal
├── web/
│ ├── wp-content/
│ │ ├── themes/
│ │ │ └── mi-tema/ # Tema personalizado
│ │ ├── plugins/
│ │ │ └── mi-plugin/ # Plugin personalizado
│ │ └── uploads/ # Sincronizado con S3/DO Spaces
│ ├── wp-config.php # Configuración con variables de entorno
│ └── index.php # Front controller
├── docker/
│ ├── Dockerfile # Imagen personalizada para WP
│ └── docker-compose.yml # Entorno local
├── scripts/
│ ├── deploy.sh # Script de despliegue
│ └── test.sh # Script de pruebas
├── composer.json # Dependencias PHP
├── package.json # Assets JS/CSS
└── .env.example # Variables de entorno de ejemplo
GitHub Actions: El Corazón del Pipeline
GitHub Actions es la plataforma de CI/CD nativa de GitHub. Nos permite definir flujos de trabajo (workflows) que se ejecutan en respuesta a eventos como push, pull_request o release.
Workflow básico de CI/CD WordPress
Crea el archivo .github/workflows/deploy.yml con el siguiente contenido:
name: CI/CD WordPress Pipeline
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
# Job 1: Pruebas y linting
test:
runs-on: ubuntu-latest
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: wordpress_test
ports:
- 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
tools: composer, wp-cli
- name: Install dependencies
run: composer install --no-progress --prefer-dist
- name: Run PHPCS (WordPress Coding Standards)
run: |
vendor/bin/phpcs --standard=WordPress web/wp-content/themes/mi-tema/
- name: Run unit tests (PHPUnit)
run: |
cd web/wp-content/themes/mi-tema
composer install
vendor/bin/phpunit
# Job 2: Build y construcción de assets
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install npm dependencies
run: npm ci
- name: Build assets (CSS/JS)
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-assets
path: web/wp-content/themes/mi-tema/dist/
# Job 3: Despliegue en producción
deploy:
needs: build
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: build-assets
path: web/wp-content/themes/mi-tema/dist/
- name: Deploy via rsync
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
REMOTE_HOST: ${{ secrets.REMOTE_HOST }}
REMOTE_USER: ${{ secrets.REMOTE_USER }}
REMOTE_PATH: ${{ secrets.REMOTE_PATH }}
run: |
mkdir -p ~/.ssh
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
rsync -avz --delete --exclude='.git*' --exclude='node_modules' --exclude='tests' \
web/ $REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH
- name: Run WP-CLI post-deploy commands
env:
WP_CLI_URL: ${{ secrets.WP_CLI_URL }}
WP_CLI_USER: ${{ secrets.WP_CLI_USER }}
WP_CLI_PASS: ${{ secrets.WP_CLI_PASS }}
run: |
ssh $REMOTE_USER@$REMOTE_HOST "cd $REMOTE_PATH && \
wp cache flush --allow-root && \
wp rewrite flush --allow-root && \
wp transient delete --all --allow-root"
[TIP] Usa
secretsen GitHub para almacenar credenciales sensibles como claves SSH, contraseñas de base de datos y API keys. Nunca las incluyas en el código.
Docker WordPress: Entornos Reproducibles
Docker es esencial para garantizar que el pipeline CI/CD se ejecute en un entorno idéntico al de producción. En lugar de instalar WordPress manualmente, usamos una imagen Docker con todas las dependencias.
Dockerfile personalizado para WordPress
# Usamos la imagen oficial de WordPress con PHP 8.2
FROM wordpress:6.7-php8.2-apache
# Instalamos herramientas adicionales para CI/CD
RUN apt-get update && apt-get install -y \
git \
unzip \
subversion \
&& rm -rf /var/lib/apt/lists/*
# Instalamos WP-CLI
RUN curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar \
&& chmod +x wp-cli.phar \
&& mv wp-cli.phar /usr/local/bin/wp
# Copiamos la configuración personalizada de PHP
COPY docker/php.ini /usr/local/etc/php/conf.d/custom.ini
# Configuramos Xdebug (opcional, para tests)
RUN pecl install xdebug && docker-php-ext-enable xdebug
WORKDIR /var/www/html
docker-compose.yml para desarrollo local
version: '3.8'
services:
wordpress:
build: .
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DEBUG: 1
volumes:
- ./web/wp-content:/var/www/html/wp-content
- ./docker/php.ini:/usr/local/etc/php/conf.d/custom.ini
db:
image: mysql:8.0
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
MYSQL_ROOT_PASSWORD: rootpassword
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
[WARNING] No uses
docker-compose.ymlen producción. Es solo para desarrollo local. En producción, considera orquestadores como Kubernetes o servicios gestionados como WP Engine.
WP-CLI Automatización: El Multitool de WordPress
WP-CLI es la navaja suiza para automatizar tareas en WordPress. En un pipeline CI/CD, lo usamos para:
- Sincronizar la base de datos entre entornos.
- Actualizar plugins y temas.
- Generar contenido de prueba.
- Ejecutar migraciones de datos.
Script de post-despliegue con WP-CLI
Crea scripts/post-deploy.sh para ejecutar después de cada despliegue:
#!/bin/bash
set -e
# Variables de entorno (inyectadas por CI/CD)
SITE_URL="${SITE_URL:-https://example.com}"
ADMIN_USER="${ADMIN_USER:-admin}"
ADMIN_PASS="${ADMIN_PASS:-securepassword}"
ADMIN_EMAIL="${ADMIN_EMAIL:-admin@example.com}"
echo "=== Post-deploy WordPress ==="
# 1. Verificar que WP-CLI está disponible
if ! command -v wp &> /dev/null; then
echo "WP-CLI no encontrado. Instalando..."
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
fi
# 2. Esperar a que la base de datos esté lista
echo "Esperando conexión a la base de datos..."
until wp db check --allow-root 2>/dev/null; do
sleep 2
done
# 3. Actualizar la URL del sitio (útil en staging)
wp option update siteurl "$SITE_URL" --allow-root
wp option update home "$SITE_URL" --allow-root
# 4. Activar el tema correcto
wp theme activate mi-tema --allow-root
# 5. Actualizar plugins de forma segura
wp plugin update --all --allow-root
# 6. Limpiar cachés
wp cache flush --allow-root
wp rewrite flush --allow-root
# 7. Crear usuario admin si no existe (solo en staging)
if ! wp user get "$ADMIN_USER" --allow-root 2>/dev/null; then
wp user create "$ADMIN_USER" "$ADMIN_EMAIL" --role=administrator --user_pass="$ADMIN_PASS" --allow-root
fi
echo "=== Post-deploy completado ==="
Integración del script en GitHub Actions
Añade este paso al job de despliegue:
- name: Run WP-CLI post-deploy script
run: |
ssh $REMOTE_USER@$REMOTE_HOST "cd $REMOTE_PATH && bash scripts/post-deploy.sh"
env:
SITE_URL: ${{ secrets.SITE_URL }}
ADMIN_USER: ${{ secrets.ADMIN_USER }}
ADMIN_PASS: ${{ secrets.ADMIN_PASS }}
Estrategias de Despliegue: Blue-Green y Canary
Para sitios WordPress de alto tráfico, el despliegue directo con rsync puede causar downtime. Implementa estrategias avanzadas:
Blue-Green Deployment
- Entorno Azul: Producción activa.
- Entorno Verde: Nuevo código desplegado, sin tráfico.
- Switch: Cambia el balanceador de carga al entorno verde.
# Fragmento de workflow para Blue-Green
- name: Deploy to Green environment
run: |
rsync -avz --delete web/ $REMOTE_USER@$REMOTE_HOST:/var/www/green/
- name: Switch load balancer to Green
run: |
ssh $REMOTE_USER@$REMOTE_HOST "sudo systemctl reload nginx-green"
Canary Releases con tráfico gradual
Usa un balanceador de carga (como HAProxy o Nginx) para enviar el 10% del tráfico al nuevo entorno, monitorear errores y luego aumentar al 100%.
[INFO] Para implementar Canary en WordPress, asegúrate de que la base de datos sea compartida y las sesiones de usuario no se pierdan. Usa Redis para caché compartida.
Pruebas Automatizadas en el Pipeline
Un pipeline CI/CD sin pruebas es solo un pipeline de despliegue. WordPress permite varios tipos de testing:
PHPUnit para plugins y temas
<!-- phpunit.xml.dist -->
<phpunit bootstrap="tests/bootstrap.php" colors="true">
<testsuites>
<testsuite name="Plugin Test Suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./</directory>
<exclude>
<directory>./tests/</directory>
<directory>./vendor/</directory>
</exclude>
</whitelist>
</filter>
</phpunit>
Pruebas de integración con Cypress (E2E)
Para pruebas de frontend, usa Cypress en un job separado:
e2e-tests:
runs-on: ubuntu-latest
services:
wordpress:
image: wordpress:6.7-php8.2-apache
env:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
steps:
- uses: actions/checkout@v4
- name: Run Cypress tests
uses: cypress-io/github-action@v6
with:
build: npm run build
start: npm start
wait-on: 'http://localhost:8080'
Gestión de Secretos y Variables de Entorno
Nunca hardcodees credenciales en tu repositorio. Usa los GitHub Secrets para almacenar:
| Secreto | Descripción |
|---|---|
SSH_PRIVATE_KEY | Clave privada para acceso SSH al servidor |
DB_PASSWORD | Contraseña de la base de datos de producción |
WP_CLI_URL | URL del sitio para WP-CLI |
S3_ACCESS_KEY | Clave de acceso a S3 para assets |
En tu workflow, referencia los secretos con ${{ secrets.NOMBRE }}.
Monitoreo y Rollback Automatizado
Un buen pipeline incluye monitoreo post-despliegue y capacidad de rollback.
Health check después del despliegue
- name: Health check
run: |
STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://example.com)
if [ "$STATUS" -ne 200 ]; then
echo "Error: Sitio devolvió código $STATUS"
exit 1
fi
Rollback automático
Si el health check falla, revierte el despliegue:
- name: Rollback on failure
if: failure()
run: |
ssh $REMOTE_USER@$REMOTE_HOST "cd $REMOTE_PATH && git checkout HEAD~1 -- web/"
echo "Rollback ejecutado"
Conclusión: DevOps para WordPress es Real
La automatización de despliegue CI/CD para WordPress ya no es un lujo, es una necesidad para equipos que buscan agilidad y fiabilidad. Con GitHub Actions, Docker, y WP-CLI, puedes construir un pipeline robusto que:
- Ejecuta pruebas autom
