Rellene dinámicamente el parámetro de elección de Jenkins con ramas de Git en un repositorio específico

Tengo un trabajo de Jenkins parametrizado que requiere la entrada de una rama de Git específica en un repositorio de Git específico. Actualmente este parámetro es un parámetro de cadena.

¿Hay alguna forma de hacer de este parámetro un parámetro de elección y llenar dinámicamente la lista desplegable con las ramas de Git? No quiero requerir que alguien mantenga este parámetro de elección configurando manualmente el menú desplegable cada vez que se crea una nueva rama.

preguntado el 03 de mayo de 12 a las 15:05

14 Respuestas

Intenté un par de respuestas mencionadas en este enlace, pero no pude encontrar la manera de informarle a Jenkins sobre la rama seleccionada por el usuario. Como mencioné en mi comentario anterior en el hilo anterior, había dejado el campo selector de rama vacío.

Pero, durante investigaciones posteriores, encontré otra forma de hacer lo mismo: https://wiki.jenkins-ci.org/display/JENKINS/Git+Parameter+Plugin ¡Descubrí que este método era mucho más simple y tenía menos cosas que configurar!

Esto es lo que configuré:

  1. Instalado el complemento de parámetros de git
  2. Verificó 'Esta compilación está parametrizada' y agregó un 'parámetro Git'
  3. Se agregaron los siguientes valores: Configuración del complemento de parámetros de Git en el trabajo

  4. Luego, en la sección git SCM del trabajo, agregué el mismo valor mencionado en la sección 'Nombre', como si fuera una variable de entorno. (Si lee atentamente la ayuda de este complemento de parámetros de git, se dará cuenta de esto) Selector de sucursales

Después de esto, simplemente ejecuté la compilación, elegí mi rama (Jenkins verifica esta rama antes de compilarla) y completó la compilación con éxito, Y elegí la rama que había especificado.

respondido 23 mar '15, 16:03

Limitaciones / errores conocidos: el complemento de parámetros de git no es compatible con la configuración de esclavos de Jenkins con repositorios de git desprotegidos solo en esclavos - AmokHuginnsson

Me emocioné mucho con esto, pero desafortunadamente está plagado de un error en el que no pasa las credenciales al servidor git. Entonces, si necesita credenciales (como para repositorios privados de github), esto no funcionará hasta que se aborde JENKINS-28597. - mike mensaje

Desafortunadamente, no puedo obtener el nombre de la sucursal sin 'origen/'. ${BRANCH_SELECTOR##*/} no funciona cuando se inyectan variables. - Igor

@AmokHuginnsson se corrigió y se lanzó a principios de julio en issues.jenkins-ci.org/browse/JENKINS-16290 - Montss

Funciona de maravilla - yasir ali

Complemento de parámetro de elección extendida le permitirá leer las opciones de un archivo.

Por supuesto, ahora tiene otro problema: cómo asegurarse de que el archivo esté actualizado (eso se puede hacer con un enlace posterior a la confirmación) y se propague a todos los usuarios (eso se puede hacer colocándolo en un archivo compartido). servidor de archivos). Pero puede haber mejores soluciones.

contestado el 03 de mayo de 12 a las 16:05

Estamos usando el Complemento de parámetro de elección extensible con un guión maravilloso: return [" "].plus(["powershell","(git.exe ls-remote -h http://review/Project)-replace '\\w{40}\\trefs/heads/'"].execute().text.tokenize()). Es PowerShell ya que está en una máquina con Windows, pero puede sustituirlo por otra herramienta para el reemplazo de RegEx. Esto mantendrá la lista actualizada en cada carga sin necesidad de archivos externos. - Stoinov

@Stoinov Me gusta mucho tu solución. Tengo problemas para que esto funcione en un servidor Linux. - RocosoMontañaAlta

Tengo muy poca experiencia con Linux, pero debería poder usar cualquier comando de Linux que pueda reemplazar la lista devuelta de un comando de git. - Stoinov

gran fragmento, me falta la autenticación ssh para git en mi caso ... - vicente gerris

