W tym poście omówimy konfigurację automatyzacji HotFix w projektach Maven z wykorzystaniem Teamcity.
Aby zrealizować HotFix, zazwyczaj wykonuje się wiele ręcznych czynności:
- Utworzyć gałąź dla wydania, na które chcesz wdrożyć HotFix.
- Naprawić błąd w wydaniu.
- Zaktualizować wersję bugfix w gałęzi wydania.
- Wdrożyć tag wersji bugfix.
Punkty 1, 3, 4 można zautomatyzować.
Zanim przejdziemy do tematu, chciałbym poruszyć ważny i złożony temat — wersjonowania oprogramowania. Krótkie wyjaśnienie dotyczące Semver można zrozumieć z tego zrzutu ekranu. 
Szczegóły można przeczytać pod tym linkiem: .
Wszystkie ustawienia opisane w tym poście opierają się na i .
W Trunk-Based Development dla każdego wydania należy utworzyć swoją gałąź. Wszystkie zmiany (hotfix) w ramach tego wydania są zatwierdzane w tej gałęzi.
W ramach tego postu zautomatyzujemy następujące rzeczy:
Budowa CI.
Tworzenie nowego wydania.
Tworzenie gałęzi dla wydania.
Zmiana wersji bugfix.

Wymagania:
- Repozytorium Git do przechowywania twojego kodu. W poście będziemy korzystać z repozytorium. .
- Serwer i agent Teamcity. Możesz uruchomić swój lokalny serwer Teamcity i agenta za pomocą
- Tam, gdzie masz agenta Teamcity, muszą być zainstalowane java, maven, git.
Utworzymy w Teamcity projekt „Automation Maven Hotfix” i utworzymy tam 4 zadania.
CI Build.
Utwórz gałąź dla wydania.
Maven zwiększa wersję bugfix.
Maven release.
Zrzut ekranu projektu:

Ogólne ustawienia.
We wszystkich zadaniach należy zaznaczyć opcję „Clean build: Usuń wszystkie pliki w katalogu checkout przed budową.«, ponieważ brak tej opcji powodował u mnie błędy.
Tworzymy jedyny VCS. Szczegóły VCS oznaczone na czerwono.

