Blog

Optimiza el Desarrollo con CI/CD en GitHub

/ github actions, pipelines, workflow, ci/cd

La integración continua y el despliegue continuo o CI/CD se han convertido en una herramienta clave para el desarrollo de software. CI/CD facilita la entrega de códigos con frecuencia, precisión y la mejor calidad posible, ya que elimina la necesidad de realizar pruebas y despliegues manuales.

¿Qué es GitHub Actions?

GitHub Actions es una potente funcionalidad integrada en GitHub, diseñada para ayudarnos a automatizar nuestros procesos de desarrollo de software. Nos permite compilar, probar y desplegar nuestro código directamente desde GitHub. La magia de GitHub Actions reside en su flexibilidad y facilidad de uso. Con sólo unos pocos archivos de configuración YAML, podemos construir flujos de trabajo personalizados que se ejecutan cada vez que se producen eventos específicos en nuestro repositorio, como un push a una rama o la creación de un pull request.

Imagina no tener que preocuparte de ejecutar pruebas o desplegar aplicaciones manualmente. GitHub Actions lo hará todo por nosotros. Es compatible con una amplia gama de lenguajes de programación y plataformas, por lo que es adecuado para cualquier proyecto. Y, obviamente, se integra a la perfección con el ecosistema de GitHub, por lo que podemos utilizarlo junto a otras herramientas que ya nos encantan.

¿Qué es un flujo de trabajo?

En el mundo de GitHub Actions, un flujo de trabajo es un conjunto personalizable de procesos automatizados que pueden manejar cualquier cosa, desde ejecutar pruebas hasta desplegar tu última obra maestra. También podemos conocerlos como pipelines. Estos flujos de trabajo se definen mediante archivos YAML, que añadimos a nuestro repositorio.

Configurar un flujo de trabajo

Configurar las Acciones de GitHub es sencillo, sólo tenemos que crear un archivo YAML que defina nuestro flujo de trabajo y colocarlo en el directorio .github/workflows de nuestro repositorio. Agreguemos un flujo de trabajo al proyecto de la publicación anterior Análisis estático de código PHP con PHPStan. El repositorio publico es hexagonal-architecture-example-in-php.

name: Test  

on:  
  push:  
    branches: [ 'master' ]  
  pull_request:  
    types: [ 'opened', 'synchronize', 'reopened' ]  

jobs:  
  test:  
    runs-on: ubuntu-latest  

    strategy:  
      matrix:  
        php-version: [ '8.2', '8.3' ]  

    steps:  
      - name: Checkout source code  
        uses: actions/checkout@v2  
        with:  
          fetch-depth: 0

En el ejemplo anterior hemos definido un nuevo flujo de trabajo, vamos a desglosar el código y explicar lo que está sucediendo:

  • El nombre del flujo de trabajo es Test.
  • Este flujo de trabajo se ejecutará para dos eventos:
    • Cuando push código en la rama master.
    • Cuando pull_request es opened, synchronize y reopened.
  • Hemos definido un trabajo llamado test.
  • El trabajo test se ejecuta en un sistema operativo ubuntu-latest.
  • Como nuestro código es PHP definimos que el trabajo test necesita ser ejecutado para dos versiones diferentes de PHP 8.2 y 8.3.
  • Finalmente, usamos la sección steps para definir cada acción que necesitamos ejecutar dentro de nuestro flujo de trabajo o pipeline.

Qué incluir en el flujo de trabajo

Como mínimo, nuestros flujos de trabajo deberían incluir los siguientes pasos:

  • Configuración del runtime: Configurar el entorno de ejecución necesario para el proyecto.
  • Clonado del código: Recuperar el último código del repositorio.
  • Instalación de dependencias: Instalar todas las dependencias necesarias para el proyecto.
  • Ejecución de pruebas: Ejecutar todas las pruebas necesarias para asegurar la funcionalidad del código.
  • Comprobación del estilo del código: Verificar que el código se adhiere a las directrices de estilo del proyecto.
  • Análisis estático del código: Analizar el código para identificar posibles problemas y aplicar las normas de codificación.

Añadamos algunos de estos pasos a nuestro flujo de trabajo:

name: Test  

on:  
  push:  
    branches: [ 'master' ]  
  pull_request:  
    types: [ 'opened', 'synchronize', 'reopened' ]  

