Portfolio
Web
CI/CD

Actualizando Portafolio [Parte 4]

En este post les explico los workflows de github actions que implementé en mi proyecto de portfolio.

Ivan Robles

4 min read
Actualizando Portafolio [Parte 4]

Esta es una serie de posts, describiendo los procesos que llevé acabo para la creación de mi portafolio, el cual se encuentra en: https://sharmaz.github.io/me/

[Parte 1, El diseño]
[Parte 2, El setup]
[Parte 3, El desarrollo]
[Parte 4, Los workflows] 👈️ Aquí estamos
[Parte 5, La migración a typescript]

En esta ocasión tocaré el tema de los workflows de github actions. En el desarrollo de software “moderno”, ademas de utilizar un sistema de control de versiones como Git y plataformas para alojar repositorios como github y gitlab. Estas plataformas agregaron maneras de entregar código con mejor calidad. Esto es gracias a los Workflows o Pipelines.

Cuando desarrollamos un producto de software, lo mas seguro es que hay que realizar ciertos procesos como un build de proyecto, hacer tests o hacer deploy a diferentes stages del proyecto.

Los Workflows o Pipelines sirven para automatizar estos procesos, en el momento que se hagan interacciones o acciones en Git, como en el caso de hacer un push, un pull request o un merge.

Github los llamó Workflows y Gitlab Pipelines, voy a atreverme a decir que sirven para lo mismo aunque por definición los conceptos son diferentes.

Github Actions es la plataforma de CI/CD (continuous integration y continuous delivery) de Github. Mis proyectos están en github así que usamos los workflows de Github Actions.

Los Workflows se componen de varias partes:

  • Eventos, van a disparar (triggerear) el workflow.
  • Jobs, una serie de pasos a ejecutar.
  • Actions, son mini aplicaciones que van a correr en el workflow como es el caso del checkout, lo veremos mas adelante.
  • Runners, es la instancia o imagen de sistema operativo donde va a correr el proyecto, como por ejemplo Ubuntu.

Explicándolo de otra manera, un Workflow corre sobre una instancia de sistema operativo (Runner), similar a docker, ejecuta una serie de pasos (Jobs), puede incluir o no acciones que son mini apps muy útiles y es disparado según un evento como puede ser un Pull Request.

El Action utilizado más comúnmente es el de Checkout, lo que hace es clonar o descargar nuestro repositorio en el Runner o sistema operativo que le especificamos a nuestro Workflow.

En mi proyecto inicialmente comencé con 3 Workflows, uno para ejecutar el linter ESlint, otro para las pruebas con Jest y uno mas para hacer deploy a Github Pages. Estos se crean en el directorio .github/workflows y son archivos con extension .yml .

ESlint Workflow

Va a correr ESlint cada vez que se haga un Pull Request a la rama main:

name: ESlint Test
on:
  pull_request:
    branches:
    - main # 👈️ Al pull request en la rama main corremos el job

jobs:
  build:
    runs-on: ubuntu-latest # 👈️ Va a correr en una instancia de ubuntu
    strategy:
      matrix:
        node: ['16'] # 👈️ Con una version de nodejs específica
    steps:
      - uses: actions/checkout@v3 # 👈️ Agrega nuestro repo a ubuntu
      - name: Setup Node 16
        uses: actions/setup-node@v3
        with:
          node-version: 16.x
      - run: npm install  # 👈️ Instalamos las dependencias 
      - run: npm run lint # 👈️ Corremos nuestro script de linter

Después de descargar el repo se van a ejecutar la instalación de dependencias y nuestro script para el linter que definimos en el package.json .

Tests Workflow

Básicamente es lo mismo que el anterior, solo ejecutamos un diferente script, el cual va a correr Jest con sus configuraciones.

name: Jest Tests
on:
  pull_request:
    branches:
    - main

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node: ['16']
    steps:
      - uses: actions/checkout@v3
      - name: Setup Node 16
        uses: actions/setup-node@v3
        with:
          node-version: 16.x
      - run: npm install
      - run: npm run test # 👈️ Corremos las pruebas

Deploy Workflow

Para deployar en github pages le especificamos que el evento sucede cuando se cierre un pull request a main, habiéndose mergeado:

name: Build and Deploy
on:
  pull_request:
    branches:
      - main
    types: [closed] # 👈️ Al cerrarse un PR a la rama Main
permissions:
  contents: write
jobs:
  build-and-deploy:
    if: ${{ github.event.pull_request.merged }} # 👈️ Si el PR fue mergeado
    concurrency: ci-${{ github.ref }}
    runs-on: ubuntu-latest
    steps:
      - name: Checkout 🛎️
        uses: actions/checkout@v3 # 👈️ Nuestro repo se "instala en ubuntu"

      - name: Install and Build 🔧
				# Este es un script que usando las github secrets crea un archivo .env
				# Con esas variables de entorno se hace el build del proyecto
				# El build transpila el proyecto en la carpeta dist
        run: |
          npm ci
          echo -e "API_KEY=${{secrets.API_KEY}}\\nBASE_URL=${{secrets.BASE_URL}}\\nUSER_ID=${{secrets.USER_ID}}" >.env
          npm run build
					# 👆 Este es un script que va a hacer lo siguiente:
					#    Instalar dependencias ci significa clean install
					#    Usando echo, vamos a crear un archivo .env con nuestras variables de entorno
					#    las cuales son tomadas de los secrets en github
					#    Por ultimo vamos a buildear el proyecto en una carpeta dist
      - name: Deploy 🚀
        uses: JamesIves/github-pages-deploy-action@v4
        with:
          folder: dist # 👈️ Se le indica que los archivos que va a servir estan aqui

Conclusión

Aunque estas habilidades entran dentro de las responsabilidades de un DevOps, me pareció interesante y necesario implementarlos en mis proyectos personales.

Usualmente como Frontend Dev, entrando al flujo de desarrollo de un proyecto, los pipelines o workflows ya están ahí, gritando y pidiendo correcciones.

El implementarlo en mis proyectos, aunque fueran pequeños es algo notable.

Estos workflows son básicos y podría decir que fueron introductorios. En la parte de Backend si me aventé unos más avanzados, con base de datos y todo, así como un gran script para el deploy conectándome a un servidor vía ssh y un monton de cosas más… hablaré de ello en post mas adelante.