Gracias por compartir esta idea, me salvó el día. Modifiqué el código en mi canalización para configurar la rama predeterminada como maestra usando la opción 'CascadeChoiceParameter'. - elulcao

Pude lograr este resultado usando el Complemento de parámetros dinámicos de Jenkins. Usé la opción Parámetro de elección dinámica y, para el script de opciones, usé lo siguiente:

proc1 = ['/bin/bash', '-c', "/usr/bin/git ls-remote -h ssh://user@server.com/path/to/repo.git"].execute()
proc2 = ['/bin/bash', '-c', "awk '{print \$2}'"].execute()
proc3 = ['/bin/bash', '-c', "sed s%^refs/heads%origin%"].execute()

all = proc1 | proc2 | proc3
String result = all.text

String filename = "/tmp/branches.txt"
boolean success = new File(filename).write(result) 

def multiline = "cat /tmp/branches.txt".execute().text
def list = multiline.readLines()

Respondido el 02 de Septiembre de 14 a las 17:09

Como complemento, descubrí que ssh no siempre está disponible pero no es necesariamente necesario. Una alternativa sería usar algo como esto: proc1 = ['/bin/bash', '-c', "/usr/bin/git ls-remote -h user@server.com:path/to/repo.git"].execute() Esta es información especialmente útil cuando se trabaja con github. - verdad

Por alguna razón, la sucursal en la octava posición siempre se recoge. (Tengo alrededor de 8 sucursales). No importa cuál seleccione. ¿Alguna idea de si es necesario realizar más configuraciones en el trabajo de Jenkins? ¿O hay algún problema con el complemento? He mantenido el campo 'rama' vacío. - ravindra mijar

Parece que está describiendo un problema posterior, esto solo explica cómo llenar dinámicamente un parámetro con sus ramas de git. Para usar la rama en una compilación, normalmente nombro el parámetro "rama" y luego en "Administración de código fuente" (con Git seleccionado) uso "${branch}" (sin las comillas) para "Branchs to build" "Branch Specifier" (en blanco para 'cualquiera')". Espero que ayude. - verdad

Oh, se parece a lo que encontré con el complemento Git Parameter. (Publiqué mi hallazgo como otra posible respuesta a continuación). Gracias por esta información. - ravindra mijar

Buena respuesta, pero desafortunadamente me veo obligado a rechazar porque el complemento de parámetros dinámicos se suspendió de la distribución de Jenkins debido a una vulnerabilidad de ejecución remota de código: jenkins.io/security/advisory/2017-04-10/… - nik reiman

Es bastante simple usando el "Complemento de parámetros de Git".

Agregue un nombre como "SELECT_BRANCH" ## Asegúrese de que esta variable se use más adelante. Entonces Tipo de parámetro: Rama

Luego comuníquese con SCM: Seleccione: Git y especificador de rama: ${SELECT_BRANCH}

Para verificar, ejecute a continuación en shell en jenkins:

eco ${SELECT_BRANCH}

env.ingrese la descripción de la imagen aquí

enter image description here

Respondido 05 Feb 18, 18:02

En mi caso, trabajamos con ramas de características. Jenkins también debería compilarse automáticamente cuando alguien inserta código en la rama de funciones. Cuando el código se activa por cambios de SCM, el parámetro estará vacío. Así que tuve que hacer clic en Avanzado y escribir ** en el cuadro Valor predeterminado para que la compilación automática como resultado de un cambio de SCM funcione. - Antony

Para mí, uso el parámetro de la etapa de entrada:

  1. Comienzo mi canalización revisando el proyecto git.
  2. Uso un awk commade para generar un archivo barnch.txt con una lista de todas las sucursales
  3. En escenario setps, leo el archivo y lo uso para generar parámetros de elección de entrada

Cuando un usuario lanza un pipeline, este lo estará esperando para elegir en la lista de opciones.

