Creando parametros dinamicos en Jenkins con librerias groovy

Jenkins nos permite agregar librerias personalizadas con groovy y con ellas podemos crear pipelines que usan parametros dinamicos, en ese post veremos algunos de los casos de uso que me ha tocado trabajar.

Creando parametros dinamicos en Jenkins con librerias groovy

This post is also available in: English

En Jenkins, unos parámetros bien diseñados pueden simplificar incluso las implementaciones más complejas. En este artículo veremos cómo construir parámetros dinámicos con una librería compartida de Jenkins, cómo consultar ramas de GitHub y cómo relacionar unos parámetros con otros. Los ejemplos utilizan un Jenkinsfile declarativo, pero también pueden adaptarse a pipelines scripted.

Antes de empezar, necesitas:

  • Un Jenkins con permisos para configurar el job y ejecutar pipelines.

  • El plugin Pipeline: Groovy Libraries para cargar librerías compartidas.

  • El plugin Active Choices si vas a utilizar parámetros reactivos como CascadeChoiceParameter.

  • Credenciales almacenadas en Jenkins para acceder a repositorios privados.

  • Un repositorio Git con la estructura esperada por la librería compartida.

Cómo importar una librería dinámica en tu pipeline

En una ocasión, tuve que crear un repositorio personal para desarrollar librerías de Groovy, ya que no tenía acceso ni a la configuración de Jenkins ni al repositorio que contenía las librerías originales. Por eso, utilicé este script.

Una librería compartida puede organizarse, por ejemplo, de esta manera:

jenkins_poc/
├── vars/
│ └── testName.groovy
├── src/
│ └── com/ejemplo/jenkins/
└── resources/

Los archivos colocados en vars/ exponen pasos globales del pipeline. Para proyectos más grandes, la lógica reutilizable debería vivir en src/, dejando en vars/ únicamente una interfaz sencilla para los Jenkinsfiles.

En producción es preferible fijar una etiqueta o una versión concreta de la librería en lugar de utilizar siempre master o main. De esta forma, un cambio en la librería no modifica accidentalmente todos los pipelines.

library identifier: "jenkins_poc@main", retriever: modernSCM([
$class: 'GitSCMSource',
remote: "https://github.com/${user}/jenkins_poc.git",
credentialsId: credentialsId
])

Una vez que hemos resuelto el tema de la librería, es hora de ponerla en acción en tu pipeline. Puedes invocar sus funciones de manera sencilla y práctica. Esto te permitirá aprovechar al máximo las capacidades de la librería para optimizar tus procesos.

properties([
parameters([
choice (
name: 'name',
choices: [testName("Dynamic parameter")],
description: 'name'
),
])
])

En este ejemplo, testName devuelve una opción para el desplegable. Si la función devuelve varias líneas, Jenkins las interpreta como varias opciones del parámetro:

// vars/environmentOptions.groovy
def call() {
return ['dev', 'stag', 'prod']
}

Y el parámetro puede consumirlas así:

properties([
parameters([
choice(
name: 'ENVIRONMENT',
choices: environmentOptions(),
description: 'Selecciona el entorno de destino'
)
])
])

Conviene utilizar nombres de parámetros descriptivos y constantes, como ENVIRONMENT o RELEASE_BUILD, para que el pipeline sea fácil de leer y mantener.

En este caso la función es muy simple.

# vars/testName.groovy
def call(String name) {
return name
}

Y así se vería nuestro nuevo parámetro dinámico

Listar las ramas de un repositorio en GitHub

Si requieres que las ramas de un proyecto vengan directamente del repositorio de GitHub, puedes integrar este código.

import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials;
import jenkins.model.Jenkins;
def credentials = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
com.cloudbees.plugins.credentials.Credentials.class,
Jenkins.instance,
null,
null
);
def user = credentials.findResult { it.id == credentials_id ? it : null }
try{
def gettags = ("git ls-remote -t -h https://${user.username}:${user.password}@github.com/${user}/${project}.git").execute()
def branchesNoDefault = gettags.text.readLines().collect {
it.split()[1].replaceAll('refs/heads/', '').replaceAll('refs/tags/', '').replaceAll("\\\\^\\\\{\\\\}", '')
}
branches = branchesNoDefault.collect {
if (it == defaultBranch){
return "${defaultBranch}:selected"
}else {
return it
}
}
return branches
} catch(all) {
return [all.getMessage()]
}

Este enfoque es útil, pero tiene dos aspectos importantes. Primero, el comando git ls-remote debe ejecutarse con una credencial segura y no con las credenciales interpoladas directamente en una URL, porque podrían terminar expuestas en logs o en la lista de procesos. Segundo, el usuario que ejecuta el pipeline necesita permisos para leer las credenciales y para acceder al repositorio.

Siempre que sea posible, utiliza el plugin de Git y withCredentials o una credencial SSH gestionada por Jenkins. También valida los nombres de repositorio y las ramas recibidas antes de utilizarlos en comandos posteriores. Si el repositorio contiene muchas ramas, considera devolver únicamente las ramas permitidas para evitar que el formulario sea lento.

Usar el último número de compilación exitoso de otro pipeline

Si tus builds de Docker están en un pipeline diferente, puedes usar el parámetro RunParameterDefinition y agregarlo a tu pipeline con este código.

properties([
parameters([
choice (
name: 'name',
choices: [testName("Dynamic parameter")],
description: 'name'
),
[
$class: 'RunParameterDefinition',
filter: 'SUCCESSFUL',
name: 'RELEASE_BUILD',
projectName: build_job
]
])
])

Así se vería nuestro pipeline

