Trabajando con GitHub Actions

Trabajando con GitHub Actions

Como desarrolladores, sabemos que hay una gran cantidad de tareas repetitivas que consumen tiempo y pueden ser propensas a errores. Desde la compilación de código hasta las pruebas, el despliegue en diferentes entornos y más, hay muchos procesos que pueden automatizarse. Aquí es donde GitHub Actions brilla, ofreciendo una forma sencilla de configurar flujos de trabajo personalizados directamente en nuestros repositorios.

¿Qué es GitHub Actions?

GitHub Actions es una característica de GitHub que permite la integración continua (CI) y la entrega continua (CD) directamente desde tus repositorios. Con GitHub Actions, puedes crear flujos de trabajo que se ejecutan en respuesta a eventos específicos, como commits, pull requests o la creación de nuevas ramas. Estos flujos de trabajo se definen mediante archivos YAML (.yml) y pueden incluir cualquier cosa, desde pruebas automatizadas hasta despliegues.

Beneficios de Utilizar GitHub Actions

1. Integración y Entrega Continua (CI/CD)

GitHub Actions facilita la implementación de CI/CD, lo que significa que puedes automatizar el proceso de integración y entrega de tu código. Esto asegura que cada cambio en el código es probado y desplegado automáticamente, reduciendo errores y mejorando la calidad del software.

2. Automatización de Tareas Repetitivas

Las tareas repetitivas como la ejecución de pruebas, la creación de builds y el despliegue de aplicaciones pueden ser automatizadas, liberando tiempo para que los desarrolladores se enfoquen en tareas más complejas y creativas.

3. Flexibilidad y Personalización

Con GitHub Actions, tienes total control sobre tus flujos de trabajo. Puedes personalizar cada paso y combinar múltiples acciones para adaptarse a las necesidades específicas de tu proyecto.

4. Integración con el Ecosistema de GitHub

GitHub Actions se integra perfectamente con el ecosistema de GitHub, lo que permite acceder fácilmente a los repositorios, issues y pull requests. Además, puedes utilizar y compartir acciones creadas por la comunidad a través del marketplace de GitHub.

5. Versionado y Colaboración

Al tener los flujos de trabajo definidos como código, podemos versionar, revisar y colaborar en ellos de la misma manera que lo hacemos con nuestras aplicaciones. Esto facilita el mantenimiento y la escalabilidad a medida que nuestros proyectos crecen.

6. Caching de Objetos

El uso de caché en GitHub Actions puede acelerar significativamente los tiempos de ejecución. Al cachear dependencias y otros objetos, puedes evitar la reinstalación de paquetes en cada ejecución, lo que ahorra tiempo y recursos.

Desafíos de GitHub Actions

1. Curva de Aprendizaje

Aunque GitHub Actions es una herramienta poderosa, puede tener una curva de aprendizaje empinada, especialmente si no estás familiarizado con YAML o con la configuración de CI/CD.

2. Complejidad en Proyectos Grandes

En proyectos grandes, la configuración de flujos de trabajo puede volverse compleja. Mantener los archivos YAML organizados y legibles puede ser un desafío.

3. Gestión de Secretos y Credenciales

La gestión de secretos y credenciales es crucial. Si bien GitHub ofrece una forma segura de almacenar y utilizar estos datos sensibles, debemos ser cuidadosos y seguir las mejores prácticas para evitar exponer información confidencial.

4. Limitaciones de Recursos

GitHub ofrece una cantidad limitada de minutos de ejecución gratuitos para GitHub Actions en repositorios públicos y privados. Los proyectos grandes o muy activos pueden superar estos límites, lo que podría incurrir en costos adicionales.

5. Costo por Tiempo de Ejecución

GitHub cobra por el tiempo de ejecución de las acciones. Por lo tanto, es importante optimizar los flujos de trabajo para minimizar el tiempo de ejecución y evitar costos innecesarios.

Estrategias y Recomendaciones

1. Uso de Múltiples Estrategias

GitHub Actions permite usar múltiples estrategias y lenguajes de programación en tus flujos de trabajo. Puedes definir matrices de configuración para probar tu código en diferentes versiones de Node.js, sistemas operativos y más.

