Desplegar theme de Wordpress con Github Actions
Tags: devops, github, spanish, ci
Published: 2023-11-14 07:37:51

---
title: Desplegar theme de Wordpress con Github Actions
published: true
date: 2023-11-09 06:00:00 UTC
tags: DevOps, GitHub, Spanish, CI
canonical_url: https://danieljsaldana.dev/desplegar-theme-wordpress-github-actions
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9egjv9lqv35j5ypc5yf5.png
---

En este nuevo laboratorio, vamos a explorar cómo automatizar el despliegue de un tema de WordPress en un servidor alojado en DigitalOcean utilizando Github Actions. Hemos simplificado la creación de un entorno de prueba para que puedas probarlo tú mismo. 🚀

**Creación del Entorno con Terraform 🌍**

Para comenzar, vamos a crear una carpeta que contendrá el código de Terraform. Aquí es donde definiremos los recursos que necesitamos para configurar nuestro servidor en DigitalOcean.

**Archivo provider.tf 🔌**

En este archivo, especificaremos el proveedor que vamos a utilizar, en este caso, **DigitalOcean**. Asegúrate de que tengas tu token de acceso a DigitalOcean disponible.

```
terraform {
  required_providers {
    digitalocean = {
      source = "digitalocean/digitalocean"
      version = "~> 2.30"
    }
  }
}

provider "digitalocean" {
  token = var.do_token
}

resource "digitalocean_ssh_key" "mi_clave_rsa" {
  name = "mi_clave_rsa"
  public_key = file(var.do_public_key)
}

```

**Archivo main.tf 🏢**

En este archivo, definiremos la creación de nuestro servidor en DigitalOcean. Aquí es donde configuramos detalles como la imagen, el nombre, la región y el tamaño del servidor.

```
resource "digitalocean_droplet" "mi_droplet" {
  image = var.droplet_image
  name = var.droplet_name
  region = var.droplet_region
  size = var.droplet_size
  monitoring = true
  tags = ["wordpress", "blog", "lab"]
  droplet_agent = true
  ssh_keys = [
    digitalocean_ssh_key.mi_clave_rsa.fingerprint
  ]
}

```

**Archivo terraform.tfvars 🧾**

Este archivo contendrá las variables que utilizaremos en nuestro archivo `main.tf`. Asegúrate de configurar estas variables según tus preferencias y necesidades.

```
do_public_key = "tf-digitalocean.pub"
droplet_image = "wordpress-20-04"
droplet_name = "labs-deploy-wordpress"
droplet_region = "fra1"
droplet_size = "s-2vcpu-4gb"

```

Estas variables son esenciales para personalizar la configuración de tu servidor en DigitalOcean. A medida que continúes con la automatización del despliegue, estas variables se utilizarán en el archivo `main.tf` para configurar y crear tu servidor en DigitalOcean. A continuación, una breve descripción de cada variable:

- `do_public_key`: Debes especificar el nombre de tu clave pública que utilizarás para acceder al servidor.

- `droplet_image`: Selecciona la imagen de Droplet de DigitalOcean que deseas utilizar, en este caso, "wordpress-20-04".

- `droplet_name`: Define el nombre de tu Droplet, que identificará tu servidor en DigitalOcean.

- `droplet_region`: Selecciona la región de DigitalOcean donde se creará el Droplet. En este caso, "fra1" se refiere a la región de Frankfurt.

- `droplet_size`: Especifica el tamaño del Droplet, en este caso, "s-2vcpu-4gb".

**Archivo variables.tf 🧾**

En este archivo, definiremos las variables que usaremos en nuestro proyecto. Estas variables son esenciales para la configuración de Terraform.

```
variable "do_token" {}
variable "do_public_key" {}
variable "droplet_name" {}
variable "droplet_image" {}
variable "droplet_region" {}
variable "droplet_size" {}

```

**Archivo output.tf 📤**

