Integración continua (CI)

GitBeginner
Practicar Ahora

Introducción

Imagine que escribe un libro con un equipo grande. Cada vez que alguien envía un capítulo nuevo, debe comprobar si hay errores ortográficos o problemas en la trama. Hacerlo manualmente resulta agotador.

En el desarrollo de software, resolvemos este problema mediante la integración continua (CI). La CI comprueba automáticamente los cambios desde el principio. Normalmente, instala las dependencias, ejecuta las pruebas y valida el proyecto después de cada actualización.

La idea clave es obtener comentarios rápidamente. Es más fácil corregir los problemas cuando se detectan inmediatamente después de un cambio que varios días más tarde.

Por eso, la CI suele ser la primera capa de automatización que crean los equipos. Protege la rama principal al convertir cada push en una comprobación automática de calidad.

En este laboratorio, creará esta red de seguridad para una aplicación sencilla de Node.js. Usted:

  • Creará una aplicación pequeña que realice operaciones matemáticas básicas.
  • Escribirá una prueba para demostrar que las operaciones matemáticas son correctas.
  • Configurará GitHub Actions para ejecutar esta prueba automáticamente cada vez que envíe código mediante un push.
  • Romperá el código intencionadamente para comprobar cómo la red de seguridad detecta el error.

Requisitos previos

Este laboratorio se basa en el anterior. Continuaremos utilizando el repositorio github-actions-basics que creó.

Prepare el proyecto de Node.js

Primero necesitamos código que probar. Crearemos una aplicación pequeña de Node.js. Si no es programador, no se preocupe: le proporcionaremos todo el código que necesita.

Vaya al directorio del proyecto. Como este es un entorno de laboratorio nuevo, debemos descargar el repositorio otra vez.

cd ~/project
git clone https://github.com/your-username/github-actions-basics.git
cd github-actions-basics

Nota: recuerde sustituir your-username por su nombre de usuario real de GitHub.

Necesitamos crear tres archivos para simular un proyecto real. Usaremos el comando cat, que permite crear rápidamente archivos con contenido directamente desde la línea de comandos.

1. La «receta» (package.json)

Este archivo indica al equipo qué es nuestro proyecto y qué herramientas necesita. Indicamos que el proyecto depende de una herramienta de pruebas llamada jest.

cat > package.json << EOF
{
  "name": "ci-demo",
  "version": "1.0.0",
  "scripts": {
    "test": "jest"
  },
  "dependencies": {
    "jest": "^29.7.0"
  }
}
EOF

2. La «comida» (index.js)

Este es el código de nuestra aplicación. Se trata de una función sencilla que suma dos números.

cat > index.js << EOF
function sum(a, b) {
  return a + b;
}
module.exports = sum;
EOF

3. La «prueba de sabor» (index.test.js)

Esta es nuestra prueba automatizada. Comprueba que, si sumamos 1 y 2, el resultado debe ser 3.

cat > index.test.js << EOF
const sum = require('./index');

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});
EOF

Ahora que hemos creado los archivos, debemos guardarlos en GitHub. Ejecute los comandos estándar de Git para cargar su trabajo.

git add .
git commit -m "Add Node.js project files"
git push

Es posible que se le pida iniciar sesión en GitHub otra vez. Use su nombre de usuario y su Personal Access Token (PAT), como antes.

Cree el flujo de trabajo de CI

Ahora debemos indicar a nuestro asistente robot cómo probar este código. Crearemos un archivo de flujo de trabajo llamado ci.yml en la carpeta estándar .github/workflows.

touch .github/workflows/ci.yml

Abra este archivo en el editor nano.

nano .github/workflows/ci.yml

Añada la siguiente configuración. A continuación explicaremos las partes nuevas.

name: Node.js CI

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 16

Aquí introducimos una palabra clave nueva y potente: uses.

Este es un patrón importante de GitHub Actions. En lugar de escribir manualmente cada paso de shell, los flujos de trabajo suelen combinar acciones reutilizables que agrupan tareas habituales, como extraer el código, configurar un lenguaje o cargar artefactos.

