Workflows With GitHub Actions

Hernan Castilla
6 min readOct 28, 2021

--

La idea es construir nuestro workflow con GitHub Actions desde lo más simple hasta agregarle un poco de complejidad.

  • One Job
  • Secrets
  • Deploy
  • Multiple Jobs with artifacts
  • Conditioned Jobs And Environments

Para hacer esto un poco más realista, todo el flujo se basará sobre una app con react, pero se puede aplicar a cualquier tipo de código.

One Job

.github/worflows/main.yml

name: workflow with github actions
'on':
push:
branches:
- one-job
jobs:
main:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '14'
- name: install
run: npm install
- name: test
run: npm run test
- name: build
run: npm run build

una de las cosas importantes aquí es definir una versión de node sobre la cual trabajar, por eso usamos actions/setup-node@v2 definiendo nuestra versión como 14, después procedemos a instalar las dependencias, hacer build y ejecutar las pruebas.

Actions secrets

Antes de entrar en temas de deploy debemos saber definir y llamar a nuestras secrets, para definirlas vamos a settings / secrets y damos click en new repository secret

name: TOKEN

value: FIREBASE TOKEN

Agregamos la secret, en este caso voy a hacer un deploy a Firebase hosting, por eso agrego el token .

Para acceder a la secret hacemos

${{ secrets.TOKEN }}

Deploy

Para hacer el deploy basta con agregar otro step a nuestro job que instale el cli de firebase y haga el deploy.

- name: deploy
run: |
npm install -g firebase-tools
firebase deploy --token ${{ secrets.TOKEN }}

main.yml

name: workflow with github actions
'on':
push:
branches:
- one-job
jobs:
main:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '14'
- name: install
run: npm install
- name: test
run: npm run test
- name: build
run: npm run build
- name: deploy
run: |
npm install -g firebase-tools
firebase deploy --token ${{ secrets.TOKEN }}

Listo, tenemos nuestro flujo de un solo job.

Multiple Jobs

La idea es hacer separar todo el flujo en diferentes jobs

jobs:
install_and_test:
runs-on: ubuntu-latest
steps:
- name: install and test
run: echo "install and test"
build:
needs:
- install_and_test
runs-on: ubuntu-latest
steps:
- name: build
run: echo "build"
deploy:
needs:
- build
runs-on: ubuntu-latest
steps:
- name: deploy
run: echo "deploy"

Aquí tenemos el esqueleto, install and test, build, deploy.

Por medio de needs definimos cuáles jobs son necesario para que otros se ejecuten, con esto rompemos el flujo natural que es en paralelo.

Artifacts

Son datos que se comparten entre jobs, uno de ellos lo sube y los otros pueden descargarlo cuando estén ejecutándose.

install_and_test

jobs:
install_and_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '14'
cache: "npm"
- run: npm install
- run: npm test

lo único nuevo es el cache al momento de seleccionar la versión de node, esto nos permite ahorrar algo tiempo al momento de instalar las dependencias en los diferentes jobs

build

build:
needs:
- install_and_test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '14'
cache: npm
- run: npm install
- run: npm run build
- run: rm -r node_modules
- name: artifact
uses: actions/upload-artifact@v2
with:
name: app
path: .

Procedemos a instalar las dependencias, hacer build y borrar la carpeta node_modules, después subimos nuestro codigo como artifact bajo el nombre app.

deploy

deploy:
needs:
- build
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v2
with:
node-version: '14'
- uses: actions/download-artifact@v2
with:
name: app
- name: install firebase cli
run: npm install -g firebase-tools
- name: deploy
run: firebase deploy --token ${{ secrets.TOKEN }}

En el job deploy bajamos el artifact, instalamos firebase cli y hacemos deploy.

main.yml

name: workflow with github actions
on:
push:
branches:
- main
- dev
- multiples-jobs
jobs:
install_and_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: "14"
cache: "npm"
- run: npm install
- run: npm test
build:
needs: [install_and_test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: "14"
cache: "npm"
- run: npm install
- run: npm run build
- run: rm -r node_modules
- name: artifact
uses: actions/upload-artifact@v2
with:
name: app
path: .
deploy:
needs: [build]
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v2
with:
node-version: "14"
- uses: actions/download-artifact@v2
with:
name: app
- name: install firebase cli
run: npm install -g firebase-tools
- name: deploy
run: firebase deploy --token ${{ secrets.TOKEN }}

Conditioned Jobs And Environments

Environments

la idea es cambiar el valor de nuestro secrets TOKEN dependiendo si queremos hacer deploy a dev o prod, para esto vamos a la configuración de nuestro repositorio en github y entramos en environments,.

Creamos un nuevo environment de nombre DEV y otro de nombre PROD, podemos agregarle una regla que indique que solo ciertas branches tengan acceso al enviroment, añadimos nuestro secret TOKEN (importante conservar el mismo nombre).

Hacemos el mismo proceso para PROD

listo, tenemos nuestros environments configurados, ahora hagamos los cambios en el main.yml

lo primero es agregar dos jobs que dependan de build, tengan como condicional su rama de referencia y su environment seleccionado

deploy_dev

deploy_dev:
if: ${{ github.ref == 'refs/heads/dev' }}
environment: DEV
needs: [build]
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v2
with:
node-version: "14"
- uses: actions/download-artifact@v2
with:
name: app
- name: install firebase cli
run: npm install -g firebase-tools
- name: deploy
run: echo "deploy to dev"

Para el ejemplo no tengo donde hacer deploy para dev por lo que solo imprimo un mensaje.

deploy_prod

deploy_prod:
if: ${{ github.ref == 'refs/heads/main' }}
environment: PROD
needs: [build]
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v2
with:
node-version: "14"
- uses: actions/download-artifact@v2
with:
name: app
- name: install firebase cli
run: npm install -g firebase-tools
- name: deploy
run: firebase deploy --token ${{ secrets.TOKEN }}

listo, esto en Github Actions se observa la siguiente forma

main.yml

name: workflow with github actions
on:
push:
branches:
- main
- dev
jobs:
install_and_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: "14"
cache: "npm"
- run: npm install
- run: npm test
build:
needs: [install_and_test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: "14"
cache: "npm"
- run: npm install
- run: npm run build
- run: rm -r node_modules
- name: artifact
uses: actions/upload-artifact@v2
with:
name: app
path: .
deploy_dev:
if: ${{ github.ref == 'refs/heads/dev' }}
environment: DEV
needs: [build]
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v2
with:
node-version: "14"
- uses: actions/download-artifact@v2
with:
name: app
- name: install firebase cli
run: npm install -g firebase-tools
- name: deploy
run: echo "deploy to dev"
deploy_prod:
if: ${{ github.ref == 'refs/heads/main' }}
environment: PROD
needs: [build]
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v2
with:
node-version: "14"
- uses: actions/download-artifact@v2
with:
name: app
- name: install firebase cli
run: npm install -g firebase-tools
- name: deploy
run: firebase deploy --token ${{ secrets.TOKEN }}

Si usas vscode te recomiendo la extensión Github Actions, te permite ver las acciones, los secrets y environments desde el editor.

--

--

Hernan Castilla
Hernan Castilla

Written by Hernan Castilla

” Le vent se lève!… Il faut tenter de vivre!”

No responses yet