```
output "droplet_name" {
  value = digitalocean_droplet.mi_droplet.name
}

output "droplet_ip" {
  value = digitalocean_droplet.mi_droplet.ipv4_address
}

output "droplet_price" {
  value = digitalocean_droplet.mi_droplet.price_monthly
}

```

Este archivo definirá las salidas de datos que serán útiles para nuestro servidor, como el nombre, la dirección IP y el precio mensual.

Asegúrate de configurar estos valores según tus necesidades y preferencias antes de ejecutar Terraform.

No olvides configurar el valor de `var.do_token` en los secretos de tu repositorio en GitHub. También, para acceder a tu servidor, genera una clave SSH utilizando el comando:

```
ssh-keygen -t rsa -C "tu_email@example.com" -f ./tf-digitalocean   

```

Finalmente, sube tu clave pública y privada a los secretos de tu repositorio.

Ahora comenzaremos a crear nuestras pipelines. Para ello, crearemos una carpeta llamada **.github** y dentro de ella crearemos una carpeta llamada **workflows**. Dentro de esta carpeta, se crearán los siguientes archivos YAML:

**Archivo ci.yml 🔄**

Este archivo define una pipeline de CI/CD que utiliza varios desencadenadores (`on`) y entradas (`inputs`) para controlar la ejecución de trabajos específicos. Los trabajos se ejecutan en función de las entradas proporcionadas y las necesidades específicas de tu flujo de trabajo.

```
name: CI + CD

on:    
  workflow_dispatch:
    inputs:
      terraform:
        description: Create infrastructure
        type: boolean
        required: false
        default: false
      install_wp_cli:
        description: Install WP CLI
        type: boolean
        required: false
        default: false        
      theme_test:
        description: Test theme
        type: boolean
        required: false
        default: false
      pull_request_development:
        description: Create pull request to development
        type: boolean
        required: false
        default: false     
      pull_request_production:
        description: Create pull request to production
        type: boolean
        required: false
        default: false 
      version_type:
        type: choice
        description: Define the version type
        default: ""
        options:
        - patch 
        - minor
        - major       
      ip_address:
        description: IP de acesso ao servidor
        type: string
        required: false
        default: ""    
      deploy:
        description: Deploy to production
        type: boolean
        required: false
        default: false  
      bump:
        description: Bump version
        type: boolean
        required: false
        default: false                

jobs:
  terraform:
    name: Create infrastructure
    if: ${{ inputs.terraform }}
    uses: ./.github/workflows/terraform.yml 
    secrets:
      TF_DIGITALOCEAN_PUB: ${{ secrets.TF_DIGITALOCEAN_PUB }}
      DIGITALOCEAN_TOKEN: ${{ secrets.DIGITALOCEAN_TOKEN }}

  install_wp_cli:
    name: Install WP CLI
    if: ${{ inputs.install_wp_cli }}
    uses: ./.github/workflows/install_wp_cli.yml  
    with:
      ip_address: ${{ inputs.ip_address }}    
    secrets:
      USERNAME: ${{ secrets.USERNAME }}
      TF_DIGITALOCEAN_PUB: ${{ secrets.TF_DIGITALOCEAN_PUB }}
      PORT: ${{ secrets.PORT }}            
      
  theme_test:
    name: Test application
    if: ${{ inputs.theme_test }} || ${{ inputs.pull_request_development }} || ${{ inputs.pull_request_production }} || ${{ inputs.bump }} 
    uses: ./.github/workflows/theme_review_action.yml

  pull_request_development:
    name: Open pull request to development
    if: ${{ inputs.pull_request_development }}
    needs: [theme_test]    
    uses: ./.github/workflows/pull_request.yml  

  type_version:
    name: Type version
    if: ${{ inputs.pull_request_production }}
    needs : [theme_test]
    uses: ./.github/workflows/type_version.yml  
    with:
      version_type: ${{ inputs.version_type }}
     
  pull_request_production:
    name: Open pull request to production
    if: ${{ inputs.pull_request_production }} 
    needs: [type_version]
    uses: ./.github/workflows/pull_request.yml     

  deploy_production:
    name: Deploy to production
    if: ${{ inputs.deploy }}
    uses: ./.github/workflows/deploy_theme.yml    
    with:
      ip_address: ${{ inputs.ip_address }}
    secrets:
      USERNAME: ${{ secrets.USERNAME }}
      TF_DIGITALOCEAN_PUB: ${{ secrets.TF_DIGITALOCEAN_PUB }}
      PORT: ${{ secrets.PORT }}    

  deploy_bump_versio:
    name: Deploy to production and bump version
    if: ${{ inputs.bump }}
    needs: [theme_test]
    uses: ./.github/workflows/deploy_theme.yml   
    with:
      ip_address: ${{ inputs.ip_address }}    
    secrets:
      USERNAME: ${{ secrets.USERNAME }}
      TF_DIGITALOCEAN_PUB: ${{ secrets.TF_DIGITALOCEAN_PUB }}
      PORT: ${{ secrets.PORT }}               

```

