Optimiza el Desarrollo con CI/CD en GitHub
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 ramamaster
. - Cuando
pull_request
esopened
,synchronize
yreopened
.
- Cuando
- Hemos definido un trabajo llamado
test
. - El trabajo
test
se ejecuta en un sistema operativoubuntu-latest
. - Como nuestro código es PHP definimos que el trabajo
test
necesita ser ejecutado para dos versiones diferentes de PHP8.2
y8.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:
- Código Checkout: Utiliza la Acción de pago.
- Configurar versión de PHP: Utilice la Acción Configurar PHP.
- 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.
- Validar archivos de Composer: Ejecute el comando
composer validate
. - 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
. - 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.
- Ejecutar análisis estático de código.
- 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.
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.
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
.
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.
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.