Saltar al contenido
Volver al blog
DevOpsHomelabAutomatización

Actualiza tus runners autoalojados antes de que Laravel se quede sin CI

GitHub ya bloquea runners antiguos en Enterprise Cloud y puedes detectar versiones en riesgo desde la API.

Ismael Catala5 min de lectura

El problema no estará en Laravel

Desde el 29 de septiembre de 2026, GitHub Enterprise Cloud aplica requisitos mínimos de versión para los runners autoalojados de GitHub Actions. Si uno de mis runners queda por debajo del mínimo exigido para ejecutar trabajos, los workflows pueden quedarse esperando aunque el código de Laravel, la configuración de Composer y los tests estén bien. Es un fallo incómodo porque se parece a un problema de capacidad o de etiquetas, cuando en realidad el runner ya no puede aceptar el trabajo. También afecta a los runners que ya estaban registrados antes de la fecha de aplicación.

GitHub distingue entre poder registrar un runner y poder ejecutar jobs con él. Las versiones inferiores a 2.329.0 ya no pueden registrarse ni volver a registrarse en GitHub Enterprise Cloud. Para la ejecución de jobs hay otro mínimo, superior al de registro, y GitHub no publica ese número concreto en el aviso. Por eso no conviene reducir esta revisión a comparar toda la flota con una única versión fija.

Empiezo por localizar las versiones reales

En un homelab es fácil tener un runner en una VM, otro dentro de un contenedor y alguno olvidado en una máquina dedicada. La interfaz de GitHub ayuda a mirar casos sueltos, pero para mantener una flota prefiero recoger el inventario por API. El endpoint de listado devuelve, entre otros datos, la versión instalada de cada runner. A partir de ahí puedo consultar el calendario de retirada para cada versión encontrada.

Este script pagina los runners de una organización, elimina versiones repetidas y consulta sus fechas de fin de soporte. Necesita un token con permiso de lectura sobre los runners autoalojados de la organización y acceso de administrador a esa organización. Guardo el token fuera del script, por ejemplo como variable de entorno o secreto del sistema que ejecute la comprobación. El resultado es JSON por versión, así que se puede entregar a un sistema de alertas sin tener que raspar una web.

#!/usr/bin/env bash
set -euo pipefail
 
: "${GITHUB_TOKEN:?Falta GITHUB_TOKEN}"
: "${GITHUB_ORG:?Falta GITHUB_ORG}"
 
api="https://api.github.com"
headers=(
  -H "Accept: application/vnd.github+json"
  -H "Authorization: Bearer ${GITHUB_TOKEN}"
  -H "X-GitHub-Api-Version: 2026-03-10"
)
 
page=1
 
while :; do
  response="$(
    curl -fsSL "${headers[@]}" \
      "${api}/orgs/${GITHUB_ORG}/actions/runners?per_page=100&page=${page}"
  )"
 
  count="$(jq '.runners | length' <<< "${response}")"
  jq -r '.runners[].version' <<< "${response}"
 
  if [ "${count}" -lt 100 ]; then
    break
  fi
 
  page=$((page + 1))
done |
sort -u |
while read -r version; do
  schedule="$(
    curl -fsSL "${headers[@]}" \
      "${api}/orgs/${GITHUB_ORG}/actions/runners/deprecations/${version}"
  )"
 
  jq -cn \
    --arg version "${version}" \
    --argjson schedule "${schedule}" \
    '{
      version: $version,
      registration_deprecates_at: $schedule.registration_deprecates_at,
      runtime_deprecates_at: $schedule.runtime_deprecates_at
    }'
done

La alerta debe mirar las dos fechas

El endpoint de deprecaciones recibe una versión concreta en la ruta: GET /orgs/{org}/actions/runners/deprecations/{version}. La respuesta identifica la versión y puede incluir registration_deprecates_at y runtime_deprecates_at. Para los runners que ya están funcionando, la fecha que más me interesa es la de ejecución, porque marca cuándo dejarán de recoger jobs. La fecha de registro importa especialmente al recrear una VM, sustituir un contenedor o volver a dar de alta un runner eliminado.

No esperaría al día de la retirada para avisar. Programaría esta comprobación cada día y trataría cualquier fecha próxima como una tarea de mantenimiento de la imagen o de la VM. Si todos mis runners usan una misma imagen de Docker o una plantilla de Proxmox, la corrección debería empezar ahí, no en cada instancia individual. Después actualizaría o recrearía los runners y comprobaría que vuelven a aparecer con la versión esperada en el inventario.

La letra pequeña que evita falsas expectativas

Esta medida afecta a GitHub Enterprise Cloud; no es un cambio aplicable a GitHub Enterprise Server. En GitHub Enterprise Cloud con Data Residency la aplicación ya había empezado el 31 de julio de 2026, así que no usaría el 29 de septiembre como fecha límite universal para todos los entornos. Además, la API consulta el calendario de una versión, pero no actualiza por sí sola el binario del runner ni reconstruye una imagen de contenedor. La alerta detecta deuda de mantenimiento; la actualización sigue siendo responsabilidad de quien opera la infraestructura.

Tampoco daría por hecho que las actualizaciones automáticas están activadas. GitHub indica que la aplicación del runner puede recibir actualizaciones automáticas, pero esa opción se puede deshabilitar y no cubre el sistema operativo ni el resto de herramientas instaladas. Un runner actualizado puede seguir fallando por una imagen rota, por permisos insuficientes, por Docker inaccesible o por etiquetas que no coinciden con el workflow. Antes de tocar producción, probaría la nueva imagen con un workflow de Laravel que ejecute al menos composer install, los tests y el paso de build que use el proyecto.

Convertirlo en una tarea de mantenimiento

Para mí, el punto útil de este cambio no es memorizar un número de versión, sino incorporar los runners al inventario normal del homelab. Si uso contenedores, fijo y reviso la imagen base; si uso VMs, documento de qué plantilla salen y cómo se actualizan. También separo los runners efímeros de los persistentes, porque los primeros se reemplazan con facilidad y los segundos acumulan más estado del que parece. Así, cuando GitHub retire una versión, la respuesta no será investigar por qué Laravel no recoge jobs, sino desplegar una imagen ya preparada.


Fuente: GitHub Changelog

Documentación oficial de la API REST para runners autoalojados