Home » Primeros pasos con GitHub Actions

Primeros pasos con GitHub Actions

Esta es la primera guía introductoria que escribo sobre GitHub Actions. Es algo extensa pero lo mínimamente detallada para que cualquier principiante pueda asimilar de mejor manera lo que aquí hoy explico.

Quizá hayas escuchado ya algo del tema y estés a punto de dar tus primeros pasos con GitHub Actions. Si es así, has llegado al lugar correcto.

En este artículo explicaré lo básico del tema y dejaré unos ejemplos sencillos de entender. De este modo, puedes ya irte adentrando en el mundo de la automatización en los procesos de desarrollo de software.

1. Introducción

1.1. ¿Qué es GitHub Actions?

GitHub Actions es una plataforma de automatización que te permite crear flujos de trabajo personalizados (workflows) directamente dentro de tus repositorios de GitHub. Estos workflows se ejecutan automáticamente en respuesta a eventos específicos, como cuando se publica o hacer push de un commit o se crea un Pull Eequest.

En pocas palabras, GitHub Actions te permite automatizar tareas repetitivas en tu proceso de desarrollo, como Compilar código, Realizar pruebas, Generar documentación a partir del código y Desplegar aplicaciones.

1.2. Por qué es importante aprenderlo.

Porque es una herramienta fundamental para cualquier desarrollador que quiera optimizar su flujo de trabajo y mejorar la calidad de su código. Al automatizar tareas repetitivas, ahorras tiempo y reduces la posibilidad de errores manuales. Además, te permite integrar de manera fluida diferentes herramientas y servicios, lo que facilita la colaboración en equipo y acelera el proceso de desarrollo.

1.3. Objetivo del artículo

Este artículo no pretende ser una guía muy detallada, ni avanzada sobre GitHub Actions. Por el contrario, me enfocaré en explicar conceptos esenciales y luego te iré llevando de la mano a la práctica con unos ejercicios simples.

2. Conceptos Básicos

2.1. Workflows

Un workflow de GitHub Actions es una secuencia automatizada de tareas que se ejecutan en respuesta a eventos específicos dentro de tu repositorio de GitHub.

En pocas palabras, es como una receta que le dices a GitHub para que realice ciertas acciones de manera automática, como construir tu código, ejecutar pruebas o desplegar tu aplicación.

Por ejemplo, puedes crear un workflow que se ejecute cada vez que alguien hace un cambio en tu código y que automáticamente compile el código, ejecute pruebas y genere un informe.

Aquí un ejemplo de un archivo de workflow de GitHub Actions:

name: CI

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Descargar código del repositorio
        uses: actions/checkout@v4

      - name: Construir proyecto
        run: make build

2.2. Jobs

Un job en un workflow de GitHub Actions es como una tarea específica dentro de un flujo de trabajo más grande. Imagina que un workflow es una receta completa para preparar una comida: cada job sería un paso individual de esa receta, como mezclar los ingredientes, cocinarlos o servirlos.

En resumen, un job es un conjunto de pasos que se ejecutan secuencialmente dentro de un workflow. Estos pasos pueden ser desde descargar el código del repositorio hasta ejecutar pruebas o desplegar una aplicación.

Por ejemplo, en un workflow de CI/CD, un job podría ser el encargado de compilar el código, otro de ejecutar las pruebas y un último de desplegar la aplicación en un servidor.

En el código YAML mostrado anteriormente, existe un único job llamado build que comprende desde las líneas 9 a la 16.

Cómo funcionan los jobs
  1. Activación del workflow:
    • Se produce un evento que desencadena la ejecución del workflow, como un push a un repositorio, la creación de un pull request, o una programación por fecha y hora.
  2. Creación de un runner:
    • GitHub asigna un runner (un entorno de ejecución virtual) para cada job. El runner se configura con el sistema operativo y las herramientas especificadas en el archivo YAML.
  3. Ejecución de los pasos:
    • Los pasos definidos dentro de un job se ejecutan uno tras otro en el runner asignado.
    • Cada paso puede ejecutar comandos, utilizar acciones de terceros o realizar otras tareas.
  4. Finalización del job:
    • Cuando todos los pasos de un job se han ejecutado correctamente, el job se marca como completado. Si alguno de los pasos falla, el job se marcará como fallido y la ejecución del workflow puede detenerse, dependiendo de la configuración.
  5. Ejecución de los siguientes jobs:
    • Si el workflow tiene múltiples jobs, se ejecutarán uno tras otro, siguiendo el orden definido en el archivo YAML.

