2011-06-07 7 views
29

configuró Jenkins pero desea saber qué archivos se agregaron/cambiaron entre la compilación actual y la compilación anterior. Me gustaría ejecutar algunas pruebas de larga duración dependiendo de si ciertas partes del árbol fuente se cambiaron o no.Cómo obtener la lista de archivos modificados desde la última compilación en Jenkins/Hudson

Al haber rastreado los interwebs, no puedo encontrar ninguna mención de esta habilidad dentro de Hudson/Jenkins, aunque se hicieron sugerencias para usar los ganchos post-commit de SVN. Tal vez es tan simple que todos (excepto yo) saben cómo hacerlo.

¿Alguien sabe si esto es posible?

Respuesta

4

El servidor CI le mostrará la lista de cambios, si está buscando cambios y está utilizando la actualización SVN. Sin embargo, parece que desea cambiar el comportamiento de la construcción en función de qué archivos se modificaron. No creo que exista una forma inmediata de hacerlo con Jenkins solo.

Un enganche post-commit es una idea razonable. Puede parametrizar el trabajo y hacer que su script hook abra la compilación con el valor del parámetro establecido de acuerdo con los cambios confirmados. No estoy seguro de lo difícil que puede ser para ti.

Sin embargo, es posible que desee considerar dividir esto en dos trabajos separados, uno que se ejecuta en cada confirmación y otro diferente para las pruebas de larga ejecución que no siempre necesita. Personalmente, prefiero mantener un comportamiento laboral consistente entre las ejecuciones. De lo contrario, la trazabilidad sufre.

+1

"parece querer cambiar el comportamiento de la compilación según los archivos modificados" Esto se hace, por ejemplo, con las compilaciones incrementales de Maven (complemento). –

0

Nota: tiene que usar el cliente svn de jenkin para obtener una lista de cambios. Hacerlo a través de un paso de compilación de shell no mostrará los cambios en la compilación.

16

Lo he hecho de esta manera. No estoy seguro si esa es la manera correcta, pero parece estar funcionando. Necesita instalar el plugin jenkins groovy y realizar la siguiente secuencia de comandos.

import hudson.model.*; 
import hudson.util.*; 
import hudson.scm.*; 
import hudson.plugins.accurev.* 

def thr = Thread.currentThread(); 
def build = thr?.executable; 

def changeSet= build.getChangeSet(); 

changeSet.getItems(); 

ChangeSet.getItems() le ofrece los cambios. Desde que uso accurev, lo hice List<AccurevTransaction> accurevTransList = changeSet.getItems();

Aquí, la lista modificada contiene archivos/nombres duplicados si se ha confirmado más de una vez durante la ventana de compilación actual.

+0

Usó su código para llegar a esta solución: http://stackoverflow.com/a/12939663/734687, ¡muchas gracias! – ChrLipp

+0

si el operador de navegación segura ('?') Se usa en 'thr', ¿no es posible que' build' sea nulo, y luego obtendría una excepción de puntero nulo en 'build.getChangeSet()' the siguiente linea abajo? – solstice333

4
echo $SVN_REVISION 
svn_last_successful_build_revision=`curl $JOB_URL'lastSuccessfulBuild/api/json' | python -c 'import json,sys;obj=json.loads(sys.stdin.read());print obj["'"changeSet"'"]["'"revisions"'"][0]["'"revision"'"]'` 
diff=`svn di -r$SVN_REVISION:$svn_last_successful_build_revision --summarize` 
+0

¿me puede explicar cómo hacerlo y dónde? su solución parece ser la que estoy buscando, pero no sé cómo implementarla. – Mike

+0

@ user1725378 ejecuta en 'build shell' para subversion solo – jollychang

2

Puede utilizar el Remote Access API Jenkins para obtener una descripción legible por máquina de la versión actual, incluyendo su conjunto completo de cambios. La sutileza aquí es que si tiene configurado un 'período de silencio', Jenkins puede agrupar múltiples confirmaciones en el mismo repositorio en una única compilación, por lo que depender de un único número de revisión es un poco ingenuo.

Me gusta mantener mis ganchos de post-commit de Subversion relativamente simples y entregarlos al servidor de CI. Para ello, utilizo wget para desencadenar la acumulación, algo como esto ...

/usr/bin/wget --output-document "-" --timeout=2 \ 
    https://ci.example.com/jenkins/job/JOBID/build?token=MYTOKEN 

El trabajo se configura en el lado Jenkins para ejecutar un script en Python que aprovecha la variable BUILD_URL medio ambiente y construye la URL para la API de eso. La URL termina pareciéndose a esto:

https://ci.example.com/jenkins/job/JOBID/BUILDID/api/json/ 