El parámetro RunParameterDefinition permite seleccionar una ejecución existente de otro job. Es especialmente útil cuando un pipeline de despliegue debe consumir un artefacto generado por un pipeline de compilación.

En el pipeline puedes obtener el número seleccionado y utilizarlo para descargar el artefacto correspondiente:

pipeline {
agent any
stages {
stage('Mostrar compilación seleccionada') {
steps {
echo "Compilación elegida: ${params.RELEASE_BUILD}"
}
}
}
}

La selección de una compilación exitosa es más segura que elegir únicamente el número más reciente: evita desplegar una ejecución fallida o incompleta. Aun así, conviene comprobar que el artefacto existe y que corresponde a la rama y al entorno de destino.

Lógica y dependencias de otros parámetros

También podemos agregar lógica que dependa de lo que sea seleccionado en otros parámetros; por ejemplo, si necesitas identificar qué entorno fue seleccionado y, basándote en ello, tener cierto comportamiento.

Primero debemos agregar el parámetro para seleccionar el entorno.

properties([
parameters([
choice (
name: 'name',
choices: [testName("Dynamic parameter")],
description: 'name'
),
[
$class: 'RunParameterDefinition',
filter: 'SUCCESSFUL',
name: 'RELEASE_BUILD',
projectName: build_job
],
[
$class: 'CascadeChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
description: 'Select the environment from the dropdown list',
filterLength: 1,
filterable: false,
name: 'environment',
script: [
$class: 'GroovyScript',
fallbackScript: [
classpath: [],
sandbox: false,
script:
"return['CloudCould not get the envs']"
],
script: [
classpath: [],
sandbox: false,
script:
'''return["dev", "stag", "prod"]'''
]
]
],
])
])

En un caso real, el segundo parámetro puede depender del entorno seleccionado. Por ejemplo, podemos mostrar cuentas o regiones distintas para cada entorno. Con Active Choices, el script reactivo recibe los valores de los parámetros de los que depende:

[
$class: 'CascadeChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
name: 'REGION',
referencedParameters: 'environment',
script: [
$class: 'GroovyScript',
fallbackScript: [
classpath: [],
sandbox: true,
script: "return ['No se pudieron cargar las regiones']"
],
script: [
classpath: [],
sandbox: true,
script: '''
if (environment == 'prod') {
return ['eu-west-1', 'us-east-1']
}
return ['eu-west-1']
'''
]
]
]

referencedParameters es la parte que establece la dependencia. Cada vez que el usuario cambia environment, Jenkins vuelve a evaluar el script de REGION.

Ejemplo completo de uso en un stage

Después de definir los parámetros, el pipeline puede utilizarlos para seleccionar el comportamiento de cada ejecución:

pipeline {
agent any
stages {
stage('Validar parámetros') {
steps {
script {
if (params.ENVIRONMENT == 'prod' && !params.RELEASE_BUILD) {
error('La producción requiere una compilación seleccionada')
}
}
}
}
stage('Desplegar') {
steps {
echo "Desplegando ${params.RELEASE_BUILD} en ${params.ENVIRONMENT}"
}
}
}
}

La validación dentro del pipeline sigue siendo necesaria aunque el formulario limite las opciones. Los parámetros pueden llegar vacíos, modificarse desde una llamada API o proceder de un job automatizado.

Buenas prácticas y problemas habituales

  • Evita secretos en el código: guarda tokens, contraseñas y claves SSH en Manage Jenkins → Credentials.

  • Limita el sandbox desactivado: los scripts fuera del sandbox requieren aprobación administrativa. Actívalo siempre que sea posible.

  • Controla el tiempo de respuesta: no hagas varias llamadas de red cada vez que se abre el formulario. Usa caché o una lista limitada de opciones.

  • Valida los valores en el pipeline: un parámetro dinámico mejora la experiencia, pero no sustituye las comprobaciones de seguridad.

  • Fija las versiones: utiliza tags o commits para las librerías compartidas y los plugins críticos.

  • Registra errores útiles: devuelve mensajes comprensibles cuando GitHub no esté disponible o la credencial no tenga permisos.

Si un parámetro no aparece, revisa que el job se haya ejecutado al menos una vez y que el plugin requerido esté instalado. Si aparece vacío, comprueba el resultado del script, los permisos de la credencial y los logs de Jenkins. Para parámetros reactivos, verifica también que referencedParameters coincida exactamente con el nombre del parámetro del que dependen.

En resumen, los pipelines dinámicos en Jenkins con Groovy son una herramienta poderosa que puede revolucionar tus implementaciones. Al comprender la importancia de los parámetros y cómo pueden influir en la eficiencia de tus pipelines, estás en camino de lograr implementaciones más sencillas y efectivas.

Share this article

Keep reading

Related articles

AWS

Novedades de AWS, Azure, GCP y OCI — 15 al 20 de septiembre de 2026

Descubre las novedades de AWS, Azure, Google Cloud y OCI del 15 al 20 de septiembre de 2026: Kubernetes, bases de datos, observabilidad, seguridad y networking.

DevOps

Kubernetes Troubleshooting: Health Checks, Readiness, Liveness y Startup Probes

Aprende a solucionar problemas con readiness, liveness y startup probes en Kubernetes, incluyendo timeouts, restart loops, health checks y cascading failures.

DevOps

Kubernetes Troubleshooting: Networking, Services, DNS, NetworkPolicy, Ingress y CNI

Aprende a solucionar problemas de networking en Kubernetes siguiendo el tráfico desde Pods y Services hasta EndpointSlices, DNS, NetworkPolicy, Ingress, Gateway API y CNI.

Comments