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 0
moż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 anyOf
lub odpowiednio allOf
dla 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_files
i wyrażeniem $.commits[*].['modified','added','removed'][*]
.
Możesz mieć tekst filtru, taki jak $changed_files
i wyrażenie regularne filtru, takie jak "folder/subfolder/[^"]+?"
if folder/subfolder
to 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 0
jeś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