Aquí otro ejemplo de un workflow con dos jobs: build y test

name: Node.js CI

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Use Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '22'

      - name: Instalar dependencias
        run: npm ci

      - name: Construir el proyecto
        run: npm run build

  test:
    needs:
      - build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Preparar Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '22'

      - name: Instalar dependencias
        run: npm ci

      - name: Hacer pruebas
        run: npm test

Importante:

  • Los workflows pueden configurarse para que ejecuten algunos jobs en paralelo, mientras que otros secuencialmente.
  • Cuando se ejecutan secuencialmente, usualmente se configuran dependencias entre jobs.
  • Muy probablemente, cada job se ejecute siempre en un runner diferente. Por ello, no hay que confiarse en que el runner tendrá presente un archivo o configuración creado localmente en un job para ser usado por otro job posterior.

2.3. Runners

Un runner de GitHub Actions es como una computadora virtual que ejecuta tus workflows. Es el entorno donde se llevan a cabo las tareas que has definido. Imagina que es un asistente que realiza las acciones que le indicas en tu archivo YAML.

Características clave de los runners
  • Entornos virtuales: Cada runner proporciona un entorno aislado para ejecutar tus jobs. Además, usualmente son efímeros: se crean a demanda para cada job y al terminar este se destruyen.
  • Tipos de runners: Existen runners hospedados por GitHub (GitHub-hosted runners) y runners autohospedados (self-hosted runners) que puedes configurar tú mismo.
  • Escalabilidad: GitHub puede escalar automáticamente el número de runners para manejar la carga de trabajo.

Normalmente, los runners hospedados por GitHub pueden tener estos posibles nombres:

  • ubuntu-latest
  • windows-latest
  • macos-latest

En cambio, los runners autohospedados pueden tener el nombre que tú le asignes al momento de la instalación. Esto lo explicaré mejor en otro post aparte.

Si, como todo principiante, estás recién dando tus primeros pasos en GitHub Actions, será mejor que te enfoques solo en usar los runners hospedados por GitHub.

2.4. Steps

Un step en GitHub Actions es como una instrucción individual dentro de un job. Imagina un job como una receta y los steps como cada paso que debes seguir para preparar el plato.

En resumen, un step es una tarea específica que se ejecuta dentro de un job. Puede ser cualquier cosa, desde descargar un archivo hasta ejecutar un comando en la terminal.

Por ejemplo, en un job que compila un proyecto, un step podría ser descargar el código del repositorio y otro step podría ser ejecutar el comando de compilación.

Entonces, un job está conformado por uno o más steps. Así, los steps son las unidades de trabajo más pequeñas e indivisibles en GitHub Actions.

El workflow mostrado al principio tiene un único job que consta de dos steps:

  • Descargar código del repositorio (de tipo uses)
  • Construir proyecto (de tipo run)
name: CI

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Descargar código del repositorio
        uses: actions/checkout@v4

      - name: Construir proyecto
        run: make build

Normalmente, un step puede ser de dos tipo:

  • uses: Llama a un Action existente que agrupa una serie de tareas y pasos encapsulados en una unidad de ejecución. Estos Actions son usualmente creados por terceros y se les puede encontrar en el Marketplace de GitHub.
  • run: Brinda libertad para definir una secuencia de comandos de shell script.

2.5. Eventos

Un evento en GitHub Actions es un suceso que desencadena la ejecución de un workflow.

Imagina que un evento es como un interruptor que enciende una luz. En este caso, la luz sería el workflow y el interruptor sería el evento. Cuando se produce un evento específico (como hacer un push a un repositorio), el workflow se activa y comienza a ejecutar sus tareas.