Piense en uses como si descargara una habilidad en el cerebro del robot. En lugar de escribir scripts complejos desde cero, podemos utilizar acciones prediseñadas creadas por otras personas.

  • actions/checkout@v4: esta acción estándar indica al robot: «Descarga mi código». Sin ella, el robot tendría un espacio de trabajo vacío.
  • actions/setup-node@v3: instala Node.js en el ejecutor. También le pasamos una versión específica (16) para garantizar la coherencia.

Guarde el archivo y salga del editor (Ctrl+X, Y, Enter).

Añada los pasos de instalación y pruebas

Ya tenemos el código, extraído mediante checkout, y las herramientas, incluido Node.js. Ahora debemos ejecutar realmente la prueba.

En el ecosistema de Node.js, existen dos comandos estándar para ello:

  1. npm install: descarga todas las dependencias indicadas en package.json, como la herramienta de pruebas jest.
  2. npm test: ejecuta el script de prueba definido en package.json.

Juntos, estos pasos representan el núcleo de la CI: preparar el entorno, instalar las dependencias y validar el código en un ejecutor limpio antes de aceptar que el cambio es correcto.

Añadamos estos pasos al flujo de trabajo. Abra de nuevo .github/workflows/ci.yml.

nano .github/workflows/ci.yml

Añada estos dos pasos al final del archivo. Asegúrese de que la sangría coincida con la de los pasos anteriores.

- name: Install dependencies
  run: npm install

- name: Run tests
  run: npm test

El archivo completo debería tener este aspecto:

name: Node.js CI

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 16

      - name: Install dependencies
        run: npm install

      - name: Run tests
        run: npm test

Guarde el archivo y salga del editor.

Ahora active su red de seguridad enviando este archivo a GitHub mediante un push.

git add .
git commit -m "Add CI pipeline"
git push

Vaya a su repositorio en GitHub y haga clic en la pestaña Actions. Debería ver un flujo de trabajo nuevo llamado «Node.js CI» en ejecución. Cuando termine, verá una marca de verificación verde. Esto significa que el código funciona.

CI Pipeline

Rompa la compilación

Una red de seguridad solo es útil si lo protege cuando cae. Vamos a «romper» el código intencionadamente para observar el sistema de CI en acción.

Editaremos el archivo de prueba para que, en esencia, mienta. Afirmaremos que 1 + 2 debe ser igual a 4.

Abra index.test.js con nano.

nano index.test.js

Cambie la expectativa de la prueba de 3 a 4.

const sum = require("./index");

test("adds 1 + 2 to equal 3", () => {
  expect(sum(1, 2)).toBe(4); // CHANGED 3 to 4
});

Guarde el archivo y salga. Ahora confirme y envíe este «error» mediante un push.

git add .
git commit -m "Intentionally break the test"
git push

Vuelva inmediatamente a la pestaña Actions de GitHub. Observe la ejecución del flujo de trabajo nuevo.

En unos instantes, la ejecución debería fallar. Verá un icono de X roja junto al commit. Es el sistema de CI gritando: «¡Alto! Algo no funciona».

Haga clic en la ejecución fallida y, después, haga clic en el trabajo build. Expanda el paso Run tests para ver el registro del error:

Error: expect(received).toBe(expected) // Object.is equality

Expected: 4
Received: 3

Esta sencilla X roja ahorra incontables horas de trabajo a los desarrolladores, porque detecta los errores en el momento en que se producen, en lugar de días o semanas más tarde.

CI Pipeline Failed

Resumen

En este laboratorio, creó una canalización de Integración Continua profesional.

Aprendió:

  • Cómo definir la «receta» de un proyecto mediante package.json.
  • Cómo utilizar la palabra clave uses para instalar herramientas potentes como actions/checkout y actions/setup-node.
  • Cómo automatizar las pruebas para que un robot verifique cada cambio de código.
  • La importancia de la «X roja» como red de seguridad para el código.

A continuación, aprenderemos a tomar código funcional y empaquetarlo para que el mundo pueda verlo.