Jak powiedzieć Jenkins / Hudson, aby wyzwalał kompilację tylko w przypadku zmian w określonym projekcie w moim drzewie Git?
Jak powiedzieć Jenkins / Hudson, aby wyzwalał kompilację tylko w przypadku zmian w określonym projekcie w moim drzewie Git?
Odpowiedzi:
Wtyczka Git ma opcję (wykluczony region), aby użyć wyrażeń regularnych w celu określenia, czy pominąć budowanie na podstawie tego, czy pliki w zatwierdzeniu pasują do wyrażenia regularnego wykluczonego regionu.
Niestety, standardowa wtyczka Git nie ma obecnie funkcji „dołączonego regionu” (1.15). Jednak ktoś opublikował poprawki na GitHub, które działają na Jenkins i Hudson, które implementują żądaną funkcję.
Jest to trochę pracy do zbudowania, ale działa zgodnie z reklamą i jest niezwykle przydatne, ponieważ jedno z moich drzew Git ma wiele niezależnych projektów.
https://github.com/jenkinsci/git-plugin/pull/49
Aktualizacja: Wtyczka Git (1.16) ma teraz funkcję „uwzględnionego” regionu.
Ignored commit c6e2b1dca0d1885: No paths matched included region whitelist. Jakaś wskazówka? Więcej szczegółów tutaj: stackoverflow.com/questions/47439042/…
Zasadniczo potrzebujesz dwóch miejsc pracy. Jeden, aby sprawdzić, czy pliki się zmieniły, i drugi, aby wykonać właściwą kompilację:
Zadanie nr 1
Powinno to być uruchamiane po zmianach w repozytorium Git. Następnie sprawdza, czy określona ścieżka (tutaj „src”) ma zmiany, a następnie używa interfejsu wiersza polecenia Jenkinsa do wyzwolenia drugiego zadania.
export JENKINS_CLI="java -jar /var/run/jenkins/war/WEB-INF/jenkins-cli.jar"
export JENKINS_URL=http://localhost:8080/
export GIT_REVISION=`git rev-parse HEAD`
export STATUSFILE=$WORKSPACE/status_$BUILD_ID.txt
# Figure out, whether "src" has changed in the last commit
git diff-tree --name-only HEAD | grep src
# Exit with success if it didn't
$? || exit 0
# Trigger second job
$JENKINS_CLI build job2 -p GIT_REVISION=$GIT_REVISION -s
Zadanie nr 2
Skonfiguruj to zadanie tak, aby przyjmowało parametr GIT_REVISION w ten sposób, aby upewnić się, że tworzysz dokładnie tę wersję, którą zbudowało pierwsze zadanie.

$? || exit 0... test $? -eq 0 || exit 0może?
Jeśli używasz deklaratywnej składni Jenkinsfile do opisania potoku budowania, możesz użyć warunku zestawu zmian , aby ograniczyć wykonywanie etapu tylko do przypadku, gdy określone pliki zostaną zmienione. Jest to teraz standardowa funkcja Jenkinsa i nie wymaga żadnej dodatkowej konfiguracji / oprogramowania.
stages {
stage('Nginx') {
when { changeset "nginx/*"}
steps {
sh "make build-nginx"
sh "make start-nginx"
}
}
}
Możesz łączyć wiele warunków, używając słów kluczowych anyOflub odpowiednio allOfdla zachowania OR lub AND :
when {
anyOf {
changeset "nginx/**"
changeset "fluent-bit/**"
}
}
steps {
sh "make build-nginx"
sh "make start-nginx"
}
Chociaż nie ma to wpływu na pojedyncze zadania, możesz użyć tego skryptu, aby zignorować niektóre kroki, jeśli najnowsze zatwierdzenie nie zawierało żadnych zmian:
/*
* Check a folder if changed in the latest commit.
* Returns true if changed, or false if no changes.
*/
def checkFolderForDiffs(path) {
try {
// git diff will return 1 for changes (failure) which is caught in catch, or
// 0 meaning no changes
sh "git diff --quiet --exit-code HEAD~1..HEAD ${path}"
return false
} catch (err) {
return true
}
}
if ( checkFolderForDiffs('api/') ) {
//API folder changed, run steps here
}
api/folderu). Jeśli możesz to naprawić, chciałbym zaproponować sugerowaną zmianę !
Możesz do tego użyć Generic Webhook Trigger Plugin .
Ze zmienną taką jak changed_filesi wyrażeniem $.commits[*].['modified','added','removed'][*].
Możesz mieć tekst filtru, taki jak $changed_filesi wyrażenie regularne filtru, takie jak "folder/subfolder/[^"]+?"if folder/subfolderto folder, który powinien wyzwalać kompilacje.
Odpowiedziałem na to pytanie w innym poście:
Jak uzyskać listę zmienionych plików od ostatniej kompilacji w Jenkins / Hudson
#!/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;
Możesz dodać czek bezpośrednio na górę powłoki exec zadania i zrobi to, exit 0jeśli nie zostaną wykryte żadne zmiany ... Dlatego zawsze możesz sondować najwyższy poziom, aby sprawdzić, czy uruchomi kompilację.
Napisałem ten skrypt, aby pomijać lub wykonywać testy, jeśli są zmiany:
#!/bin/bash
set -e -o pipefail -u
paths=()
while [ "$1" != "--" ]; do
paths+=( "$1" ); shift
done
shift
if git diff --quiet --exit-code "${BASE_BRANCH:-origin/master}"..HEAD ${paths[@]}; then
echo "No changes in ${paths[@]}, skipping $@..." 1>&2
exit 0
fi
echo "Changes found in ${paths[@]}, running $@..." 1>&2
exec "$@"
Możesz więc zrobić coś takiego:
./scripts/git-run-if-changed.sh cmd vendor go.mod go.sum fixtures/ tools/ -- go test