Capítulo 31 de 33 9 secciones 6 min

Que GitHub trabaje mientras duermes

Actions explicado sin jerga: qué es, para qué sirve y cuándo no vale la pena

<strong>Actions ejecuta comandos en una computadora de GitHub cuando pasa algo en tu repositorio.</strong> Se configura con un archivo en <code>.github/workflows/</code> que dice cuándo dispararse (un push, un pull request, una hora del día) y qué comandos correr. Sirve para revisar que lo que entra no rompa nada, para publicar solo y para tareas que se repiten. Las claves nunca van dentro del archivo: van en los secrets del repositorio.

Este es el último ladrillo, y es el que convierte un repositorio en algo que trabaja solo. La idea en una frase: cuando pase esto, corre esto ⚙️

Para qué sirve de verdad

  • Revisar que lo que alguien propone no rompa nada, antes de aceptarlo.
  • Publicar la web sola cada vez que subes, como en 19.
  • Tareas de calendario: un reporte todos los lunes a las siete.
  • Comprobaciones aburridas que nadie se acuerda de hacer, como que ningún CSV llegue con la ciudad vacía.

Y para qué no: si tu proyecto es una carpeta con dos scripts que corres tú una vez al mes, montar Actions es trabajo que no se paga 🙃

El archivo

Vive en una ruta exacta, .github/workflows/, y termina en .yml. Vamos a escribir uno que revise el CSV de ventas en cada push:

mkdir reporte-ventas
cd reporte-ventas
git init -q
printf 'ciudad,monto\nLima,1200\nArequipa,890\n' > ventas.csv
mkdir -p .github/workflows
cat > .github/workflows/revisa.yml <<'FIN'
name: Revisa el CSV de ventas

on:
  push:
  pull_request:

jobs:
  revisar:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Ningun monto vacio
        run: |
          tail -n +2 ventas.csv | cut -d, -f2 | grep -q '^$' && exit 1
          echo "CSV correcto"
FIN
git add .
git commit -q -m "Se revisa el CSV de ventas en cada push"
git ls-files
.github/workflows/revisa.yml
ventas.csv

Léelo de arriba abajo y se entiende sin saber nada: se llama así, se dispara con un push o un pull request, corre en una máquina Linux, se baja tu código y ejecuta esos comandos 📖

Probar la revisión aquí antes de subirla

Lo que corre allá son comandos normales, así que se pueden probar en tu máquina primero. Es lo que yo hago siempre, porque esperar a que GitHub falle para descubrir un error de dedo es lentísimo:

tail -n +2 ventas.csv | cut -d, -f2 | grep -q '^$' && exit 1
echo "CSV correcto"
CSV correcto
printf 'Cusco,\n' >> ventas.csv
tail -n +2 ventas.csv | cut -d, -f2 | grep -q '^$'
echo "encontro una fila vacia, la revision fallaria"
encontro una fila vacia, la revision fallaria

Con eso ya sabes que la revisión detecta lo que tiene que detectar, y recién ahí la subes 🔍

git checkout -q ventas.csv
cat ventas.csv
ciudad,monto
Lima,1200
Arequipa,890

Cuándo se dispara

EscribesSe ejecuta
on: pushCada vez que subes
on: pull_requestCuando alguien propone un cambio
on: schedule con un cronA una hora fija
on: workflow_dispatchCuando le das a un botón

El de pull_request es el que más cambia la vida de un equipo: la revisión automática corre sobre la propuesta y quien revisa ya sabe si funciona antes de leer una línea, que es justo lo que le faltaba a la trampa de 23 ✅

Las claves no van dentro

Si tu automatización necesita una clave, va en Settings > Secrets and variables > Actions, y en el archivo se usa por su nombre:

      - name: Manda el reporte
        env:
          TOKEN: ${{ secrets.TOKEN_DEL_REPORTE }}
        run: python3 manda_reporte.py

Ese archivo se puede subir tranquilamente: no lleva el valor, lleva el nombre. Y GitHub tapa el valor en los registros si por accidente se imprime 🔐

Cuánto cuesta

En repositorios públicos, Actions es gratis. En privados hay minutos incluidos al mes y después se paga, así que conviene mirar el consumo antes de poner algo a correr cada cinco minutos ⏱️

La trampa

Montas una automatización que sube el reporte a un servicio y pegas la clave dentro del archivo de configuración, que total es tu repositorio.

name: Reporte diario
on:
  schedule:
    - cron: '0 12 * * *'
jobs:
  reporte:
    runs-on: ubuntu-latest
    steps:
      - run: curl -H "Authorization: Bearer sk-abc123..." ...
Qué está mal

Esa clave está en el repositorio y en cada registro de ejecución 🔓

Los archivos de Actions son archivos normales del proyecto: se ven, se clonan y se indexan igual que el README. Y además, todo lo que el paso imprima queda guardado en el registro de la ejecución, que en un repositorio público lee cualquiera.

Para esto existen los secrets: se guardan en Settings > Secrets and variables y se usan por su nombre, nunca por su valor. GitHub además los tapa en los registros.

Y si ya pasó, el orden es el de 28: rotar primero, limpiar después.

Comprueba que se entendió

Comprueba que lo tienes

Tu automatización necesita la clave de un servicio. ¿Dónde la pones?

  • En los secrets del repositorio, y la uso por su nombre
  • Dentro del archivo .yml
  • En un archivo aparte que agrego al .gitignore
  • La escribo cada vez que ejecuto

Ejercicios

1. Escribe tu primera automatización

Una revisión que comprueba que el catálogo no tenga ciudades vacías.

cd ..
mkdir catalogo
cd catalogo
git init -q
printf 'bodega,ciudad\nBodega Inti,Cusco\n' > bodegas.csv
mkdir -p .github/workflows
cat > .github/workflows/revisa.yml <<'FIN'
name: Revisa el catalogo

on:
  push:
  pull_request:

jobs:
  revisar:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: |
          tail -n +2 bodegas.csv | cut -d, -f2 | grep -q '^$' && exit 1
          echo "catalogo correcto"
FIN
git add .
git commit -q -m "Se revisa el catalogo en cada push"
git ls-files
.github/workflows/revisa.yml
bodegas.csv

La ruta tiene que ser exactamente esa o GitHub no lo encuentra.

2. Prueba la revisión aquí

Los mismos comandos, en tu máquina.

tail -n +2 bodegas.csv | cut -d, -f2 | grep -q '^$' && exit 1
echo "catalogo correcto"
catalogo correcto

Pasa. Ahora hay que comprobar que también sabe fallar.

3. Comprueba que detecta el error

Mete una bodega sin ciudad.

printf 'Mayorista Norte,\n' >> bodegas.csv
tail -n +2 bodegas.csv | cut -d, -f2 | grep -q '^$'
echo "detectado, la revision fallaria"
detectado, la revision fallaria

Una revisión que nunca falla no está revisando nada 🔍

4. Devuelve el archivo a como estaba

Con lo del capítulo de deshacer.

git checkout -q bodegas.csv
cat bodegas.csv
git status --short
bodega,ciudad
Bodega Inti,Cusco

Limpio otra vez.

5. Agrega un disparo por calendario

Que además corra todos los lunes a las 12 UTC.

cat > .github/workflows/semanal.yml <<'FIN'
name: Reporte semanal

on:
  schedule:
    - cron: '0 12 * * 1'
  workflow_dispatch:

jobs:
  reporte:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: wc -l bodegas.csv
FIN
git add .github
git commit -q -m "Reporte semanal del catalogo"
git ls-files .github
.github/workflows/revisa.yml
.github/workflows/semanal.yml

El workflow_dispatch agrega además un botón para lanzarlo a mano.

6. Comprueba que no metiste claves

La revisión de siempre, ahora sobre los archivos de automatización.

grep -rn "TOKEN=\|API_KEY=\|password" .github || echo "limpio"
cat .github/workflows/semanal.yml | head -6
limpio
name: Reporte semanal

on:
  schedule:
    - cron: '0 12 * * 1'
  workflow_dispatch:

Limpio. Si eso devuelve algo, no se sube 🔐

7. Pide un archivo de workflow que no existe

Los nombres de esta carpeta son literales.

cat .github/workflows/despliegue.yml
cat: .github/workflows/despliegue.yml: No such file or directory

Si el archivo no está donde toca, para GitHub simplemente no existe 🕳️

Lo que te llevas

Cuando pase esto, corre esto. Prueba los comandos en tu máquina antes, y las claves siempre en los secrets.

Practica este capítulo 📓

Todo el código de arriba en un cuaderno que corre de principio a fin, y los ejercicios con una celda vacía para que los hagas tú. Se abre en Google Colab y no hay que instalar nada.

¿Tienes alguna duda o consulta?