remota - Cómo elegir dinámicamente una rama git para usar en la compilación Jenkins
git pull origin master (3)
Estoy tratando de crear una nueva configuración de proyecto para el servidor de compilación Jenkins. Para simplificar lo que estoy tratando de hacer, usaré solo dos componentes para describir el problema.
Componente A
- El cambio en este componente activa la compilación de este proyecto en el servidor de CI.
- El servidor de CI tiene una rama configurada estáticamente para monitorear los cambios y la construcción. P.ej. Dominar o desarrollar rama.
- Este componente contiene un archivo de configuración con la versión requerida de ComponentB del que depende.
Componente B
- Los cambios en este componente no activan la compilación de este proyecto en el servidor de CI (habrá otro proyecto para cubrir el desarrollo de ComponentB).
- Las versiones individuales del componente están etiquetadas
- ComponentA ha requerido la versión de ComponentB en su archivo de configuración
- El servidor de CI no sabe qué rama (etiqueta) se va a retirar hasta que el archivo de configuración de ComponentA se analiza de alguna manera.
¿Cuál es la forma correcta de lograr esto en Jenkins? Estaba intentando descubrir cómo agregar este comportamiento dinámico de analizar el archivo de configuración y hacer que Git Plugin compruebe la rama según la versión esperada de ComponentB, pero hasta ahora no tengo ni idea.
En el siguiente paso, es posible que desee tener comodines (como 5.3. *) En el archivo de configuración, por lo que tendré que encontrar la etiqueta ComponentB más nueva que coincida con el comodín.
EDITAR
Ahora veo que simplifiqué demasiado mi problema y debido a la simplificación, la limitación principal ya no está presente.
La principal limitación es que los componentes A y B deben construirse juntos. No es posible compilarlos por separado, ya que forman un ejecutable / biblioteca y la secuencia de comandos de compilación necesita archivos de origen de ambos componentes.
Si pregunta por qué una configuración tan extraña, démosle una descripción al Componente A y B:
- Componente A: código específico de plataforma nativa
- ComponentB: código independiente de plataforma nativa
Puede haber muchos componentes como uno para cada plataforma, pero solo un solo componente B. La combinación de A con B produce un código fuente completo para una sola plataforma, pero no todas las plataformas pueden actualizarse a la última versión de B, por lo que debe tener control sobre qué versión de B se debe utilizar para construido.
1 - ¿Sería una posible solución agregar el proyecto B
como una subrepresentación del proyecto A
?
2- (si realmente se debe evitar incluir el código fuente completo de B): ¿empujar las compilaciones de B a un repo de B_builds
, y agregar este repo como un sub-repo de A
sería una posible solución?
Justificación: una forma de hacer más explícita la dependencia entre A
y B
es representarla dentro de las dependencias del repositorio.
Esto requeriría agregar un paso adicional al administrar el proyecto A
:
update `B` sub repo in `A` project, and push this to `A`
Cada vez que produzcas una nueva versión para B
Sin embargo, tendría una visión clara, desde A
, acerca de cuándo se integraron las versiones de B
(por ejemplo: "solo usamos B 2.0.1
partir de A 4.3.2
"), y presionando a A
dispararía su flujo de Jenkins habitual .
El uso del complemento de vinculación de credenciales funcionó muy bien para mí (también mencionado por @zeppelin)
Pasos:
En la sección de credenciales globales :
-
Add Credentials
del tipo: "Nombre de usuario con contraseña" . Este debe ser el nombre de usuario y la contraseña para el servidor git del repositorio del componente B que utiliza el protocolo HTTPS (la opción SSH no es buena para este propósito)
En su configuración de trabajo Jenkins:
- Coloque el componente A en la gestión de código fuente regular en la sección
Git
todos los campos requeridos ( repositorios , sucursales , etc.).- Será más claro y más limpio colocar el repositorio en un subdirectorio: en Comportamientos adicionales, seleccione
Check out to a sub-directory
y escriba:component_a
- Será más claro y más limpio colocar el repositorio en un subdirectorio: en Comportamientos adicionales, seleccione
- Asegúrese también de verificar en Generar desencadenadores la
Build when a change is pushed to GitHub
En la sección Entorno de compilación, active la casilla
Use secret text(s) or file(s)
- poner en
Variable
algún nombre: MY_CRED - en
Credentials
elija las credenciales específicas que creó en el paso 1.
- poner en
Ahora, utilizando
MY_CRED
en el código de shell de Ejecución , tendrá acceso al repositorio del componente B:DIR="component_b" if [ "$(ls -A $DIR/.git)" ]; then cd $DIR git fetch else git clone https://[email protected]/proj/component_b.git $DIR cd $DIR fi git show
- Nota : NO verá el usuario ni la contraseña en los registros, por lo que debe ser seguro.
git clone ''https://****@github.com/proj/component_b.git'' component_b
:git clone ''https://****@github.com/proj/component_b.git'' component_b
- Nota : NO verá el usuario ni la contraseña en los registros, por lo que debe ser seguro.
Realice todos los análisis de configuración del componente A para obtener la etiqueta deseada:
TAG=$(cat ./component_a/config.cfg | grep ... | sed ...)
- Compruebe la etiqueta deseada:
cd component_b; git checkout -f $TAG
cd component_b; git checkout -f $TAG
- Nota: la etiqueta
-f
force.
- Nota: la etiqueta
- Ahora ejecuta el código y prueba como desees ...
Una opción para lograr lo que desea es usar la siguiente configuración:
Crea dos trabajos de Jenkins:
- "Componente A" (activado automáticamente en los cambios de SCM)
- "Componente B" ("manualmente" activado)
Paso 1
Defina el parámetro de compilación de branch
para "Componente B":
Utilice este parámetro como el especificador de rama "Complemento Git":
Ahora debería poder activar manualmente la compilación "Componente B", especificando un parámetro de rama (etiqueta) adecuado, por ejemplo, tags/5.3.0
.
Paso 2
Agregue un nuevo paso de compilación "Ejecutar shell" a su compilación "Componente A", que extraerá la versión "Componente B" del archivo de configuración en el área de trabajo, y prepare el archivo b.properties
con los parámetros de compilación "Componente B".
Instale un complemento de Jenkins de Trigger parametrizado , y agregue un nuevo paso de compilación "Activación / activación de activación en otros proyectos" al trabajo del "Componente A":
Usando su archivo b.properties
como la fuente de los parámetros de compilación.
Ahora, cada vez que se reconstruye el "Componente A", se activará una nueva compilación del "Componente B", con la rama / etiqueta de destino como parámetro de compilación.
Añadiendo soporte de comodín
Si desea admitir versiones con caracteres comodín, puede usar el git ls-remote
para encontrar la última etiqueta, así:
#B=$(obtain B version from the config file in a usual way)
LATEST=$(/
git ls-remote --tags YOUR_REPOSITORY_URL "$B"/
|cut -d / -f3|sort -r --version-sort|head -1/
)
cat <<EOF > b.properties
branch=tags/$LATEST
EOF
Esto mostrará una lista de todas las etiquetas, que coinciden con el patrón de versión "B", en el repositorio remoto del "Componente B", y guardará el último número de versión en la variable LATEST
.
Agregue esto a su paso "Ejecutar shell" del trabajo "Componente A", y debería poder manejar patrones de números de versión como: 5.3.*
El problema es que el script de shell se ejecutará como el usuario del demonio de Jenkins, por lo que debe tener configuradas las credenciales adecuadas para acceder al repositorio de Git remoto (por ejemplo, a través de la clave de publicación ssh).
Como alternativa, puede consultar el complemento de vinculación de credenciales para reutilizar las credenciales de Git almacenadas en el propio Jenkins.
Usando la tubería de estilo Jenkins 2.0
También puede resolver la tarea en cuestión utilizando una Pipeline estilo Jenkins 2.0, que le permitirá verificar el código de los componentes A y B, en un solo espacio de trabajo, y luego aplicarles algunos pasos de compilación comunes.
Su tubería podría verse algo como esto:
node {
//Settings
def credentialsId = ''8fd28e34-b04e-4bc5-874a-87f4c0e05a03''
def repositoryA = ''ssh://[email protected]/projects/a.git''
def repositoryB = ''ssh://[email protected]/projects/b.git''
stage(''Checkout component A'') {
git credentialsId: credentialsId ,
url: repositoryA , branch : "master"
}
stage("Resolve and checkout component B") {
def deps = readProperties file: ''meta.properties''
echo "Resolved B version = ${deps[''b'']}"
dir("module/b") {
//Clone/Fetch Component B
checkout scm:[
$class: ''GitSCM'',
userRemoteConfigs: [[url: repositoryB, credentialsId: credentialsId]],
branches: [[name: ''refs/tags/*'']]
],
changelog: false, poll: false
//Checkout the tag, matching deps[''b''] pattern
sshagent([credentialsId]) {
sh "git checkout /$(git tag -l /"${deps[''b'']}/" |sort -r --version-sort|head -1)"
}
}
}
stage("Build A+B") {
//Apply a common build step
}
}
Aquí utilizamos el comando "readProperties", que forma parte del complemento de pasos de la utilidad Pipeline para extraer el patrón de versión "Component B" de meta.properties
. También hay readYaml, readJSON comandos disponibles.
A continuación, obtenemos / clonamos el "Componente B", con el changelog: false, poll: false
indicadores, para evitar que se registre en el sondeo de SCM, en la carpeta "módulo / b" del espacio de trabajo actual.
Luego, invoque un comando de shell para seleccionar la etiqueta, según el patrón de versión, que hemos obtenido anteriormente, y verifíquelo (5.3. * Los comodines de estilo también deberían funcionar).
La invocación sh
, se envuelve en sshagent , para que reutilice las credenciales apropiadas de la tienda de credenciales de Jenkins.