pipeline{
agent any

stages{

    stage('checkout scm') {
        steps {
            script{
                git credentialsId: '8bd8-419d-8af0-30960441fcd7', url: 'ssh://jenkins@git.company.com:/usr/company/repositories/repo.git'
                sh 'git branch -r | awk \'{print $1}\' ORS=\'\\n\' >>branch.txt'
            }

        }
    }
     stage('get build Params User Input') {
        steps{
            script{

                liste = readFile 'branch.txt'
                echo "please click on the link here to chose the branch to build"
                env.BRANCH_SCOPE = input message: 'Please choose the branch to build ', ok: 'Validate!',
                        parameters: [choice(name: 'BRANCH_NAME', choices: "${liste}", description: 'Branch to build?')]


            }
        }
    } 
    stage("checkout the branch"){
        steps{
            echo "${env.BRANCH_SCOPE}"
            git  credentialsId: 'ea346a50-8bd8-419d-8af0-30960441fcd7', url: 'ssh://jenkins@git.company.com/usr/company/repositories/repo.git'
            sh "git checkout -b build ${env.BRANCH_NAME}"
        }
    }
    stage(" exec maven build"){
        steps{
            withMaven(maven: 'M3', mavenSettingsConfig: 'mvn-setting-xml') {
               sh "mvn clean install "
            }
        }
    }
    stage("clean workwpace"){
        steps{
            cleanWs()
        }
    }
}

}

Y luego el usuario interactuará dentro de la compilación:

enter image description here

enter image description here

Respondido el 07 de junio de 18 a las 13:06

Estoy enfrentando un problema similar aquí. Nuestros usuarios están migrando sus trabajos de freestyle a pipeline. No quieren que Jenkinsfile se almacene en sus repositorios (razón histórica) y todavía quieren usar el complemento "Git Parameter"

Entonces, tenemos que usar "Pipeline script" y desarrollar un complemento diferente que funcione como "Git Parameter".

Este nuevo complemento no se integra con la configuración de SCM en el proyecto. El complemento está en https://plugins.jenkins.io/list-git-branches-parameter

Espero que te ayude también

Respondido el 25 de diciembre de 18 a las 09:12

¡Gracias por este complemento! El único problema es que usamos canalización declarativa con otros dos parámetros. Si configuramos esto con la interfaz de usuario, funciona, pero después de ejecutarlo una vez, se elimina la parte del parámetro. ¿Cómo se configura esto en una canalización declarativa en la sección de parámetros? - Tomas Stubbe

Para dar un ejemplo más concreto, algo como esto: parameters { string(defaultValue: "...", description: '...?', name: 'version') choice(choices: ['a', 'b'], description: '...?', name: 'environment') listGitBranches(parameterType: 'Branch', credentialId: '[id]', repositoryUrl: '[repoUrl]', name: 'branch') } - Tomas Stubbe

Tengo una nueva respuesta para este caso: la manera fácil de resolver esto es tener jenkinsFile desde el código fuente.

Entonces elegiste: este trabajo tiene un parámetro git

enter image description here

Y la configuración de Pipeline, sin marcar la casilla de verificación "Pago ligero", esto realizará un pago realmente git en el espacio de trabajo del trabajo.

enter image description here

Después, el parámetro se completará automáticamente con su rama git

Respondido 18 Abr '19, 12:04

ampliando la respuesta de @malenkiy_scot. Creé un nuevo trabajo de jenkins para construir el archivo que usa Extended Choice Plugin.

puede hacer lo siguiente (lo hice como ejecutar los pasos de shell en jenkins, pero podría hacerlo en un script):

