Solución rápida de compilaciones fallidas usando la CLI de Jenkins

Usa la CLI de Jenkins para inspeccionar compilaciones fallidas, transmitir registros, verificar parámetros y reejecutar trabajos sin navegar por la interfaz de usuario.

Solución rápida de compilaciones fallidas usando la CLI de Jenkins

La interfaz web de Jenkins es útil cuando estás explorando. La CLI de Jenkins es mejor cuando ya conoces el nombre del trabajo, necesitas el registro ahora o quieres repetir las mismas comprobaciones sin hacer clic en páginas.

Una compilación fallida generalmente necesita tres piezas de información: qué se ejecutó, dónde falló y qué cambió desde la última ejecución exitosa. La CLI puede obtener las tres rápidamente si la configuras una vez.

Configurar un comando CLI repetible

Descarga el archivo JAR de la CLI desde tu propio controlador de Jenkins:

curl -O "$JENKINS_URL/jnlpJars/jenkins-cli.jar"

Usa un token de API, no tu contraseña de cuenta:

export JENKINS_URL="https://jenkins.example.com"
export JENKINS_USER="tu-usuario"
export JENKINS_API_TOKEN="tu-token-api"

alias jcli='java -jar jenkins-cli.jar -s "$JENKINS_URL" -auth "$JENKINS_USER:$JENKINS_API_TOKEN"'

Prueba la autenticación antes de solucionar un fallo real:

jcli who-am-i
jcli help

Si esto falla, primero corrige el acceso a la CLI. Las causas comunes son una URL incorrecta, un token copiado con un espacio extra, permisos faltantes o una configuración de seguridad de Jenkins que deshabilita el transporte de CLI que intentas usar.

Para scripts compartidos, evita los alias de shell. Envuelve el comando en un script pequeño o usa variables de entorno en tu almacén de secretos de CI para que los tokens no terminen en el historial del shell.

Encontrar la compilación fallida

Si conoces el nombre del trabajo y el número de compilación, ve directamente al registro de la consola. Si solo sabes que algo falló recientemente, comienza con Groovy a través de la CLI:

jcli groovy = <<'EOF'
Jenkins.instance.getAllItems(hudson.model.Job.class).each { job ->
  def b = job.getLastBuild()
  if (b != null && b.result == hudson.model.Result.FAILURE) {
    println "${job.fullName} #${b.number} ${b.getTime()}"
  }
}
EOF

Para carpetas y pipelines multirrama, usa el nombre completo del trabajo exactamente como lo conoce Jenkins. Un trabajo de rama podría verse así:

team-service/main
team-service/PR-42
folder-a/folder-b/deploy-prod

Si un nombre contiene espacios, cítalo en tu shell:

jcli console "Carpeta Con Espacios/Mi Pipeline" 128

Obtener el registro de la consola primero

El registro de la consola sigue siendo la fuente de verdad más rápida para la mayoría de los fallos:

jcli console MiTrabajoPipeline 123

Para registros largos, guarda una copia y busca con contexto:

jcli console MiTrabajoPipeline 123 > build-123.log
grep -niE "error|failed|exception|traceback|permission denied|timeout" build-123.log | head -40
grep -niC 3 "permission denied" build-123.log

No te bases solo en la primera línea que contenga "error". Las herramientas de compilación a menudo imprimen advertencias, nombres de pruebas o texto de fallo esperado. Busca el primer fallo significativo después de que comience la etapa, luego lee las líneas anteriores. La causa suele estar por encima del seguimiento de la pila.

Para una compilación en ejecución, sigue el registro:

jcli console MiTrabajoPipeline 123 -f

Algunas versiones de Jenkins y modos de CLI aceptan --follow; otros usan -f. Verifica jcli help console en tu controlador.

Identificar la etapa que falló

Los registros de pipeline incluyen marcadores de etapa. Búscalos cerca del fallo:

grep -n "\[Pipeline\] stage" build-123.log

Luego inspecciona la sección después del último marcador de etapa antes del error. Si el registro es ruidoso, ábrelo con less:

less build-123.log

Dentro de less, busca /ERROR, /Exception o /[Pipeline] stage.

Un buen Jenkinsfile facilita esto imprimiendo nombres de paso claros antes de operaciones riesgosas:

echo 'Instalando dependencias npm'
sh 'npm ci'
echo 'Ejecutando pruebas unitarias'
sh 'npm test'

Si cada paso es solo sh './ci.sh', la CLI aún puede obtener el registro, pero el registro puede no decirte lo suficiente. En ese caso, mejora el pipeline después del incidente.

Verificar parámetros y causas

Una compilación puede fallar porque se ejecutó con la rama incorrecta, el entorno incorrecto o un parámetro desactualizado. Obtén los metadatos de la compilación con Groovy:

