Actualizando Portafolio [Parte 4]
En este post les explico los workflows de github actions que implementé en mi proyecto de portfolio.
Ivan Robles
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.