jobs:  
  test:  
    runs-on: ubuntu-latest  

    strategy:  
      matrix:  
        php-version: [ '8.2', '8.3' ]  

    steps:  
      - name: Checkout Source Code  
        uses: actions/checkout@v4  
        with:  
          fetch-depth: 0  

      - name: Set up PHP ${{ matrix.php-version }}  
        uses: shivammathur/setup-php@v2  
        with:  
          php-version: ${{ matrix.php-version }}  
          coverage: xdebug  
          tools: composer:v2  

      - name: Cache Dependencies  
        uses: actions/cache@v4
        with:  
          path: ~/.composer/cache  
          key: php-${{ matrix.php-version }}-composer-${{ hashFiles('**/composer.json') }}  
          restore-keys: php-${{ matrix.php-version }}-composer-  

      - name: Validate Composer Files  
        run: composer validate  

      - name: Install Dependencies  
        if: steps.composer-cache.outputs.cache-hit != 'true'  
        run: composer install --prefer-dist --no-progress --no-suggest  

      - name: Prepare App Installation  
        run: |  
          mkdir -p data  
          composer db:initialize  

      - name: Execute Static Code Analysis  
        run: composer workflow:analyze  

      - name: Execute Unit, Integration and Acceptance Tests  
        run: composer workflow:test

De nuevo, vamos a desglosar el código y explicar lo que acabamos de hacer:

  1. Código Checkout: Utiliza la Acción de pago.
  2. Configurar versión de PHP: Utilice la Acción Configurar PHP.
  3. Dependencias de Caché: Utilice la Acción Caché. Para obtener más información, consulte Almacenamiento en caché de dependencias para acelerar los flujos de trabajo.
  4. Validar archivos de Composer: Ejecute el comando composer validate.
  5. Instalar dependencias: En primer lugar, comprueba si las dependencias almacenadas en caché están disponibles. Si no es así, ejecute el comando habitual composer install.
  6. Preparar la instalación del proyecto: Ejecutar comandos para preparar e instalar la aplicación, como desplegar el esquema de base de datos si es necesario.
  7. Ejecutar análisis estático de código.
  8. Ejecutar Pruebas.

Ejecutando un flujo de trabajo

Ahora que todo está configurado, todo lo que tenemos que hacer es confirmar y empujar nuestro código a una nueva rama. Después, crearemos un nuevo pull request (PR). Las Acciones de GitHub se activarán automáticamente, ya que hemos configurado nuestro flujo de trabajo para que se ejecute cuando se abra una pull request. En la página PR, veremos el estado de los flujos de trabajo que hemos definido.

github-action-pr-view

En este caso el flujo de trabajo ha tenido éxito, revisemos un ejemplo de flujo de trabajo fallido. Por ejemplo, podemos eliminar algún PHPDoc para forzar a PHPStan a fallar el análisis estático de código.

github-action-pr-view-failing

Podemos obtener más información sobre el error haciendo clic en el enlace "Detalles" de cada comprobación de flujo de trabajo, revisemos la ejecución 8.2.

github-action-execution-logs

Aquí podemos comprobar los detalles sobre los errores. Muy chulo, ¿eh? ¿Pero adivina qué? Hay otra manera de obtener información aún más detallada sobre lo que ha ido mal. Hemos configurado PHPStan con --error-format=github, así que esto nos dará la siguiente salida:

> vendor/bin/phpstan analyse --error-format=github --no-progress
Note: Using configuration file hexagonal-architecture-example/phpstan.neon.
::error file=src/UserManagement/Application/Contract/UserRepository.php,line=13,col=0::Method OtherCode\UserManagement\Application\Contract\UserRepository::all() return type has no value type specified in iterable type array.
::error file=src/UserManagement/Infrastructure/Persistence/DoctrineUserRepository.php,line=28,col=0::Method OtherCode\UserManagement\Infrastructure\Persistence\DoctrineUserRepository::all() return type has no value type specified in iterable type array.
::error file=src/UserManagement/Infrastructure/Persistence/JsonFileUserRepository.php,line=65,col=0::Method OtherCode\UserManagement\Infrastructure\Persistence\JsonFileUserRepository::all() return type has no value type specified in iterable type array.
Script vendor/bin/phpstan analyse --error-format=github --no-progress handling the workflow:analyze event returned with error code 1

Esta es una salida especial que GitHub sabe manejar, permitiéndonos ver los errores directamente en la pestaña "cambios en el archivo" del PR.

github-action-pr-view-feedback

Esto sí que es asombroso. Con esta configuración, podemos entender fácilmente lo que está pasando y solucionarlo adecuadamente. Esta integración mejora drásticamente la experiencia del desarrollador.

Conclusión

En conclusión, integrar CI/CD con GitHub Actions realmente mejora nuestro flujo de trabajo de desarrollo. Mediante la automatización de tareas como el análisis de código y las pruebas, nos aseguramos una entrega de software más rápida y fiable. GitHub Actions nos da esta plataforma impresionante para definir nuestros pipelines de desarrollo de una manera fácil, lo que significa que nuestro código mejora y nuestro equipo trabaja de manera más eficiente.

Siguiente Postt Post Anterior