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.