În această postare va fi descrisă configurarea automatizării HotFix în proiectele Maven folosind TeamCity.
Pentru a realiza un HotFix, de obicei se fac multe acțiuni manuale:
- Crearea unui branch pentru release-ul pe care doriți să aplicați HotFix-ul
- Corectarea erorii din release
- Modificarea versiunii bugfix în branch-ul de release
- Aplicarea unei etichete bugfix pentru versiune
Punctele 1, 3, 4 pot fi automatizate.
Înainte de a trece la subiect, aș dori să ating o temă importantă și complicată — versiunea software-ului. O scurtă descriere despre Semver poate fi înțeleasă din acest screenshot. 
Mai multe detalii pot fi citite la link: .
Toate setările descrise în această postare se bazează pe și .
În dezvoltarea bazată pe Trunk, pentru fiecare release trebuie să creați un branch propriu. Toate modificările (hotfix-urile) în cadrul acestui release sunt angajate în acest branch.
În cadrul acestei postări vom automatiza următoarele lucruri:
Construirea CI
Crearea unui nou release
Crearea unui branch pentru release
Modificarea versiunii bugfix

Cerințe:
- Un repo Git pentru stocarea codului dvs. În postare va fi folosit repo-ul .
- Server și agent TeamCity. Puteți configura serverul și agenții dvs. TeamCity local folosind
- Acolo unde aveți agent TeamCity, trebuie să fie instalate java, maven, git
Vom crea în TeamCity un proiect „Automation Maven Hotfix” și vom crea 4 sarcini acolo.
CI Build (Construire CI)
Crearea branch-ului pentru release (Creare branch pentru release)
Incrementarea versiunii bugfix Maven (Modificarea versiunii bugfix)
Release Maven (Crearea unui nou release)
Screenshot al proiectului:

Setările generale
În toate sarcinile trebuie să bifați caseta „Construcție curată: Ștergeți toate fișierele din directorul de checkout înainte de build„, deoarece în absența acestei bifări apăreau erori.
Creăm un singur VCS. Caracteristicile VCS-ului sunt marcate cu roșu.

În general, VCS folosește schema HTTPS. În Specificarea branch-ului: se specifică să se observe toate branch-urile și toate etichetele:
+:refs/heads/*
+:refs/tags/*Trebuie să creați 4 Parametrii de Configurare.
- BRANCH_FOR_INCREMENT
- TAG_FROM_VERSION
- TEAM_USER
- TEAM_USER_EMAIL
Câmpul value în BRANCH_FOR_INCREMENT și TAG_FROM_VERSION trebuie lăsat gol.

Trebuie să încărcați/adăugați o cheie privată. În toate sarcinile, cu excepția CI Build, este necesară cheia privată.

În fiecare sarcină, cu excepția CI Build, în secțiunea Funcții de Build trebuie să conectați cheia privată.
Exemplu pentru Release Maven

CI Build**.
În sarcina CI Build există doar un singur pas mvn clean test

Release Maven
În sarcina Release Maven 2 pași. Primul pas verifică dacă branch-ul este master. Dacă branch-ul nu este master, atunci sarcina eșuează.
BRANCH=$(git branch | grep * | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" != "master" ]]; then
echo 'Branch nu este master';
echo 'Anulare';
exit 1;
fi
Al doilea pas este standard mvn release:prepare cu opțiunea —batch-mode

Creează ramura pentru lansare
Pentru a crea un hotfix pentru lansare, trebuie să creezi o ramură. Acest lucru se ocupă de task Creează ramura pentru lansare. Are 2 pași.
Primul pas verifică dacă ramura nu master, și al doilea verifică dacă versiunea din fișierul pom.xml nu conține cuvântul SNAPSHOT
BRANCH=$(git branch | grep * | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" == "master" ]]; then
echo 'Branch este master';
echo 'Anulare';
exit 1;
fi
echo "Obține versiunea pachetului din 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 "Verifică SNAPSHOT"
if [[ $version == "*SNAPSHOT*" ]]; then
echo "******************* A T E N Ț I E *************************"
echo "************ Creezi o ramură pentru SNAPSHOTS ******************"
echo "***********************************************************"
exit 1
fi
Al doilea pas schimbă schema de conexiune developerConnection de la HTTPS la 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 increment bugfix
Task-ul constă din 6 părți. Ar fi putut fi refactorizat, dar și așa funcționează.
Primul pas — verifica că ramura nu master. Dacă ramura master task-ul eșuează.
BRANCH=$(git branch | grep * | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" == "master" ]]; then
echo 'Branch este master';
echo 'Anulare';
exit 1;
fi
# Aici obținem versiunea din fișierul pom.xml
echo "Obține versiunea pachetului din 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)"`
# Trebuie să facem checkout pe ramura dorită.
# Altfel, git status arată detached față de ramura dorită.
# Este necesar ca git status să arate pur și simplu ramura
git checkout $BRANCH
# Exportăm variabila bash în variabila Teamcity pentru utilizare ulterioară.
echo "##teamcity[setParameter name='BRANCH_FOR_INCREMENT' value='$BRANCH']"
Al doilea pas Maven schimbă versiunea bugfix în fișierul pom.xml.
Obiective: la maven totul într-o singură linie
build-helper:parse-version versions:set -DnewVersion=${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.nextIncrementalVersion} versions:commit
Al treilea pas — afișarea informațiilor despre status-ul Git și altele:
echo 'cat pom.xml'
cat pom.xml
echo 'git status'
git status
echo 'git remote -v'
git remote -v
echo 'git branch'
git branch
Al patrulea pas schimbă schema de conexiune developerConnection de la HTTPS la GIT.
Și împinge modificările în ramura specificată în variabila 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%
Al cincilea pas obține din fișier pom.xml versiunea și o setează în variabila Teamcity . Observați că versiunea din fișier TAG_FROM_VERSIONfără litera v înainte. Iar eticheta, bazată pe această versiune, deja cu litera v la început. pom.xml echo "Obține versiunea pachetului din 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']"
echo "Obține pachetul de versiune din 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']"
Pasul șase - etichetarea corectare de buguri versiuni. Aceasta se face cu ajutorul Maven cu opțiunea corespunzătoare în Obiectiv.
Opțiune Obiective:
-Dtag=%TAG_FROM_VERSION% scm:tag
Sursa: habr.com