Aquí hay un código de Python muestra que se pueda ejecutar dentro de la secuencia de comandos shell. He omitido el manejo de errores o la autenticación HTTP para que todo sea legible aquí.

import os 
import json 
import urllib2 


# Make the URL 
build_url = os.environ['BUILD_URL'] 
api = build_url + 'api/json/' 

# Call the Jenkins server and figured out what changed 
f = urllib2.urlopen(api) 
build = json.loads(f.read()) 
change_set = build['changeSet'] 
items = change_set['items'] 
touched = [] 
for item in items: 
    touched += item['affectedPaths'] 
1

A través de Groovy:

<!-- CHANGE SET --> 
<% changeSet = build.changeSet 
if (changeSet != null) { 
hadChanges = false %> 
<h2>Changes</h2> 
<ul> 
<% changeSet.each { cs -> 
hadChanges = true 
aUser = cs.author %> 
<li>Commit <b>${cs.revision}</b> by <b><%= aUser != null ? aUser.displayName :  it.author.displayName %>:</b> (${cs.msg}) 
<ul> 
<% cs.affectedFiles.each { %> 
<li class="change-${it.editType.name}"><b>${it.editType.name}</b>: ${it.path}        </li> <% } %> </ul> </li> <% } 

if (!hadChanges) { %> 
    <li>No Changes !!</li> 
<% } %> </ul> <% } %> 
3

Usando el flujo Construir Plugin y git:

final changeSet = build.getChangeSet() 
final changeSetIterator = changeSet.iterator() 
while (changeSetIterator.hasNext()) { 
    final gitChangeSet = changeSetIterator.next() 
    for (final path : gitChangeSet.getPaths()) { 
    println path.getPath() 
    } 
} 
+0

¿Hay alguna forma de obtener la ruta de acceso absoluta del archivo? Esto da la ruta relativa al repositorio, por lo que no puedo averiguar en qué repositorio estaba el archivo. –

+0

No lo sé por la parte superior de mi cabeza. Tendrá que ir a través de la fuente, https://github.com/jenkinsci/git-plugin/blob/master/src/main/java/hudson/plugins/git/GitChangeSet.java, y/o experimentar usted mismo. –

+0

Build Flow Plugin ahora está en desuso, para mí (Jenkins 2.89) esta solución no funciona. – heroin

2
#!/bin/bash 

set -e 

job_name="whatever" 
JOB_URL="http://myserver:8080/job/${job_name}/" 
FILTER_PATH="path/to/folder/to/monitor" 

python_func="import json, sys 
obj = json.loads(sys.stdin.read()) 
ch_list = obj['changeSet']['items'] 
_list = [ j['affectedPaths'] for j in ch_list ] 
for outer in _list: 
    for inner in outer: 
    print inner 
" 

_affected_files=`curl --silent ${JOB_URL}${BUILD_NUMBER}'/api/json' | python -c "$python_func"` 

if [ -z "`echo \"$_affected_files\" | grep \"${FILTER_PATH}\"`" ]; then 
    echo "[INFO] no changes detected in ${FILTER_PATH}" 
    exit 0 
else 
    echo "[INFO] changed files detected: " 
    for a_file in `echo "$_affected_files" | grep "${FILTER_PATH}"`; do 
    echo " $a_file" 
    done; 
fi; 

ligeramente diferente - que necesitaba un guión de Git en una carpeta en particular .. entonces, escribí un cheque basado en jollychang

Se puede agregar directamente al script de shell exec del trabajo. Si no se detectan archivos lo hará exit 0, es decir SUCCESS .. esta manera siempre se puede disparar en registros de entrada a la cesión temporal, pero la construcción cuando los archivos en la carpeta del cambio de interés

Pero .. Si querían construir en sitio la demanda (es decir, hacer clic en Crear ahora) con el pasado de la última acumulación .. que iba a cambiar a _affected_files:

_affected_files=`curl --silent $JOB_URL'lastSuccessfulBuild/api/json' | python -c "$python_func"` 
1

con tuberías Jenkins (API apoyo secuencia de los conectores 2.2 o superior) para mí esta solución está funcionando:

def changeLogSets = currentBuild.changeSets 
for (int i = 0; i < changeLogSets.size(); i++) { 
    def entries = changeLogSets[i].items 
    for (int j = 0; j < entries.length; j++) { 
    def entry = entries[j] 
    def files = new ArrayList(entry.affectedFiles) 
    for (int k = 0; k < files.size(); k++) { 
     def file = files[k] 
     println file.path 
    } 
    } 
} 

Ver https://support.cloudbees.com/hc/en-us/articles/217630098-How-to-access-Changelogs-in-a-Pipeline-Job-

Cuestiones relacionadas