Zazwyczaj VCS używa schematu HTTPS. W Specyfikacja gałęzi: należy przeglądać wszystkie gałęzie i wszystkie tagi:
+:refs/heads/*
+:refs/tags/*Należy utworzyć 4 parametry konfiguracyjne.
- BRANCH_FOR_INCREMENT.
- TAG_FROM_VERSION.
- TEAM_USER.
- TEAM_USER_EMAIL.
Pole value w BRANCH_FOR_INCREMENT i TAG_FROM_VERSION należy pozostawić puste.

Należy załadować/dodać klucz prywatny. Wszystkich zadaniach oprócz CI Build wymagany jest klucz prywatny.

W każdym zadaniu poza CI Build w sekcji Funkcje budowy należy podłączyć klucz prywatny.
Przykład dla Maven release.

CI Build.
W zadaniu CI Build jest tylko jeden krok. mvn clean test.

Maven release.
W zadaniu Maven release. 2 kroki. Pierwszy krok sprawdza, czy gałąź to master. Jeśli gałąź nie jest master, to zadanie kończy się niepowodzeniem.
BRANCH=$(git branch | grep * | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" != "master" ]]; then
echo 'Gałąź nie jest główna';
echo 'Przerywam';
exit 1;
fi.
Drugi krok to standardowy mvn release:prepare. z opcją. —tryb wsadowy

Utwórz gałąź dla wydania
Aby utworzyć hotfix dla wydania, musisz utworzyć gałąź. Zajmuje się tym zadanie Utwórz gałąź dla wydania. Ma 2 kroki.
Pierwszy krok sprawdza, czy gałąź nie master, a drugi sprawdza, czy wersja w pliku pom.xml nie zawiera słowa SNAPSHOT
BRANCH=$(git branch | grep * | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" == "master" ]]; then
echo 'Gałąź to master';
echo 'Przerywanie';
exit 1;
fi
echo "Pobierz wersję pakietu z pom.xml"
version=`python -c "import xml.etree.ElementTree as ET; print(ET.parse(open('pom.xml')).getroot().find('{http://maven.apache.org/POM/4.0.0}version').text)"`
echo "Sprawdź SNAPSHOT"
if [[ $version == "*SNAPSHOT*" ]]; then
echo "******************* O S T R Z E Ż E N I E *************************"
echo "************ Tworzysz gałąź dla SNAPSHOTS ******************"
echo "***********************************************************"
exit 1
fi
Drugi krok zmienia w developerConnection schemat połączenia z HTTPS na GIT.
# Здесь получаем developerConnection из файла pom.xml
developerConnection=$(xmllint -xpath "/*[local-name() = 'project' ]//*[local-name() = 'developerConnection']/text()" pom.xml | sed 's|scm:git:ssh://||')
echo developerConnection
echo $developerConnection
# Здесь меняем / на : в URL для git_remote_url
git_remote_url=$(echo $developerConnection| sed 's/gitlab.com//gitlab.com:/g')
echo git_remote_url
echo $git_remote_url
git remote set-url origin $git_remote_url
# Если вы не используете ввстроенную возможность Teamcity получения user и email из ~/.gitconfig, то можно указать их здесь
echo 'git config user.name %TEAM_USER%'
git config user.name %TEAM_USER%
echo 'git config user.email %TEAM_USER_EMAIL%'
git config user.email %TEAM_USER_EMAIL%
# Здесь получаем версию из файла pom.xml
echo "Get version package from pom.xml"
version=`python -c "import xml.etree.ElementTree as ET; print(ET.parse(open('pom.xml')).getroot().find('{http://maven.apache.org/POM/4.0.0}version').text)"`
echo $version
# Почему-то без fetch выдавало ошибку.
git fetch
if [ `git branch -a | egrep "${version}$"` ]
then
echo "Branch exists"
exit 1
fi
# Создаем бранч той версии, который был в файле pom.xml
echo "Create branch"
git checkout -b $version
# Чистый git всегда предлагает настроить политику отправки.
git config --global push.default simple
# Пушим в ветку совпадающую с версией в pom.xml
echo "Push release branch"
git push --set-upstream origin $version
Naprawa błędu inkrementacji w Maven
Zadanie składa się z 6 części. Można by było zrefaktoryzować, ale i tak działa.
Pierwszy krok — sprawdzenie, czy gałąź nie master. Jeśli gałąź master zadanie kończy się błędem.
BRANCH=$(git branch | grep * | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" == "master" ]]; then
echo 'Gałąź to master';
echo 'Przerywanie';
exit 1;
fi
# Tutaj pobieramy wersję z pliku pom.xml
echo "Pobierz wersję pakietu z pom.xml"
BRANCH=`python -c "import xml.etree.ElementTree as ET; print(ET.parse(open('pom.xml')).getroot().find('{http://maven.apache.org/POM/4.0.0}version').text)"`
# Muszę zrobić checkout na potrzebną gałąź.
# W przeciwnym razie git status pokazuje detached do potrzebnej gałęzi.
# Musi to być, aby git status pokazywał po prostu gałąź
git checkout $BRANCH
# Eksportujemy zmienną bash do zmiennej Teamcity do dalszego użycia.
echo "##teamcity[setParameter name='BRANCH_FOR_INCREMENT' value='$BRANCH']"
Drugi krok Maven zmienia wersję naprawy błędów w pliku pom.xml.
Cele: w Maven wszystko w jednej linii
build-helper:parse-version versions:set -DnewVersion=${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.nextIncrementalVersion} versions:commit
Trzeci krok — wyświetlenie informacji o stanie Git i inne:
echo 'cat pom.xml'
cat pom.xml
echo 'git status'
git status
echo 'git remote -v'
git remote -v
echo 'git branch'
git branch
Czwarty krok zmienia w developerConnection schemat połączenia z HTTPS na GIT.
I przesyła zmiany do gałęzi wskazanej w zmiennej Teamcity %BRANCH_FOR_INCREMENT%
# Здесь получаем developerConnection из файла pom.xml
developerConnection=$(xmllint -xpath "/*[local-name() = 'project' ]//*[local-name() = 'developerConnection']/text()" pom.xml | sed 's|scm:git:ssh://||')
echo developerConnection
# Здесь меняем / на : в URL для git_remote_url
git_remote_url=$(echo $developerConnection| sed 's/gitlab.com//gitlab.com:/g')
echo git_remote_url
echo $git_remote_url
git remote set-url origin $git_remote_url
# Если вы не используете ввстроенную возможность Teamcity получения user и email из ~/.gitconfig, то можно указать их здесь
echo 'git config user.name %TEAM_USER%'
git config user.name %TEAM_USER%
echo 'git config user.email %TEAM_USER_EMAIL%'
git config user.email %TEAM_USER_EMAIL%
echo 'git add .'
git add .
echo 'git commit -m "Increment bugfix"'
git commit -m "Increment bugfix"
git push --set-upstream origin %BRANCH_FOR_INCREMENT%
Piąty krok pobiera z pliku pom.xml wersję i ustawia ją na Teamcity zmienną TAG_FROM_VERSION.. Zauważ, że wersja z pliku pom.xml bez litery v na początku. A tag na podstawie tej wersji już z literą v na początku.
echo "Pobierz wersję pakietu z pom.xml"
VERSION_AFTER_CHANGE=`python -c "import xml.etree.ElementTree as ET; print(ET.parse(open('pom.xml')).getroot().find('{http://maven.apache.org/POM/4.0.0}version').text)"`
echo $VERSION_AFTER_CHANGE
echo "##teamcity[setParameter name='TAG_FROM_VERSION' value='v$VERSION_AFTER_CHANGE']"
Szósty krok — tagowanie bugfix wersji. Robi się to za pomocą Maven z odpowiednią opcją w Cel.
Opcja Cele:
-Dtag=%TAG_FROM_VERSION% scm:tag
Źródło: habr.com