git ls-remote git@github.com:my/repo.git |grep refs/heads/* >tmp.txt
sed -e 's/.*refs\/heads\///' tmp.txt > tmp2.txt
tr '\n' ',' < tmp2.txt > tmp3.txt
sed '1i\branches=' tmp3.txt > tmp4.txt
tr -d '\n'  < tmp4.txt > branches.txt

Luego uso el complemento de implementación de Artifact para enviar ese archivo a una ubicación compartida, que se encuentra en una URL web, luego solo uso 'http://localhost/branches.txt' en el complemento Extended Choice como URL. Funciona de maravilla.

Respondido el 12 de enero de 13 a las 09:01

mmm. ¿Es un repositorio público? ¿Puedes compartir la URL de git? Tendría curiosidad por ver por qué no funcionó. paquet

Puede lograr lo mismo usando el complemento de parámetro de elección extendida antes mencionado por malenkiy_scot y un script php simple de la siguiente manera (suponiendo que tenga en algún lugar un servidor para implementar scripts php que pueda ejecutar desde la máquina Jenkins)

<?php
chdir('/path/to/repo');
exec('git branch -r', $output);
print('branches='.str_replace('  origin/','',implode(',', $output)));
?>

or

<?php
exec('git ls-remote -h http://user:pass@repo.git', $output);
print('branches='.preg_replace('/[a-z0-9]*\trefs\/heads\//','',implode(',', $output)));
?>

Con la primera opción, necesitaría clonar el repositorio. Con el segundo no lo hace, pero en ambos casos necesita git instalado en el servidor que aloja su script php. Con cualquiera de estas opciones, se vuelve completamente dinámico, no necesita crear un archivo de lista. Simplemente coloque la URL de su secuencia de comandos en el campo "archivo de propiedades" del parámetro de elección extendida.

respondido 06 mar '13, 09:03

Por lo tanto, necesita este script php en un servidor web que tenga instalado git + credenciales ssh para acceder al servidor git. está bien. Pero, ¿cómo se llama este script php desde el complemento de parámetros de opción extendida? - Amédée Van Gasse

Sí, escribí un pequeño script maravilloso que funciona. Debe agregar un 'Parámetro de elección dinámica' a su trabajo y personalizar el siguiente script maravilloso según sus necesidades:

#!/usr/bin/groovy

def gitURL = "git repo url"
def command = "git ls-remote --heads --tags ${gitURL}"

def proc = command.execute()
proc.waitFor()              

if ( proc.exitValue() != 0 ) {
   println "Error, ${proc.err.text}"
   System.exit(-1)
}

def text = proc.in.text
# put your version string match
def match = /<REGEX>/
def tags = []

text.eachMatch(match) { tags.push(it[1]) }
tags.unique()
tags.sort( { a, b ->
         def a1 = a.tokenize('._-')
         def b1 = b.tokenize('._-')
         try {
            for (i in 1..<[a1.size(), b1.size()].min()) { 
                 if (a1[i].toInteger() != b1[i].toInteger()) return a1[i].toInteger() <=> b1[i].toInteger()
            }
            return 1
         } catch (e) {
            return -1;
         }
} )
tags.reverse()

En mi caso, la cadena de versión estaba en el siguiente formato XXXX y podía tener ramas de usuario en el formato XXX-nombre de usuario, etc. Así que tuve que escribir mi propia función de clasificación. Este fue mi primer guión maravilloso, así que si hay mejores formas de hacer las cosas, me gustaría saberlo.

respondido 16 mar '14, 17:03

Tenga cuidado con este script, ejecutándolo en Dynamic Choice Parameter, había bloqueado mi Jenkins (2.7, 2.8) - Noam Manos

¿Puedes decir por qué? ¿tienes un backtrace? Nunca lo he probado en la versión 2.X - sagi

probablemente se deba a la llamada System.exit () (no relacionada con la versión de Jenkins) - Noam Manos

¿Supongo que esto no es compatible con ssh creds para git? Y no se debe llamar a System.exit, ¿mata el proceso de jenkins? - vicente gerris

Podemos eliminar la lectura/escritura de archivos innecesaria usando text. Mi solución completa es la siguiente:

proc1 = ['/bin/bash', '-c', 
  "/usr/bin/git ls-remote --heads ssh://repo_url.git"].execute()
proc2 = ['/bin/bash', '-c', 
  "/usr/bin/awk ' { gsub(/refs\\/heads\\//, \"\"); print \$2 }' "].execute()
all = proc1 | proc2

choices = all.text
return choices.split().toList();

Respondido el 12 de diciembre de 17 a las 10:12

El siguiente guión maravilloso sería útil, si su trabajo no usa "Administración de código fuente" directamente (del mismo modo, "Complemento de parámetros de Git"), pero aún tiene acceso a un repositorio de git local (clonado):

import jenkins.model.Jenkins

def envVars = Jenkins.instance.getNodeProperties()[0].getEnvVars() 
def GIT_PROJECT_PATH = envVars.get('GIT_PROJECT_PATH') 
def gettags = "git ls-remote -t --heads origin".execute(null, new File(GIT_PROJECT_PATH))

return gettags.text.readLines()
         .collect { it.split()[1].replaceAll('\\^\\{\\}', '').replaceAll('refs/\\w+/', '')  }
         .unique()

Ver explicación completa aquí: https://stackoverflow.com/a/37810768/658497

contestado el 23 de mayo de 17 a las 13:05

Soy consciente del hecho de que en la pregunta original no se mencionó la canalización de Jenkins, pero si aún es aplicable (usándola), encuentro que esta solución es fácil de mantener y conveniente.

Este enfoque describe la configuración necesaria para componer una canalización de Jenkins que "sondea" (enumere) dinámicamente todas las ramas de un repositorio en particular, lo que luego permite al usuario ejecutar la canalización con alguna rama específica al ejecutar una compilación de este trabajo.

Los supuestos aquí son:

  • El servidor Jenkins es 2.204.2 (alojado en Ubuntu 18.04)
  • El repositorio está alojado en un BitBucket.

Lo primero que debe hacer es proporcionar las credenciales de Jenkins para conectarse (y "obtener") al repositorio privado en BitBucket. Esto se puede hacer creando un par de claves SSH para "vincular" entre el usuario de Jenkins (!!) en la máquina que aloja el servidor de Jenkins y el repositorio (privado) de BitBucket.

  1. Lo primero es crear una clave SSH para el usuario de Jenkins (que es el usuario que ejecuta el servidor de Jenkins; lo más probable es que se cree de forma predeterminada durante la instalación):

    guya@ubuntu_jenkins:~$ sudo su jenkins 
    [sudo] password for guya:
    jenkins@ubuntu_jenkins:/home/guya$ ssh-keygen
    

    El resultado debería ser similar al siguiente:

Generación de un par de claves rsa públicas/privadas. Introduzca el archivo en el que guardar la clave
(/var/lib/jenkins/.ssh/id_rsa): directorio creado '/var/lib/jenkins/.ssh'. Ingrese la frase de contraseña (vacío si no hay frase de contraseña): Ingrese la misma frase de contraseña nuevamente: Su identificación se guardó en /var/lib/jenkins/.ssh/id_rsa. Su clave pública se guardó en /var/lib/jenkins/.ssh/id_rsa.pub. La huella digital de la clave es: SHA256:q6PfEthg+74QFwO+esLbOtKbwLG1dhtMLfxIVSN8fQY jenkins@ubuntu_jenkins La imagen randomart de la clave es: +---[RSA 2048]----+ | . ..oE | | . . .o... o | | . o..o | | +.oo | | . ooX..S | |..+.Bo* . | |.++oo* o. | |..+*..*o | | .=+o==+. | +----[SHA256]-----+ jenkins@ubuntu_jenkins:/inicio/guya$

  1. Ahora, el contenido de esta clave SSH debe configurarse en el repositorio de BitBucket de la siguiente manera:
  • Cree (agregue) una clave SSH en el repositorio de BitBucket yendo a: Settings --> Access keys --> Add key.
  • Otorgue permisos de lectura a la clave y copie el contenido de la clave PÚBLICA en el "cuerpo" de la clave. El contenido de la clave se puede mostrar ejecutando: cat /var/lib/jenkins/.ssh/id_rsa.pub
  1. Después de configurar la clave SSH en el repositorio de BitBucket, debemos "decirle" a Jenkins que la UTILICE cuando intente obtener (leer en este caso) el contenido del repositorio. TENGA EN CUENTA que al informar a Jenkins, en realidad significa permitir que el usuario jenkins este "privilegio".

Esto se puede hacer agregando un nuevo nombre de usuario SSH con clave privada al Jenkins --> Credentials --> System --> Global Credentials --> Add credentials.

  • En la sección ID, coloque cualquier nombre descriptivo para la clave.
  • En la sección Nombre de usuario, coloque el nombre de usuario del servidor Jenkins que es jenkins.
  • Marque la sección Clave privada y pegue el contenido de la clave PRIVADA que se generó anteriormente copiando y pegando el contenido de: ~/.ssh/id_rsa. Esta es la clave privada que comienza con la cadena:-----BEGIN RSA PRIVATE KEY----- y termina con la cadena: -----END RSA PRIVATE KEY-----. Tenga en cuenta que todo este "bloque" debe copiarse y pegarse en la sección anterior.
  1. Instale el complemento Git Parameter que se puede encontrar en su página oficial aquí

  2. La tubería mínima que se requiere para enumerar (dinámicamente) todas las ramas de un repositorio determinado es la siguiente:

    pipeline 
    { 
        agent any parameters
        { 
            gitParameter branchFilter: 'origin/(.*)', defaultValue: 'master', name: 'BRANCH', type: 'PT_BRANCH' 
        }
        stages 
        { 
           stage("list all branches") 
           { 
               steps 
               { 
                    git branch: "${params.BRANCH}", credentialsId: "SSH_user_name_with_private_key", url: "ssh://git@myCompanyBitBucketSite.com:port/myRepository.git" 
               } 
          } 
       } 
    }
    

NOTAS:

  • La defaultValue se establece a master de modo que si no existen sucursales, se mostrará en la "lista desplegable" de la canalización.
  • La credentialsId tiene el nombre de las credenciales configuradas anteriormente.
  • En este caso utilicé la URL SSH del repositorio en el parámetro url.
  • Esta respuesta asume (y está configurada) que el servidor git es BitBucket. Supongo que todas las configuraciones "administrativas" realizadas en los pasos iniciales tienen sus configuraciones equivalentes en GitHub.

Respondido 03 Oct 20, 10:10

Puede probar esto, esta lista de nombres de ramas dinámicas en el menú desplegable wrt ingresado Git Repo.

Se requieren complementos de Jenkins:

  1. Validación de parámetro de cadena
  2. Elecciones activas

OPCIÓN 1: Archivo Jenkins:

    properties([
        [$class: 'JobRestrictionProperty'], parameters([validatingString(defaultValue: 'https://github.com/kubernetes/kubernetes.git', description: 'Input Git Repo (https) Url', failedValidationMessage: 'Invalid Git Url. Retry again', name: 'GIT_REPO', regex: 'https://.*'), [$class: 'CascadeChoiceParameter', choiceType: 'PT_SINGLE_SELECT', description: 'Select Git Branch Name', filterLength: 1, filterable: false, name: 'BRANCH_NAME', randomName: 'choice-parameter-8292706885056518', referencedParameters: 'GIT_REPO', script: [$class: 'GroovyScript', fallbackScript: [classpath: [], sandbox: false, script: 'return[\'Error - Unable to retrive Branch name\']'], script: [classpath: [], sandbox: false, script: ''
                            'def GIT_REPO_SRC = GIT_REPO.tokenize(\'/\')
                            GIT_REPO_FULL = GIT_REPO_SRC[-2] + \'/\' + GIT_REPO_SRC[-1]
                            def GET_LIST = ("git ls-remote --heads git@github.com:${GIT_REPO_FULL}").execute()
                            GET_LIST.waitFor()
                            BRANCH_LIST = GET_LIST.in.text.readLines().collect {
                                it.split()[1].replaceAll("refs/heads/", "").replaceAll("refs/tags/", "").replaceAll("\\\\^\\\\{\\\\}", "")
                            }
                            return BRANCH_LIST ''
                            ']]]]), throttleJobProperty(categories: [], limitOneJobWithMatchingParams: false, maxConcurrentPerNode: 0, maxConcurrentTotal: 0, paramsToUseForLimit: '
                            ', throttleEnabled: false, throttleOption: '
                            project '), [$class: '
                            JobLocalConfiguration ', changeReasonComment: '
                            ']])
    try {
        node('master') {
            stage('Print Variables') {
                echo "Branch Name: ${BRANCH_NAME}"
            }
    }
    catch (e) {
        currentBuild.result = "FAILURE"
        print e.getMessage();
        print e.getStackTrace();
    }



OPCIÓN 2: interfaz de usuario de Jenkins

enter image description here

enter image description here



Muestra de salida:

enter image description here

Respondido el 05 de diciembre de 20 a las 08:12

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.