В този пост ще бъде описана настройката на автоматизацията HotFix в Maven проекти с използване на Teamcity.
За да направите HotFix, обикновено се извършват много ръчни действия:
- Създаване на клон за версията, за която искате да внедрите HotFix
- Поправяне на грешка в версията
- Промяна на версията на bugfix в версияния клон
- Внедряване на таг за bugfix версията
Точки 1, 3, 4 могат да бъдат автоматизирани.
Преди да преминем към темата, искам да засегна важна и сложна тема — версиониране на софтуер. Кратко за Semver може да се разбере от този екран. 
Повече информация може да се прочете на линка: .
Всички настройки, описани в този пост, се основават на и .
В Trunk-Based Development за всяка версия трябва да се създаде собствен клон. Всички промени (hotfix) в рамките на тази версия се комитират в този клон.
В рамките на този пост автоматизираме следните неща:
CI сборка
Създаване на нова версия
Създаване на клон за версия
Промяна на версията на bugfix

Изисквания:
- Git репозиторий за съхранение на вашия код. В поста ще се използва репозиторий .
- Teamcity сървър и агент. Можете да настроите свой локален Teamcity сървър и агент с помощта на
- Там, където имате Teamcity агент, трябва да бъдат инсталирани java, maven, git
Създаваме в Teamcity проект „Automation Maven Hotfix“ и там създаваме 4 задачи.
CI Build (CI сборка)
Create branch for release (Създаване на клон за версия)
Maven increment bugfix (Промяна на версията на bugfix)
Maven release (Създаване на нова версия)
Скриншот на проекта:

Общи настройки
Във всички задачи е необходимо да се отметне опцията „Clean build: Изтрийте всички файлове в директорията за изтегляне преди изграждането«, тъй като при отсъствието на тази отметка получавах грешки.
Създаваме единствен VCS. Особеностите на VCS са обградени с червено.

Обикновено VCS използва схема HTTPS. В Branch specification: е посочено да се гледат всички клонове и всички тагове:
+:refs/heads/*
+:refs/tags/*Необходимо е да се създадат 4 параметъра за конфигурация.
- BRANCH_FOR_INCREMENT
- TAG_FROM_VERSION
- TEAM_USER
- TEAM_USER_EMAIL
Полето value в BRANCH_FOR_INCREMENT и TAG_FROM_VERSION трябва да остане празно.

Необходимо е да се качи/добави частен ключ. Във всички задачи освен CI Build е необходим частен ключ.

Във всяка задача освен CI Build в раздела Build Features трябва да се свърже частният ключ.
Пример за Maven release

CI Build**.
В задачата CI Build има само една стъпка mvn clean test

Maven release
В задачата Maven release 2 стъпки. Първата стъпка проверява дали клонът е master. Ако клонът не е master, задачата се проваля.
BRANCH=$(git branch | grep * | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" != "master" ]]; then
echo 'Клонът не е master';
echo 'Прекратяване';
exit 1;
fi
Втората стъпка е стандартна mvn release:prepare с опцията —batch-mode

Създаване на клон за версия
За да създадете hotfix за версия, трябва да създадете клон. С това се занимава таска Създаване на клон за версия. Тя има 2 стъпки.
Първата стъпка проверява дали клонът не master, а втората проверява дали версията в файла pom.xml не съдържа думата SNAPSHOT
BRANCH=$(git branch | grep * | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" == "master" ]]; then
echo 'Клонът е master';
echo 'Прекратяване';
exit 1;
fi
echo "Вземи версия от 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 "Проверка на SNAPSHOT"
if [[ $version == "*SNAPSHOT*" ]]; then
echo "******************* П Р А В И Л О ***"
echo "************ Създавате клон за SNAPSHOTS ******************"
echo "***********************************************************"
exit 1
fi
Втората стъпка променя developerConnection от HTTPS на 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
Maven увеличава bugfix
Таската се състои от 6 части. Можеше да бъде рефакторирана, но и така работи.
Първата стъпка — проверка дали клонът не master. Ако клонът master таската пада.
BRANCH=$(git branch | grep * | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" == "master" ]]; then
echo 'Клонът е master';
echo 'Прекратяване';
exit 1;
fi
# Тук взимаме версия от файла pom.xml
echo "Вземи версия от 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)"`
# Приходи е да направите checkout на нужния клон.
# Иначе git status показва detached към нужния клон.
# Трябва да е git status показва просто клон
git checkout $BRANCH
# Изнасяме променливата bash в променливата Teamcity за по-нататъшна употреба.
echo "##teamcity[setParameter name='BRANCH_FOR_INCREMENT' value='$BRANCH']"
Втората Maven стъпка променя bugfix версията в файла pom.xml.
Цели: в maven всичко в една редица
build-helper:parse-version versions:set -DnewVersion=${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.nextIncrementalVersion} versions:commit
Третата стъпка — извеждане на информация за Git статус и други:
echo 'cat pom.xml'
cat pom.xml
echo 'git status'
git status
echo 'git remote -v'
git remote -v
echo 'git branch'
git branch
Четвъртата стъпка променя developerConnection от HTTPS на GIT.
И пуши промените в клона, указан в 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%
Петата стъпка получава от файла pom.xml версии и я задава в Teamcity проверка TAG_FROM_VERSION. Обърнете внимание, че версията от файла pom.xml без буква v отпред. А тагът, основан на тази версия, вече с буква v отначало.
echo "Вземи версия от 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']"
Шестата стъпка — тагиране bugfix версии. Прави се с помощта на Maven с необходимата опция в Цел.
Опция Цели:
-Dtag=%TAG_FROM_VERSION% scm:tag
Източник: habr.com