Ejemplos comunes de eventos:

  • push: Cuando se hacer un push a un repositorio.
  • pull_request: Cuando se crea un Pull Request.
  • schedule: Cuando se programa una ejecución a una fecha y hora determinada.
  • workflow_dispatch: Cuando se inicia un workflow manualmente.

En resumen, los eventos son los detonantes que ponen en marcha los workflows de GitHub Actions.

2.6. Actions

Los Actions de GitHub Actions son como pequeñas piezas de código predefinidas que puedes utilizar para automatizar tareas en tus workflows. Imagina que son como bloques de construcción que encajas para crear tu flujo de trabajo personalizado. Estos Actions pueden realizar tareas como instalar dependencias, ejecutar pruebas, desplegar código, y mucho más.

El Marketplace de GitHub es como una tienda donde puedes encontrar miles de estos Actions creados por la comunidad. Es decir, es un lugar donde puedes buscar y descubrir Actions para cualquier tarea que necesites automatizar, sin tener que escribir todo el código desde cero.

3. Ejemplo 1 de workflow

3.1. Crear repositorio

Empieza por crear un repositorio en GitHub yendo a https://github.com/new y completas la información básica para la creación:

Creación de repositorio en GitHub

3.2. Crear workflow

A través de la interfaz Web, crea un nuevo archivo en la rama por defecto main:

Crear archivo en repositorio Git

Escribe la ruta .github/workflows/workflow1.yml como nombre de archivo:

Definición de ruta de archivo de workflow vía Web en GitHub

Pega el siguiente contenido:

---
on:
  # El workflow se dispara cada vez que se hace
  # un push hacia la rama main
  push:
    branches:
      - main

jobs:
  build:
    # Nombre del job
    name: Compilar nginx
    # Usa runners hospedados por GitHub
    runs-on: ubuntu-latest
    steps:
      - name: Instalar dependencias
        run: |
          # Instala dependencias necesarias para la compilacion
          # de nginx
          sudo apt-get update
          sudo apt-get install -y libpcre2-dev

      - name: Descargar y extraer codigo
        run: |
          wget https://github.com/nginx/nginx/releases/download/release-1.27.3/nginx-1.27.3.tar.gz
          tar -zxf nginx-1.27.3.tar.gz

      - name: Compilar el codigo
        run: |
          cd nginx-1.27.3
          ./configure
          make

3.3. Detalles del workflow

  • Propósito: Este workflow tiene un único job que a través de tres steps instala dependencias con APT (librería de desarrollo de PCRE), luego descarga el código fuente de nginx-1.27.3 y después lo compila.
  • Cómo ejecutarlo: Solo basta hacer un commit y push de cualquier archivo dentro del repositorio en la rama main.

4. Ejemplo 2 de workflow

4.1. Hacer fork de repositorio

Voy a usar el repositorio simple-java-maven-app como base. Para ello, le doy a la opción «Fork» y creo una copia del mismo en mi propia cuenta de GitHub:

Hacer fork de un repositorio GitHub

Deja las opciones por defecto y dale clic al botón «Create fork»:

Confirmar fork de repositorio GitHub

4.2. Crear workflow

Creo un archivo en la rama por defecto master y creo el archivo .github/workflows/workflow2.yml con este contenido:

---
name: Workflow manual

on:
  # Este workflow se ejecuta manualmente
  workflow_dispatch:

jobs:
  build:
    name: Construir proyecto
    runs-on: ubuntu-latest
    # Declaro dos outputs creados por el step "ver-info"
    # que son "nombre" y "version"
    outputs:
      nombre: ${{ steps.ver-info.outputs.nombre }}
      version: ${{ steps.ver-info.outputs.version }}
    steps:
      - name: Checkout de repositorio
        uses: actions/checkout@v4

      # Descargar Oracle Java 21 y configurarlo para que
      # use la cache de Maven
      - name: Instalar Java
        uses: actions/setup-java@v4
        with:
          distribution: oracle
          java-version: 21
          cache: maven

      # Descargo la version minima de Maven requerida
      # por el proyecto
      - name: Instalar Maven
        uses: hb0730/maven-action@v1
        with:
          maven-version: 3.9.3

      # Construyo el proyecto sin realizar pruebas
      - name: Compilar
        run: mvn -B -DskipTests clean package

      # Obtengo el nombre y version del proyecto construido
      # Ambos los guardo como "outputs" de GitHub para poder
      # ser reutilizados en un step o job posterior
      - name: Obtener nombre y version de artefacto
        id: ver-info
        run: |
          nombre=$(mvn -q -DforceStdout help:evaluate -Dexpression=project.name)
          version=$(mvn -q -DforceStdout help:evaluate -Dexpression=project.version)
          echo "nombre=$nombre" >>$GITHUB_OUTPUT
          echo "version=$version" >>$GITHUB_OUTPUT

      # Solo el directorio target lo guardo como artefacto
      - name: Guardar artefacto
        uses: actions/upload-artifact@v4
        with:
          name: artefacto-java
          retention-days: 1
          path: |
            target

  test:
    name: Realizar pruebas
    runs-on: ubuntu-latest
    needs:
      - build
    steps:
      - name: Checkout de repositorio
        uses: actions/checkout@v4

      - name: Instalar Java
        uses: actions/setup-java@v4
        with:
          distribution: oracle
          java-version: 21
          cache: maven

      - name: Set up Maven
        uses: hb0730/maven-action@v1
        with:
          maven-version: 3.9.3

      # Descargo el artefacto antes creado que contiene
      # al directorio target/
      - name: Descargar artefacto
        uses: actions/download-artifact@v4
        with:
          name: artefacto-java

      # Realizo las pruebas del proyecto con Maven
      - name: Probar
        run: mvn test

  exe:
    name: Ejecutar artefacto
    runs-on: ubuntu-latest
    needs:
      - build
      - test
    steps:
      - name: Descargar artefacto
        uses: actions/download-artifact@v4
        with:
          name: artefacto-java

      # Luego de descargar el artefacto que contiene al
      # archivo .jar, lo ejecuto
      # El nombre del .jar se obtiene del valor de los
      # outputs "nombre" y "version" creados en el job build
      - name: Ejecutar .jar
        env:
          NOMBRE: ${{ needs.build.outputs.nombre }}
          VERSION: ${{ needs.build.outputs.version }}
        run: java -jar "${NOMBRE}-${VERSION}.jar"

4.3. Detalles del workflow

  • Propósito: Este workflow tiene tres jobs ejecutados secuencialmente que son build, test y exe:
    • El primer job build construye el proyecto Java usando Maven y guarda el directorio target como artefacto para uso posterior en otro job del mismo workflow.
    • El segundo job test descarga el artefacto ya antes guardado y lo utiliza para realizar las pruebas del proyecto.
    • El tercer job exe descarga el artefacto y ejecuta el archivo .jar
  • Cómo ejecutarlo: En la URL del repositorio del que hiciste fork en tu cuenta (Ejm: https://github.com/arengifoc/simple-java-maven-app), agrega la ruta /actions en la barra de direcciones y luego haz clic en «Workflow manual» (título que le pusiste al workflow dentro del archivo workflow2.yml):
Proceso para ejecutar un workflow manual

Luego, haz clic en «Run workflow» como se muestra debajo:

Confirmar ejecución de workflow manual

Ahora, espera unos segundos o refresca la página y debe aparecer una instancia del pipeline ejecutándose:

Visualizacion de pipelines en ejecucion

Si das clic al nombre del pipeline en ejecución puedes ver los jobs que lo conforman:

Detalle del pipeline ejecutado

Y por último, si das clic a cada uno de los jobs puedes ver el detalle de los mismos.

5. Cierre

Este artículo introductorio «Primeros pasos con GitHub Actions» ha pretendido enseñar los elementos básicos más importantes sobre el tema, lo suficiente como para que un lector principiante pueda en poco tiempo entender los conceptos y llevarlos a la práctica a través de un par de ejemplos.

Los pipelines en GitHub Actions es un tema bastante amplio, por lo mismo seguiré publicando más artículos al respecto sobre aspectos específicos.

Si esto te fue de ayuda, no dudes en compartirlo.

Post navigation

Deja un comentario

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *