¿Cómo puedo usar las Acciones de GitHub para crear flujos de trabajo para CI?

Completado

Aquí encontrará información sobre los flujos de trabajo y las Acciones de GitHub para CI.

Aprenderá a:

  • Crear un flujo de trabajo a partir de una plantilla.
  • Comprender los registros de las Acciones de GitHub.
  • Realizar pruebas con varios destinos.
  • Separar los trabajos de compilación y prueba.
  • Guardar los artefactos de compilación y acceder a ellos.
  • Automatizar el etiquetado de una solicitud de incorporación de cambios en la revisión.

Creación de un flujo de trabajo a partir de una plantilla

Para crear un flujo de trabajo, empiece por usar una plantilla. Una plantilla tiene trabajos y pasos comunes preconfigurados para el tipo de automatización concreto que está implementando. Si no está familiarizado con los flujos de trabajo, los trabajos y los pasos, consulte el módulo Automatización de las tareas de desarrollo mediante Acciones de GitHub.

En la página principal del repositorio, seleccione la pestaña Acciones para crear un Nuevo flujo de trabajo.

En la página Elegir un flujo de trabajo, puede elegir entre muchas plantillas diferentes. Un ejemplo es la plantilla de Node.js, que realiza una instalación limpia de dependencias de nodo, compila el código fuente y ejecuta pruebas para diferentes versiones de Node. Otro ejemplo es la plantilla de paquete de Python, que instala las dependencias de Python y ejecuta pruebas, incluida lint, en distintas versiones de Python.

En el cuadro de búsqueda, escriba Node.js.

Screenshot showing GitHub Actions tab with the search box highlighted and containing the text 'Node.js'.

En los resultados de la búsqueda, en el panel Node.js, seleccione Configurar.

Screenshot showing GitHub Actions tab with the Node.js pane highlighted and the Node.js template selected.

Verá este flujo de trabajo de plantilla de Node.js predeterminado en el archivo recién creado node.js.yml.

name: Node.js CI

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build:

    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [14.x, 16.x, 18.x]

    steps:
    - uses: actions/checkout@v3
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v3
      with:
        node-version: ${{ matrix.node-version }}
        cache: 'npm'
    - run: npm ci
    - run: npm run build --if-present
    - run: npm test

Observe el atributo on:. Este flujo de trabajo se desencadena con un envío de cambios al repositorio, y cuando se realiza una solicitud de incorporación de cambios en la rama principal.

Hay un elemento job en este flujo de trabajo. Revisemos lo que tenemos.

El atributo runs-on: especifica que, para el sistema operativo, el flujo de trabajo se ejecuta en ubuntu-latest. El atributo node-version: especifica que hay tres compilaciones: una para la versión 14.x de Node, otra para la versión 16.x y otra para la versión 18.x. La parte matrix se describirá más adelante, cuando personalicemos el flujo de trabajo.

En el elemento steps del trabajo se usa la acción actions/checkout@v3 de Acciones de GitHub para obtener el código del repositorio en la máquina virtual y la acción actions/setup-node@v3 para configurar la versión correcta de Node.js. Especificamos que vamos a probar tres versiones de Node.js con el atributo ${{ matrix.node-version }}. Este atributo hace referencia a la matriz que definimos anteriormente. El atributo cache especifica un administrador de paquetes para el almacenamiento en caché en el directorio predeterminado.

En la última parte de este paso se ejecutan los comandos usados por los proyectos de Node.js. El comando npm ci instala las dependencias del archivo package-lock.json, mientras que npm run build --if-present ejecuta un script de compilación, si existe, y npm test ejecuta el marco de pruebas. Tenga en cuenta que esta plantilla incluye los pasos tanto de compilación como de prueba en el mismo trabajo.

Para obtener más información obre npm, consulte la documentación de npm:

Registros de acciones de la compilación

Al ejecutar un flujo de trabajo, este genera un registro que incluye los detalles de lo sucedido y cualquier error o fallo en las pruebas.

Si se produce un error o si una prueba falla, verá una ✖ roja en lugar de una marca de verificación verde ✔️ en los registros. Puede examinar los detalles del error o el fallo para investigar qué ha pasado.

 GitHub Actions log with details on a failed test.

En el ejercicio, debe identificar las pruebas erróneas examinando los detalles de los registros. Puede acceder a los registros desde la pestaña Acciones.

Personalización de las plantillas de flujo de trabajo

Al principio de este módulo, se describió un escenario en el que era necesario configurar CI para el equipo. La plantilla Node.js es un comienzo excelente, pero quiere personalizarla para que se adapte mejor a los requisitos de su equipo. Quiere tener como destino distintas versiones de Node y sistemas operativos diferentes. También querrá que los pasos de compilación y prueba sean trabajos independientes.

Echemos un vistazo a cómo se puede personalizar un flujo de trabajo.

strategy:
  matrix:
    os: [ubuntu-latest, windows-latest]
    node-version: [16.x, 18.x]

Aquí se ha configurado una matriz de compilación para realizar pruebas en varios sistemas operativos e idiomas. Esta matriz genera cuatro compilaciones, una para cada sistema operativo emparejado con cada versión de Node.

Cuatro compilaciones junto con todas sus pruebas producen bastante información de registro. Puede que sea difícil ordenarlo todo. En el ejemplo siguiente, se muestra cómo trasladar el paso de prueba a un trabajo de prueba dedicado. Este trabajo realiza pruebas con varios destinos. Separar los pasos de compilación y prueba facilita la comprensión del registro.

test:
  runs-on: ${{ matrix.os }}
  strategy:
    matrix:
      os: [ubuntu-latest, windows-latest]
      node-version: [16.x, 18.x]
  steps:
  - uses: actions/checkout@v3
  - name: Use Node.js ${{ matrix.node-version }}
    uses: actions/setup-node@v3
    with:
      node-version: ${{ matrix.node-version }}
  - name: npm install, and test
    run: |
      npm install
      npm test
    env:
      CI: true

¿Qué son los artefactos?

Cuando un flujo de trabajo genera algo que no es una entrada de registro, el producto se denomina artefacto. Por ejemplo, la compilación de Node.js produce un contenedor de Docker que se puede implementar. Este artefacto, el contenedor, se puede cargar en el almacenamiento mediante la acción actions/upload-artifact y se puede descargar posteriormente desde el almacenamiento mediante la acción actions/download-artifact.

El almacenamiento de un artefacto lo conserva entre trabajos. Cada trabajo usa una nueva instancia de una máquina virtual (VM), por lo que no puede volver a usar el artefacto guardándolo en la máquina virtual. Si necesita el artefacto en otro trabajo, puede cargarlo en el almacenamiento de un trabajo y descargarlo para otro.

Almacenamiento de artefactos

Los artefactos se almacenan en el espacio de almacenamiento de GitHub. El espacio es gratuito para los repositorios públicos y tiene una parte gratuita para los repositorios privados, en función de la cuenta. GitHub almacena los artefactos durante 90 días.

En el siguiente fragmento de flujo de trabajo, observe que en la acción actions/upload-artifact@main hay un atributo path:. El valor de este atributo es la ruta de acceso para almacenar el artefacto. Aquí se especifica public/ para cargar todo en un directorio. Si solo quisiéramos cargar un único archivo, usaríamos algo como public/mytext.txt.

  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: npm install and build webpack
        run: |
          npm install
          npm run build
      - uses: actions/upload-artifact@main
        with:
          name: webpack artifacts
          path: public/

Para descargar el artefacto con el fin de realizar pruebas, la compilación debe completarse correctamente y cargarse el artefacto. En el siguiente código, se especifica que el trabajo de prueba depende del trabajo de compilación.

test:
    needs: build
    runs-on: ubuntu-latest

En el siguiente fragmento de flujo de trabajo, se descarga el artefacto. Ahora el trabajo de prueba puede usar el artefacto para las pruebas.

steps:
    - uses: actions/checkout@v3
    - uses: actions/download-artifact@main
      with:
        name: webpack artifacts
        path: public

Para obtener más información sobre el uso de artefactos en flujos de trabajo, consulte Almacenamiento de datos de flujo de trabajo como artefactos en la documentación de GitHub.

Automatización de revisiones en GitHub mediante flujos de trabajo

Hasta ahora hemos hablado de cómo iniciar el flujo de trabajo con eventos de GitHub como el envío de cambios o la solicitud de incorporación de cambios. También se puede ejecutar un flujo de trabajo en una programación o en algún evento fuera de GitHub.

A veces, queremos ejecutar el flujo de trabajo solo después de que una persona realice una acción. Por ejemplo, es posible que solo quiera ejecutar un flujo de trabajo después de que un revisor apruebe la solicitud de incorporación de cambios. En este escenario, se puede desencadenar en pull-request-review.

Otra acción que se puede realizar es agregar una etiqueta a la solicitud de incorporación de cambios. En este caso, se usa la acción pullreminders/label-when-approved-action.

    steps:
     - name: Label when approved
       uses: pullreminders/label-when-approved-action@main
       env:
         APPROVALS: "1"
         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
         ADD_LABEL: "approved"

Observe el bloque denominado env:. En este bloque es donde se establecen las variables de entorno para esta acción. Por ejemplo, puede establecer el número de aprobadores necesarios. En este caso, es uno. La autenticación variable secrets.GITHUB_TOKEN es necesaria porque la acción debe realizar cambios en el repositorio agregando una etiqueta. Por último, proporcione el nombre de la etiqueta que se va a agregar.

Agregar una etiqueta puede ser un evento que inicie otro flujo de trabajo, como una combinación. Este evento se describirá en el módulo siguiente relativo a la entrega continua con Acciones de GitHub.