Tabla de Contenidos
¡Esta es una revisión vieja del documento!
7. GitHub Actions
Introducción
El despliegue continuo es desplegar las aplicaciones web lo más pronto posible: cada cambio que se sube al repositorio acaba en el servidor sin que nadie tenga que hacerlo a mano.
Para eso se usa un servidor de automatización: un programa que, cuando ocurre algo (un push a una rama, que alguien pulse un botón, una hora concreta), ejecuta solo una lista de pasos escrita de antemano. Los pasos son los que haríamos nosotros a mano:
- Descargar el código del repositorio.
- Compilarlo y pasar los tests.
- Construir la imagen Docker.
- Desplegar la nueva versión
Si un paso falla, se para ahí y avisa: lo que no compila o no pasa los tests no llega al servidor.
Existen muchas formasde hacerlo, antiguamente se hacía con una herramienta de software libre llamada Jenkins pero actualmente se usan las acciones de GitHub o GitLab , etc.
GitHub Actions es el sistema de automatización integrado en GitHub. Cada fichero YAML dentro de .github/workflows/ es un workflow, y en él se define:
- Cuándo se ejecuta: al hacer un push, cuando tú decidas o a una hora programada.
- Qué se ejecuta: las tareas (jobs), como compilar, pasar los tests o desplegar. Cada job se compone de pasos (steps), que pueden ser órdenes de shell o actions reutilizables hechas por otros.
- Dónde se ejecuta: en un runner, el programa que ejecuta los jobs. Puede estar en una máquina virtual de GitHub o en una máquina tuya (Runners).
Mas información:
Workflows
Un workflow es un fichero YAML dentro de la carpeta .github/workflows/ del repositorio. GitHub lee esa carpeta en cada push: no hay que darlo de alta en ningún sitio. El fichero tiene cuatro partes:
on: cuándo se ejecuta.pushconbranchescuando se sube algo a esa rama;workflow_dispatchañade un botón Run workflow en la pestaña Actions para lanzarlo a mano.jobs: los trabajos que hay que hacer.runs-on: el runner en el que se ejecuta cada trabajo. Conubuntu-24.04, un Ubuntu que GitHub crea para la ocasión y tira al acabar; conself-hosted, un runner propio (Runners). Siempre con la versión puesta, nuncaubuntu-latest: cuando GitHub cambia la versión a la que apunta, los scripts que funcionaban pueden dejar de funcionar sin haber tocado nada.steps: los pasos de cada trabajo, en orden. Cada paso tiene unnamey hace una de dos cosas:run: órdenes de shell, como en una terminal. Con|se ponen varias líneas.uses: una acción ya hecha por otros, comoactions/checkout@v7, que descarga el código del repositorio en el runner.
Lo que no debe estar en el repositorio (contraseñas, claves SSH, IPs) se guarda como secreto en Settings → Secrets and variables → Actions y se usa en el workflow con ${{ secrets.NOMBRE }}. GitHub lo oculta en los logs.
actions/checkout, y no tiene nada instalado aparte de lo que trae Ubuntu, así que lo que haga falta se instala en un paso.
Para compilar el proyecto Java y pasar sus tests cada vez que se sube algo a master, se añade al repositorio:
name: Compilar
on:
workflow_dispatch:
push:
branches:
- master
jobs:
compilar:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v7
- name: Instalar Java 21
uses: actions/setup-java@v6
with:
distribution: temurin
java-version: 21
- name: Compilar y pasar los tests
run: mvn -B package
actions/setup-java: el Ubuntu del runner no trae la versión de Java del proyecto; esta acción la instala.mvn -B package: compila y pasa los tests. Si falla un test, el workflow sale en rojo.-Bes el modo no interactivo, sin colores ni barras de progreso en el log.
Cada ejecución sale en la pestaña Actions del repositorio, con cada paso en verde o en rojo y su log. Si un paso falla, los siguientes no se ejecutan.
Runners
Un runner es el programa que ejecuta los jobs de un workflow: GitHub le pasa los pasos y él los va ejecutando y le devuelve el log. Dónde está el runner lo elige runs-on, y hay dos tipos:
- Runner de GitHub (
runs-on: ubuntu-24.04): una máquina virtual que GitHub crea para cada job y tira al acabar. Es el del workflow de arriba. - Runner propio (
runs-on: self-hosted): el mismo programa, pero instalado por nosotros en un servidor nuestro. Se queda siempre en marcha esperando trabajo.
| Runner de GitHub | Runner propio | |
|---|---|---|
| Dónde se ejecutan los pasos | En una máquina de GitHub | En nuestro servidor |
| Hay que instalarlo y mantenerlo | ✓ | |
| Empieza vacío en cada ejecución | ✓ | |
| Ve la red del servidor | ✓ | |
| Para desplegar necesita VPN, SSH y sus secretos | ✓ |
Para compilar y pasar los tests, el runner de GitHub. Para desplegar en un servidor nuestro, un runner propio en ese servidor: los pasos se ejecutan allí mismo, así que el workflow se queda en lanzar deploy.sh.
Con el runner de GitHub
El runner está en Internet y el servidor en el instituto, así que para desplegar tendría que entrar por VPN y SSH, con las claves guardadas como secretos:
La clave privada SSH para entrar en el servidor (Proyecto 1) se guarda como secreto SSH_KEY, y el usuario y el servidor como SSH_USER y SSH_HOST. El workflow entra por SSH y ejecuta deploy.sh, que está en el home del usuario en el servidor:
name: Desplegar
on:
workflow_dispatch:
push:
branches:
- master
jobs:
desplegar:
runs-on: ubuntu-24.04
steps:
- name: Desplegar
run: |
echo "${{ secrets.SSH_KEY }}" > clave
chmod 600 clave
ssh -i clave -o StrictHostKeyChecking=accept-new ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "~/deploy.sh"
echoychmod:sshlee la clave de un fichero, así que se escribe el secreto en uno.StrictHostKeyChecking=accept-new: el runner es nuevo y no conoce el servidor. Sin esto,sshpregunta si se fía de él y el workflow se queda parado esperando la respuesta."~/deploy.sh": la orden que se le pasa asshdetrás del servidor se ejecuta en el servidor, no en el runner. Va entre comillas para que~sea el home del servidor y no el del runner.
Solo funciona si el servidor acepta SSH desde Internet. Si está detrás del router del instituto o de la empresa, antes hay que conectar la VPN en otro paso, con más secretos.
Con un runner propio
El runner está dentro del servidor. Es él quien pregunta a GitHub si hay trabajo, por HTTPS, como un navegador: no hace falta abrir ningún puerto ni VPN, y funciona aunque el servidor esté detrás del router del instituto.
Instalar un runner propio en Linux
Un runner se registra en un repositorio y solo ejecuta sus workflows. Se instala en el servidor con el usuario que va a desplegar, no con root:
- En el repositorio, Settings → Actions → Runners → New self-hosted runner, con Linux y x64. GitHub muestra las órdenes de los pasos siguientes con el token ya puesto. El token caduca en una hora.
- Descargarlo:
mkdir actions-runner && cd actions-runner curl -O -L https://github.com/actions/runner/releases/download/v2.338.2/actions-runner-linux-x64-2.338.2.tar.gz tar xzf ./actions-runner-linux-x64-2.338.2.tar.gz
- Registrarlo en el repositorio. Pregunta el grupo, el nombre y las etiquetas: con Enter se queda lo que propone.
./config.sh --url https://github.com/lgonzalezmislata/Facturas --token AXQKZ7MBV3LN2RCYEUHJ4PDTD6Y2W
- Dejarlo como servicio, para que siga en marcha al cerrar la sesión SSH y arranque solo al reiniciar el servidor:
sudo ./svc.sh install sudo ./svc.sh start sudo ./svc.sh status
- En Settings → Actions → Runners tiene que salir como Idle.
Configurar un workflow para usar un runner
El workflow es el mismo que con el runner de GitHub, pero sin SSH: el runner ya está en el servidor y ejecuta deploy.sh allí mismo.
name: Desplegar
on:
workflow_dispatch:
push:
branches:
- master
jobs:
desplegar:
runs-on: self-hosted
steps:
- name: Desplegar
run: ~/deploy.sh
Lo que hace que el job se ejecute en nuestro servidor es runs-on: self-hosted. Los pasos se ejecutan con el usuario que instaló el runner
Más información:
- About self-hosted runners: qué son y requisitos.
- Configure the self-hosted runner application:
svc.shen Linux.
Ejercicios
Ejercicio 1
Añade a tu repositorio de Java el workflow compilar.yml. Comprueba en Actions que sale en verde; luego haz fallar un test, súbelo y comprueba que sale en rojo y en qué paso.
Ejercicio 2
- Instala un runner propio para tu repositorio de Java en tu servidor como en Instalar un runner propio en Linux, como servicio, y comprueba que sale Idle.
- Añade el workflow
desplegar.ymladaptado a tu proyecto. Se ejecutará manualmente y cuando haya un cambio enmaster. Sube un cambio y comprueba que llega desplegado al servidor.


