Wskazówki i triki zdobyte przez lata korzystania z Jenkins
Zaktualizowaliśmy ten tekst dla Ciebie!
Data aktualizacji: 24.01.2024
Autor aktualizacji: Miłosz Nowak
Chciałbym podzielić się z Wami kilkoma przydatnymi sposobami pracy z Jenkins oraz metodami radzenia sobie z różnymi problemami, które napotkałem (i prawdopodobnie wielu z Was także) podczas mojej kariery w obszarze QA. Warto również wspomnieć o kilku niezawodnych wtyczkach. Uważałem je za pomocne i oszczędzające czas, więc warto zebrać je w tym krótkim wpisie na blogu.
Zarządzanie zadaniami masowo z linii poleceń
Tworzenie i modyfikowanie zadań za pomocą interfejsu graficznego jest wygodne, dopóki nie musimy zmodyfikować dziesiątek z nich i nie powtarzają się te same czynności, jak zmiana nazw pól, katalogów w ramach zadań itp.
Aby zrobić to szybciej, potrzebna będzie podstawowa wiedza o zadaniach. Mówiąc konkretniej, podstawowe zadania w Jenkins opierają się na XML, gdzie przechowywana jest konfiguracja, więc wszystko, co musimy zrobić, to zmodyfikować konfigurację zadania i wymusić ponowne załadowanie przez Jenkins.
Przejdźmy do przykładu.
Utwórzmy nowe zadanie ogólnego przeznaczenia i nazwijmy je test_job. To zadanie będzie po prostu wypisywać bieżącą datę w formacie DD/MM/YYYY. Aby to zrobić, musimy dodać następującą linię kodu shell w kroku „Wykonaj polecenie shell”:
printf "%s\n" "$(date +'%d/%m/%Y')"
Następnie utwórzmy drugie zadanie reload_job_config, którego zadaniem będzie przeładowanie konfiguracji wskazanego zadania. Będziemy korzystać z API Jenkinsa, dlatego w parametrach zadania należy podać użytkownika i jego token API oraz wyraźnie zadanie, które chcemy odświeżyć. W tym celu zaznacz pole wyboru To zadanie jest sparametryzowane, a następnie utwórz 3 zmienne tekstowe: użytkownik, token i nazwa_zadania_. W kroku Wykonaj powłokę:
curl -O http://"$user":"$token"@$JENKINS_URL/job/$job_name_/config.xml
curl -X POST http://"$user":"$token"@$JENKINS_URL/job/$job_name_/config.xml --data-binary ""@config.xml""
Za pomocą curl plik config.xml (domyślna nazwa pliku konfiguracyjnego zadania – jeśli jest inna w Twoim przypadku, dodaj kolejny parametr, aby go dostosować) jest pobierany do przestrzeni roboczej zadania reload_job_config. Następnie zmodyfikowany plik konfiguracyjny jest wysyłany z powrotem, co powoduje, że nasze zadanie jest zmieniane zgodnie ze zmianami w config.xml. $JENKINS_URL to wbudowana zmienna środowiskowa, w moim przypadku wskazująca na localhost:8080. Token API można wygenerować w konfiguracji profilu. Zachowaj go gdzieś, ponieważ po jego wygenerowaniu nie będzie już możliwy do odzyskania.
Po utworzeniu naszych testowych zadań, możemy zmodyfikować plik config.xml zadania test_job na dysku, a następnie go przeładować. Na przykład, załóżmy, że chcemy zmienić format daty używanej w zadaniu test_job.
cd path_to_job_config_file
sed -i -e 's/%d\/%m\/%Y/%d-%m-%Y/g' config.xml
Teraz uruchom zadanie reload_job_config, podając wymagane parametry, i gotowe – zadanie jest przeładowane, zaktualizowane zgodnie z config.xml na dysku.
Na podstawie tego prostego przykładu widać, że dla wielu zmian w określonych zadaniach (np. zmiana wspólnych ścieżek, poleceń itp.), jest to wygodny sposób szybkich zmian, bez używania wbudowanej opcji Jenkins o nazwie Reload, która usuwa wszystkie dane i przeładowuje wszystkie zadania.
Kiedyś miałem zadanie, którego wymagania zmieniały się co drugi dzień. Zadania Jenkins odpowiedzialne za to korzystały ze wtyczki do wykresów, więc ręczna zmiana opisów dziesiątek wykresów była naprawdę uciążliwa. Dlatego stworzyłem to rozwiązanie i teraz dzielę się nim z Wami.
Przechowywanie konfiguracji zadań w git jako sposób śledzenia zmian
Jak wspomniałem w poprzedniej sekcji, Jenkins przechowuje ogólne konfiguracje zadań w plikach config.xml. Biorąc to pod uwagę, możemy łatwo śledzić (i tworzyć kopie zapasowe) zadania w git, tworząc zadanie cron lub zadanie Jenkins.
Zakładając, że mamy zadanie skonfigurowane z wtyczką Git, oto jeden ze sposobów, jak możemy zrobić kopię zapasową plików config.xml:
#!/bin/sh
# Go to backup directory
cd /path_to_backup_directory
# Clear all files except hidden (.git)
ls | xargs -n1 -i{} rm -rf "{}"
# Create dirs based on current ls result
ls /path_to_jobs_signatures/jobs | xargs -n1 -i{} mkdir "{}"
# Copy config.xml to each catalog
ls | xargs -n1 -i{} cp -R ../jobs/"{}"/config.xml "{}"
# Create directory Jenkins configuration backup
mkdir JenkinsConfig
# Copy Jenkins instance files
ls -I "jobs*" -I "logs" -I "*.log" -I "monitoring" -I "updates" \
-I "userContent" -I "fingerprints" -I "*disk_usage*Factory*" ../ | \
xargs -n1 -i{} cp -R ../"{}" ./JenkinsConfig/"{}"
# Add everything to staging file
git add .
# Create commit message
message=$(date +%Y-%m-%d_%H-%M)
# Commit files
git commit -m "Backup "$message
# Push changes
git push origin master
Każda linia jest dość dobrze opisana w powyższym fragmencie kodu.
Z drugiej strony, możesz użyć jednej z istniejących wtyczek zaprojektowanych do śledzenia zmian, jak np. jobConfigHistory (szczegóły na stronie https://plugins.jenkins.io/jobConfigHistory).
Wtyczka Git i uruchamianie zadań z określonym forkiem i gałęzią
Wtyczka Git jest szeroko stosowana w Jenkins. Jest również jedną z sugerowanych wtyczek podczas instalacji. Dzięki niej użytkownicy mogą uruchamiać kod na różnych forkach i gałęziach w określonych krokach procesu ciągłej integracji.
Uważałem za przydatne utworzenie zadania git_clone z czterema parametrami tekstowymi, jak poniżej: fork, branch, git_clone_directory, repository, które pozwala mi na sklonowanie dowolnego repozytorium (oczywiście z skonfigurowanym kluczem SSH) do wskazanej lokalizacji na dysku. W moim przypadku było to samo-hostowane repozytorium Bitbucket, dlatego adres URL repozytorium może być inny w Twoim przypadku.
To małe pomocnicze zadanie było używane setki razy jako część pipeline’ów lub zadań multiprojektowych.
Uruchamianie pipeline’ów za pomocą wtyczki Node do przełączania między workerami
Jak wiemy, Jenkins działa z rozproszonymi agentami (serwerami). W moim projekcie miałem kilka serwerów, na których przechowywane były agenty Jenkins z dostępem do różnych zasobów na dyskach twardych. Aby zorganizować proces za pomocą pipeline’u, musiałem używać różnych agentów do konkretnych kroków, aby uzyskać dostęp do pożądanych danych. Jednym ze sposobów jest użycie wtyczki Node oraz dyrektywy agent w Declarative Pipeline.
Oto przykład, jak to było zarządzane:
pipeline {
agent { node { label 'master' } }
environment {
PATH = "/usr/sbin:/usr/bin:/sbin:/bin"
}
stages {
stage('Test') {
steps {
script {
echo "[ INFO ] functional tests"
}
build job: 'functional_tests', parameters: [
[
$class: 'NodeParameterValue',
name: 'node',
labels: ["slave"],
nodeEligibility: [$class: 'AllNodeEligibility']
]
]
}
}
stage('Parsing') {
steps {
script {
sh "ls /tests/functional -t | head -1 > lastResults"
lastResults = readFile('lastResults').trim()
echo "[ INFO ] Parsing last results from: "+lastResults
}
build job: 'parsing_tool', parameters: [
[
$class: 'NodeParameterValue',
name: 'node',
labels: ["slave"],
nodeEligibility: [$class: 'AllNodeEligibility']
],
string(
name: 'input',
value: '/tests/functional'+lastResults
),
string(
name: 'output',
value: '/results/functional'
)
]
}
}
stage('Updating dashboard') {
steps {
script {
echo "[ INFO ] Updating tests results dashboard"
// Python's script is placed in workspace
sh """
source /home/py_envs/python363_env/bin/activate
python update_dashboard.py
"""
}
}
}
}
}
W słowie wyjaśnienia na temat tego fragmentu kodu:
sh "ls /tests/functional -t | head -1 > lastResults "
lastResults = readFile('lastResults').trim()
W Declarative Pipeline każda instrukcja sh jest oddzielną instancją i nie przechowuje utworzonych zmiennych. Jednym z obejść jest zapisanie wyników do pliku tekstowego, a następnie ich odczytanie.
Wnioski
Dane o udziale w rynku narzędzi do ciągłej integracji są trudne do porównania. Można spotkać informacje o udziale rynku zajmowanym przez Jenkins, który waha się od 20% do nawet 50%. Niemniej jednak, popularność tego narzędzia jest niezaprzeczalna, dlatego warto je spersonalizować za pomocą dostępnych wtyczek i/lub napisać własne narzędzia, które mogą poprawić efektywność codziennych zadań. Mam nadzieję, że znalazłeś coś przydatnego w tym tekście.
Poznaj mageek of j‑labs i daj się zadziwić, jak może wyglądać praca z j‑People!
Skontaktuj się z nami