Como podrás observar en este flujo, nos apoyamos en los inputs para poder ejecutar los trabajos que necesitemos. Aunque este flujo no sea el más óptimo, nos permite realizar pruebas de forma sencilla y nos brinda la flexibilidad de personalizarlo a nuestro gusto y mejorarlo.

**Job: terraform.yml 🏗️**

```
name: DigitalOcean

on:    
  workflow_call:
    secrets:
      TF_DIGITALOCEAN_PUB: 
        required: true    
      DIGITALOCEAN_TOKEN: 
        required: true  

env:
  TF_DIGITALOCEAN_PUB: ${{ secrets.TF_DIGITALOCEAN_PUB }}
  DIGITALOCEAN_TOKEN: ${{ secrets.DIGITALOCEAN_TOKEN }}
    
jobs:
  terraform:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout código fuente
      uses: actions/checkout@v4

    - name: Mover llave pública
      run: |
        echo "$TF_DIGITALOCEAN_PUB" > ./terraform/tf-digitalocean.pub
        echo $DIGITALOCEAN_TOKEN
    
    - name: Configurar Terraform
      run: |
        terraform -chdir=./terraform init -var do_token=$DIGITALOCEAN_TOKEN
        terraform -chdir=./terraform validate

    - name: Aplicar infraestructura
      run: |
        terraform -chdir=./terraform apply -auto-approve -var do_token=$DIGITALOCEAN_TOKEN

    - name: Esperar 15 minutos
      run: sleep 900

    - name: Destruir infraestructura
      run: |
        terraform -chdir=./terraform destroy -auto-approve -var do_token=$DIGITALOCEAN_TOKEN

```

En este código, hemos creado un servidor en DigitalOcean y disponemos de 15 minutos para realizar las pruebas que necesites.

**Job: type\_version.yml 🆕**

```
name: Type version

on:    
  workflow_call:
    inputs:
      version_type:
        description: 'Tipo de versión'
        required: true
        default: ''
        type: string  

jobs:
  type-version:
    runs-on: ubuntu-latest 
    timeout-minutes: 10    
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}
          token: ${{ secrets.GITHUB_TOKEN }}
          fetch-depth: 0
                
      - name: Obtener versión
        id: version
        run: |
          echo " **********************"
          git config user.name "$GITHUB_ACTOR"
          git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
          versionold=$(npm run env | grep npm_package_version | awk -F= '{print $2}')
          npm version ${{ inputs.version_type }} -m "v%s"
          version=$(node -p "require('./package.json').version")
          echo "::set-output name=versionold::${versionold}"
          echo "::set-output name=version::${version}"
          echo " **********************"

      - name: Cambiar versión en style.css
        run: |
          echo " **********************"
          git config user.name "$GITHUB_ACTOR"
          git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
          sed -i "s/${{ steps.version.outputs.versionold }}/${{ steps.version.outputs.version }}/g" style.css
          git add style.css
          git commit -m "Actualizar versión a ${{ steps.version.outputs.version }}"
          git push --force
          echo " **********************"          

```