2. Crear Tareas Pequeñas

Es recomendable crear tareas o acciones pequeñas para facilitar el debugging. Al mantener las tareas pequeñas y específicas, es más fácil identificar y solucionar problemas cuando ocurren.

3. Uso de Caché

Configura el caché para dependencias y otros recursos comunes para acelerar los tiempos de ejecución.

4. Optimización de Versiones

Cuantas más versiones y configuraciones uses, más tiempo tomará compilar para cada una. Define solo las versiones necesarias para reducir el tiempo de ejecución.

5. Automatización de Dependencias (nodejs)

Automatiza la instalación de dependencias usando un gestor de paquetes rápido como pnpm en lugar de npm para mejorar los tiempos de instalación.

Ejemplos Prácticos

Ahora, vamos a poner manos a la obra con algunos ejemplos prácticos para que puedas comenzar a explorar el poder de GitHub Actions.

Inicializar un Proyecto Node.js

Comencemos por generar el package.json de un proyecto Node.js. Yo generalmente uso pnpm en lugar de npm; te lo recomiendo ya que maneja las dependencias mejor, usando menos espacio y siendo más rápido.

pnpm init

Esto creará un archivo package.json con la estructura básica. Lo siguiente es crear un archivo index.js y pegar el siguiente código (esto es un ejemplo):

index.js

console.log('Hola Mundo');

Configuración de package.json y archivo de Pruebas

Desde la consola, instalaremos el paquete mocha, que usaremos para el ejemplo, y crearemos una prueba sencilla que ejecutaremos desde los scripts del package.json.

pnpm add mocha

Mocha se ha agregado a nuestro package.json y ahora, en la sección scripts, agrega las siguientes líneas:

package.json

{
  "name": "test",
  "version": "1.0.0",
  "description": "Un ejemplo de proyecto Node.js",
  "main": "index.js",
  "scripts": {
+    "build": "echo 'test'",
-    "test": "echo \"Error: no test specified\" && exit 1"
+    "test": "mocha",
+    "ci": "pnpm run build && pnpm run test"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "mocha": "^10.4.0"
  }
}

En este ejemplo, hemos agregado tres scripts: build, test y ci. El script test ejecuta Mocha, un popular marco de pruebas para Node.js, y el script ci compila el proyecto (si es necesario) y luego ejecuta las pruebas. El script build es una simple prueba.

Para que Mocha funcione, necesitarás crear un directorio llamado test en la raíz de tu proyecto y asegurarte de tener al menos un archivo de prueba en el directorio. Aquí tienes un ejemplo simple:

Archivo de prueba test/index.js

const assert = require('assert');

describe('Array', function() {
  describe('#indexOf()', function() {
    it('debería devolver -1 cuando el valor no está presente', function() {
      assert.strictEqual([1, 2, 3].indexOf(4), -1);
    });
  });
});

Ejemplo 1: Compilar y probar un proyecto Node.js

Este ejemplo muestra cómo configurar un flujo de trabajo sencillo para compilar y probar un proyecto Node.js cada vez que se realiza un push a la rama principal. Crea un nuevo archivo llamado .github/workflows/ci.yml en tu repositorio con el siguiente contenido:

name: Node.js CI

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

jobs:  
    build:
        runs-on: ubuntu-latest

steps:
    - uses: actions/checkout@v4
    - uses: actions/setup-node@v4
        with:
            node-version: 18
    - uses: pnpm/action-setup@v4
        with:
            version: 8
    - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v2
        with:
            node-version: ${{ matrix.node-version }}
    - run: pnpm install
    - run: pnpm run ci
    - run: pnpm run build --if-present
    - run: pnpm run test

Este flujo de trabajo se activará en cada push o pull request hacia la rama principal (main). Utilizará la última versión de Ubuntu disponible y ejecutará el código en varias versiones de Node.js.

Los pasos no son tan complicados. Este es un ejemplo simple para que tengas una idea más clara de cómo funciona. Al tener el ambiente preparado, simplemente necesitamos ejecutar los comandos pnpm run ci.

Incluso podrías probar estos comandos en tu terminal y deberían funcionar sin problemas, teniendo una salida como la siguiente:

$ pnpm run ci
> [email protected] ci /Users/jack/Public/test
> pnpm run build && pnpm run test
> [email protected] build /Users/jack/Public/test
> echo 'test'

test

> [email protected] test /Users/jack/Public/test
> mocha

  Array
    #indexOf()
      ✔ debería devolver -1 cuando el valor no está presente

  1 passing (2ms)

Si todo está en orden, estás listo para hacer un git push y eso desplegará la ejecución del action.

Ejemplo 2: Crear un action personalizado con Node.js

Además de utilizar los Actions predefinidos, también puedes crear tus propios Actions personalizados. Esto te permite automatizar tareas más específicas y compartirlas con la comunidad. Veamos cómo crear un sencillo Action de Node.js que imprime un saludo.

Primero, crea un nuevo directorio llamado hello-world-action en tu repositorio. Dentro de este directorio, crea un nuevo archivo action.yml con el siguiente contenido:

name: 'Hello World'
description: 'Greet someone and record the time'
inputs:
  who-to-greet:
    description: 'Who to greet'
    required: true
    default: 'World'
runs:
  using: 'node20'
  main: 'index.js'

A continuación, dentro del directorio hello-world-action crea el archivo index.js con el siguiente código:

const core = require('@actions/core');
const github = require('@actions/github');

try {
  const nameToGreet = core.getInput('who-to-greet');
  console.log(`Hello ${nameToGreet}!`);
  const time = new Date();
  core.setOutput("time", time.toTimeString());
} catch (error) {
  core.setFailed(error.message);
}

También, crea el archivo package.json dentro del directorio hello-world-action con el siguiente contenido:

{
  "name": "hello-world-action",
  "version": "1.0.0",
  "description": "A hello world action",
  "main": "index.js",
  "dependencies": {
    "@actions/core": "^1.10.1",
    "@actions/github": "^6.0.0"
  }
}

Instala las dependencias en tu máquina local ejecutando pnpm install dentro del directorio hello-world-action.

Finalmente, crea un nuevo archivo .github/workflows/action.yml con el siguiente contenido:

on: [push]

jobs:
  hello_world_job:
    runs-on: ubuntu-latest
    name: A job to say hello
    steps:
    - uses: actions/checkout@v4
    - uses: actions/setup-node@v4
      with:
        node-version: '20'
    - uses: pnpm/action-setup@v2
      with:
        version: 8

    - name: Install dependencies
      run: pnpm install
      working-directory: ./hello-world-action

    - name: Hello world action step
      id: hello
      uses: ./hello-world-action
      with:
        who-to-greet: 'Mona the Octocat'

    - name: Get the output time
      run: echo "The time was ${{ steps.hello.outputs.time }}"

Este flujo de trabajo se activará en cada push y ejecutará nuestra Action personalizada, pasando 'Mona the Octocat' como el valor de who-to-greet. Luego, imprimirá la hora generada como salida.

Para probarlo, solamente tienes que hacer un push de todo tu código y en la pestaña de actions deberías tener la salida.

Con esto habrias completado dos diferentes actions para tu proyecto, uno ejecutando un action predefinido con comandos especificos y otro el cual hemos creado y configurado para que realiza tareas especificas con parametros de entrada.

Conclusión

GitHub Actions es una herramienta increíblemente poderosa para la automatización de tareas en el desarrollo de software. Al implementar CI/CD, automatizar tareas repetitivas y personalizar flujos de trabajo según las necesidades del proyecto, los desarrolladores pueden mejorar significativamente su productividad y la calidad del software.

Aunque puede haber una curva de aprendizaje inicial y algunos desafíos en la gestión de flujos de trabajo complejos, los beneficios superan con creces estos inconvenientes. Además, mediante el uso de estrategias como el caching, la creación de tareas pequeñas y específicas, y la optimización de versiones, es posible maximizar la eficiencia y minimizar costos.

Espero que estos ejemplos y recomendaciones te ayuden a comenzar con GitHub Actions y a integrar la automatización en tus proyectos de manera efectiva.

Happy coding! :D


Photo by EJ Strat on Unsplash

Written with StackEdit.

Jack Fiallos

Jack Fiallos

Te gustó este artículo?