jcli groovy = <<'EOF'
def job = Jenkins.instance.getItemByFullName('MiTrabajoPipeline')
def build = job?.getBuildByNumber(123)
if (build == null) {
  println 'Compilación no encontrada'
  return
}
println "Trabajo: ${job.fullName}"
println "Compilación: #${build.number}"
println "Resultado: ${build.result}"
println "Duración: ${build.durationString}"
println 'Causas:'
build.getCauses().each { println "- ${it.shortDescription}" }
println 'Parámetros:'
build.getAction(hudson.model.ParametersAction)?.parameters?.each {
  println "- ${it.name}=${it.value}"
}
EOF

Esto es especialmente útil para trabajos de despliegue. Un despliegue de producción fallido con BRANCH=feature/test es un problema muy diferente a un despliegue fallido de la etiqueta de lanzamiento esperada.

Ten cuidado al imprimir variables de entorno. Pueden incluir secretos. Si necesitas detalles del entorno, imprime claves seguras específicas en lugar de volcar todo:

jcli groovy = <<'EOF'
def job = Jenkins.instance.getItemByFullName('MiTrabajoPipeline')
def build = job?.getBuildByNumber(123)
def env = build?.getEnvironment(TaskListener.NULL)
['JOB_NAME', 'BUILD_NUMBER', 'BRANCH_NAME', 'GIT_COMMIT', 'NODE_NAME'].each { key ->
  println "${key}=${env?.get(key)}"
}
EOF

Si tu script carece de permisos o un plugin cambia los metadatos disponibles, recurre al registro de la consola y la configuración del trabajo.

Comparar con la última compilación exitosa

Un solo registro fallido es útil. Un registro fallido junto al último registro exitoso es mejor.

Encuentra el número de la última compilación exitosa:

jcli groovy = <<'EOF'
def job = Jenkins.instance.getItemByFullName('MiTrabajoPipeline')
def b = job?.getLastSuccessfulBuild()
println b == null ? 'No se encontró compilación exitosa' : b.number
EOF

Luego obtén ambos registros:

jcli console MiTrabajoPipeline 122 > build-122-exitoso.log
jcli console MiTrabajoPipeline 123 > build-123-fallido.log

Compara los comandos, versiones de dependencias, etiquetas de agente, ramas y SHAs de checkout. Muchos fallos provienen de una imagen base cambiada, una dependencia movida, un agente diferente o una credencial que expiró entre compilaciones.

Para pipelines basados en Git, estos valores suelen ser suficientes para empezar:

grep -nE "Checking out|GIT_COMMIT|BRANCH_NAME|git rev-parse|Docker|image:" build-123-fallido.log

Reejecutar una compilación con cuidado

Una vez que entiendas el fallo o hayas aplicado una corrección, desencadena una nueva compilación:

jcli build MiTrabajoPipeline

Para trabajos parametrizados:

jcli build MiTrabajoPipeline -p BRANCH=main -p ENVIRONMENT=staging

Para esperar y transmitir la salida, verifica las opciones compatibles de tu controlador:

jcli help build

Las opciones comunes incluyen esperar la finalización e imprimir la salida de la consola, pero los nombres pueden variar según la versión de Jenkins y los plugins.

No reejecutes trabajos de despliegue de producción solo para ver qué sucede. Confirma primero los parámetros, credenciales y entorno de destino. Si el trabajo no es idempotente, una reejecución puede empeorar el incidente.

Usar la salida de la CLI en notas de incidentes

La CLI es buena para dejar un rastro. Guarda el registro exacto y los metadatos que usaste:

mkdir -p incidente-jenkins-123
jcli console MiTrabajoPipeline 123 > incidente-jenkins-123/consola.log
jcli get-job MiTrabajoPipeline > incidente-jenkins-123/configuracion-trabajo.xml

Trata configuracion-trabajo.xml como sensible si contiene referencias a credenciales, URLs o nombres internos. No lo pegues en tickets públicos.

Una nota de incidente compacta podría incluir:

Trabajo: MiTrabajoPipeline #123
Etapa fallida: Pruebas unitarias
Primer comando fallido: npm test
Commit: abc1234
Agente: linux-build-07
Causa probable: la instalación de dependencias usó Node 22 en lugar del Node 20 esperado
Acción: versión de herramienta fijada y reejecutada #124 exitosamente

Eso es mucho más útil que "Jenkins falló".

Un flujo práctico de solución de problemas

Usa este orden cuando una compilación falle y necesites señal rápidamente:

jcli who-am-i
jcli console MiTrabajoPipeline 123 > build-123.log
grep -niE "error|failed|exception|permission denied|timeout" build-123.log | head -40
grep -n "\[Pipeline\] stage" build-123.log

Luego inspecciona parámetros y causas con Groovy, compara con la última compilación exitosa y reejecuta solo después de saber si el fallo fue de código, infraestructura, credenciales o parámetros de entrada.

La CLI de Jenkins no diagnosticará mágicamente cada compilación fallida. Lo que hace bien es eliminar la fricción. Obtiene el registro, los metadatos y el comando de reejecución en tu terminal rápidamente, donde puedes buscar, comparar, guardar y repetir las mismas comprobaciones la próxima vez que un pipeline se rompa.