In questo post descriveremo la configurazione dell'automazione HotFix nei progetti Maven utilizzando Teamcity.
Per effettuare un HotFix solitamente è necessario compiere molte azioni manuali:
- Creare un branch per la release su cui si desidera applicare HotFix
- Correggere l'errore nella release
- Modificare la versione bugfix nel branch di release
- Pubblicare il tag della versione bugfix
I punti 1, 3 e 4 possono essere automatizzati.
Prima di passare all'argomento, è importante toccare un tema significativo e complesso — versionato del software. Brevemente, Semver può essere compreso da questo screenshot. 
Puoi leggere di più al link: .
Tutte le configurazioni descritte in questo post si basano su e .
Nel Sviluppo basato su trunk per ogni release è necessario creare il proprio branch. Tutte le modifiche (hotfix) relative a questa release vengono committate in questo branch.
In questo post automatizzeremo le seguenti attività:
Build CI
Creazione di una nuova release
Creazione di un branch per la release
Modifica della versione bugfix

Requisiti:
- Repository Git per conservare il tuo codice. In questo post utilizzeremo il repository .
- Server e agenti Teamcity. Puoi avviare il tuo server e agente Teamcity locale usando
- Dove hai l'agente Teamcity, devono essere installati java, maven, git
Creeremo in Teamcity il progetto "Automation Maven Hotfix" e al suo interno creeremo 4 task.
Build CI (CI Build)
Crea branch per la release (Create branch for release)
Incremento bugfix Maven (Maven increment bugfix)
Rilascio Maven (Maven release)
Screenshot del progetto:

Impostazioni generali
In tutti i task è necessario selezionare la casella "Clean build: Elimina tutti i file nella directory di checkout prima della build", poiché in assenza di questa casella ho riscontrato errori.
Creiamo un'unica VCS. Le peculiarità della VCS sono cerchiate in rosso.

Di solito la VCS utilizza lo schema HTTPS. In Specifica branch: è indicato di controllare tutti i branch e tutti i tag:
+:refs/heads/*
+:refs/tags/*È necessario creare 4 Parametri di Configurazione.
- BRANCH_FOR_INCREMENT
- TAG_FROM_VERSION
- TEAM_USER
- TEAM_USER_EMAIL
Il campo value in BRANCH_FOR_INCREMENT e TAG_FROM_VERSION deve rimanere vuoto.

È necessario caricare/aggiungere una chiave privata. In tutti i task tranne il CI Build è necessaria la chiave privata.

In ogni task tranne il CI Build, nella sezione Funzionalità Build, è necessario collegare la chiave privata.
Esempio per Rilascio Maven

Build CI.
Nel task Build CI c'è solo un passo mvn clean test

Rilascio Maven
Nel task Rilascio Maven 2 passi. Il primo passo verifica che il branch sia master. Se il branch non è master, il task fallisce.
BRANCH=$(git branch | grep * | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" != "master" ]]; then
echo 'Branch is not master';
echo 'Aborting';
exit 1;
fi
Il secondo passo è il standard mvn release:prepare con opzione modalità-batch

Crea ramo per il rilascio
Per creare un hotfix per il rilascio è necessario creare un ramo. Questo è compito della task Crea ramo per il rilascio. Ha 2 fasi.
La prima fase verifica che il ramo non sia master, e la seconda verifica che la versione nel file pom.xml non contenga la parola SNAPSHOT
BRANCH=$(git branch | grep * | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" == "master" ]]; then
echo 'Il ramo è master';
echo 'Interruzione';
exit 1;
fi
echo "Ottieni versione pacchetto da 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 "Controlla SNAPSHOT"
if [[ $version == "*SNAPSHOT*" ]]; then
echo "******************* W A R N I N G *************************"
echo "************ Stai creando un ramo per SNAPSHOTS ******************"
echo "***********************************************************"
exit 1
fi
La seconda fase modifica il developerConnection cambiando il protocollo di connessione da HTTPS a 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
Bugfix di incremento Maven
La task è composta da 6 parti. Si poteva rifattorizzare, ma funziona anche così.
La prima fase — verifica che il ramo non sia master. Se il ramo master la task fallisce.
BRANCH=$(git branch | grep * | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" == "master" ]]; then
echo 'Il ramo è master';
echo 'Interruzione';
exit 1;
fi
# Qui otteniamo la versione dal file pom.xml
echo "Ottieni versione pacchetto da 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)"`
# È necessario eseguire checkout sul ramo richiesto.
# Altrimenti git status mostra detached al ramo richiesto.
# È necessario che git status mostri semplicemente il ramo
git checkout $BRANCH
# Esportiamo la variabile bash in una variabile Teamcity per uso futuro.
echo "##teamcity[setParameter name='BRANCH_FOR_INCREMENT' value='$BRANCH']"
La seconda fase Maven modifica la versione bugfix nel file pom.xml.
Obiettivi: in maven tutto è su una sola riga
build-helper:parse-version versions:set -DnewVersion=${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.nextIncrementalVersion} versions:commit
La terza fase — visualizzazione delle informazioni con Git status e altro:
echo 'cat pom.xml'
cat pom.xml
echo 'git status'
git status
echo 'git remote -v'
git remote -v
echo 'git branch'
git branch
La quarta fase modifica il developerConnection cambiando il protocollo di connessione da HTTPS a GIT.
E invia le modifiche al ramo specificato nella variabile 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%
La quinta fase ottiene dal file pom.xml la versione e la imposta in Teamcity variabile TAG_FROM_VERSION. Nota che la versione dal file pom.xml senza la lettera v davanti. Mentre il tag, basato su questa versione, inizia già con la lettera v.
echo "Ottieni versione pacchetto da 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']"
La sesta fase — tagging bugfix della versione. Questo è fatto con Maven con l'opzione corretta in Obiettivo.
Opzione Goals:
-Dtag=%TAG_FROM_VERSION% scm:tag
Fonte: habr.com