**Job: deploy\_theme.yml 🚚**

```
name: Install theme on production

on:
  workflow_call:
    secrets:
      USERNAME: 
        required: true    
      TF_DIGITALOCEAN_PUB: 
        required: true
      PORT: 
        required: true      
    inputs:
      ip_address:
        description: 'IP address of the server'
        required: true
        default: ''  
        type: string           
  pull_request:
    branches:
      - 'production'      
    types:
      - closed                  
      
jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: Production
    timeout-minutes: 15
    steps:    
      - name: executing remote ssh commands using private key   
        uses: appleboy/ssh-action@v1.0.0
        with:
          host: ${{ inputs.ip_address }}
          username: ${{ secrets.USERNAME }}
          key: ${{ secrets.TF_DIGITALOCEAN_PUB }}
          port: ${{ secrets.PORT }}
          script: |
            echo "Activating maintenance mode"
            wp --path=/var/www/html --allow-root maintenance-mode activate
            echo "Deploying theme to server"
            git clone https://github.com/danieljsaldana/deploy-theme-wordpress.git 
            echo "Changing permissions"
            chown -R www-data:www-data deploy-theme-wordpress
            echo "Backing up current theme"
            mv /var/www/html/wp-content/themes/deploy-theme-wordpress /var/www/html/wp-content/themes/deploy-theme-wordpress.bak   
            echo "Deploying theme"          
            rsync -av deploy-theme-wordpress /var/www/html/wp-content/themes 
            echo "Removing backup"           
            rm -fr /var/www/html/wp-content/themes/deploy-theme-wordpress.bak
            echo "Removing deploy folder"
            rm -rf deploy-theme-wordpress
            echo "Deploying theme to server completed"    
            echo "Deactivating maintenance mode"
            wp --path=/var/www/html --allow-root maintenance-mode deactivate

```

En este codigo, lo que hacemos es desplegar el theme en el servidor de produccion. Para ello nos conectamos por ssh y ejecutamos los comandos necesarios para desplegar el theme.

Recordar que nuestra pipeline funcione debemos de agregar todos los secretos que hemos definido en los workflows.

#### Conclusiones

En este laboratorio, hemos explorado cómo automatizar el proceso de despliegue de un tema de WordPress en un servidor alojado en DigitalOcean utilizando GitHub Actions. Esta automatización te permite ahorrar tiempo y reducir errores al eliminar la necesidad de realizar despliegues manuales. 🕒

Comenzamos creando un entorno de servidor en DigitalOcean utilizando Terraform. Configuramos los recursos esenciales, como la imagen del servidor, su ubicación y su tamaño. Personalizamos estos detalles mediante un archivo terraform.tfvars que contiene variables clave. ⚙️

Luego, configuramos flujos de trabajo en GitHub Actions que nos permiten controlar todo el proceso. Desde la creación del servidor con Terraform hasta el despliegue del tema en producción, cada paso se ha automatizado. 🤖

Además, hemos explorado cómo cambiar la versión del tema y realizar pruebas con GitHub Actions. Estos flujos de trabajo se han diseñado para adaptarse a diferentes situaciones, como la creación de solicitudes de extracción a ramas de desarrollo y producción. 📈

Finalmente, hemos observado cómo el tema se despliega en el servidor de producción mediante una conexión SSH. Hemos seguido prácticas recomendadas, como activar el modo de mantenimiento y realizar copias de seguridad del tema actual para asegurarnos de que el proceso sea seguro y confiable. 🔑

Este enfoque de automatización con GitHub Actions simplifica tus tareas de administración y te permite centrarte en el desarrollo de tu sitio de WordPress. Recuerda configurar los secretos adecuados y personalizar los flujos de trabajo según tus necesidades específicas. 💪