En esta publicación se describirá la configuración de la automatización de HotFix en proyectos Maven utilizando Teamcity.
Para realizar un HotFix, normalmente se hacen muchas acciones manuales:
- Crear una rama para la versión a la que deseas aplicar el HotFix.
- Corregir el error en la versión.
- Modificar la versión de bugfix en la rama de lanzamiento.
- Lanzar la etiqueta de la versión de bugfix.
Los puntos 1, 3 y 4 se pueden automatizar.
Antes de entrar en el tema, me gustaría tocar un tema importante y complejo — versionado semántico del software. Una breve explicación sobre Semver se puede entender en esta captura de pantalla. 
Puedes leer más en el siguiente enlace: .
Todos los ajustes descritos en esta publicación se basan en y .
En el Desarrollo Basado en Trunk, para cada lanzamiento se debe crear su propia rama. Todos los cambios (hotfix) para este lanzamiento se comprometen en esta rama.
En esta publicación automatizaremos las siguientes cosas:
Construcción CI
Creación de un nuevo lanzamiento
Creación de una rama para el lanzamiento
Modificación de la versión de bugfix

Requisitos:
- Repositorio Git para almacenar tu código. Se utilizará el repositorio .
- Servidor y agente de Teamcity. Puedes levantar tu servidor y agente local de Teamcity con
- Donde tengas el agente de Teamcity, deben estar instalados java, maven, git.
Creamos en Teamcity el proyecto "Automation Maven Hotfix" y allí creamos 4 tareas.
CI Build (Construcción CI)
Crear rama para el lanzamiento (Creación de la rama para el lanzamiento)
Maven increment bugfix (Modificación de la versión de bugfix)
Maven release (Creación de un nuevo lanzamiento)
Captura de pantalla del proyecto:

Configuraciones generales
En todas las tareas es necesario marcar la casilla "Clean build: Eliminar todos los archivos en el directorio de checkout antes de la construcción«, ya que al no tener esta casilla marcada, me aparecían errores.
Creamos un único VCS. Las características del VCS están rodeadas en rojo.

Normalmente el VCS utiliza el esquema HTTPS. En Especificación de la rama: se indica que se deben mirar todas las ramas y todas las etiquetas:
+:refs/heads/*
+:refs/tags/*Es necesario crear 4 Parámetros de Configuración.
- BRANCH_FOR_INCREMENT
- TAG_FROM_VERSION
- TEAM_USER
- TEAM_USER_EMAIL
El campo value en BRANCH_FOR_INCREMENT y TAG_FROM_VERSION debe dejarse vacío.

Es necesario cargar/agregar una clave privada. En todas las tareas excepto CI Build se necesita la clave privada.

En cada tarea excepto CI Build, en la sección de Características de Construcción, se debe conectar la clave privada.
Ejemplo para Maven release.

CI Build**.
En la tarea CI Build solo hay un paso mvn clean test

Maven release.
En la tarea Maven release. 2 pasos. El primer paso verifica que la rama sea master. Si la rama no es master, la tarea falla.
BRANCH=$(git branch | grep * | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" != "master" ]]; then
echo 'La rama no es master';
echo 'Aborting';
exit 1;
fi
El segundo paso es estándar mvn release:prepare con la opción —modo por lotes

Crear rama para la versión
Para crear un hotfix para la versión, es necesario crear una rama. Esto es manejado por la tarea Crear rama para la versión. Tiene 2 pasos.
El primer paso verifica que la rama no master, y el segundo verifica que la versión en el archivo pom.xml no contenga la palabra SNAPSHOT
BRANCH=$(git branch | grep * | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" == "master" ]]; then
echo 'La rama es master';
echo 'Abortando';
exit 1;
fi
echo "Obteniendo versión del paquete de 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 "Verificando SNAPSHOT"
if [[ $version == "*SNAPSHOT*" ]]; then
echo "******************* ADVERTENCIA *************************"
echo "************ Estás creando una rama para SNAPSHOTS ******************"
echo "***********************************************************"
exit 1
fi
El segundo paso cambia en developerConnection el esquema de conexión de 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
Maven increment bugfix
La tarea consiste en 6 partes. Se podría haber refactorizado, pero así funciona.
El primer paso es verificar que la rama no master. Si la rama master la tarea falla.
BRANCH=$(git branch | grep * | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" == "master" ]]; then
echo 'La rama es master';
echo 'Abortando';
exit 1;
fi
# Aquí obtenemos la versión del archivo pom.xml
echo "Obteniendo versión del paquete de 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)"`
# Se tiene que hacer checkout en la rama correcta.
# De lo contrario, git status muestra detached en la rama correcta.
# Es necesario que git status muestre simplemente la rama
git checkout $BRANCH
# Exportamos la variable bash a la variable de Teamcity para su uso posterior.
echo "##teamcity[setParameter name='BRANCH_FOR_INCREMENT' value='$BRANCH']"
El segundo paso de Maven es cambiar la versión bugfix en el archivo pom.xml.
Objetivos: en maven todo en una línea
build-helper:parse-version versions:set -DnewVersion=${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.nextIncrementalVersion} versions:commit
El tercer paso es mostrar información sobre el estado de Git y otros:
echo 'cat pom.xml'
cat pom.xml
echo 'git status'
git status
echo 'git remote -v'
git remote -v
echo 'git branch'
git branch
El cuarto paso cambia en developerConnection el esquema de conexión de HTTPS a GIT.
Y empuja los cambios a la rama indicada en la variable de 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%
El quinto paso obtiene del archivo pom.xml la versión y la establece en Teamcity variable TAG_FROM_VERSION. Tenga en cuenta que la versión del archivo pom.xml no tiene la letra v al principio. Y la etiqueta, basada en esta versión, ya tiene la letra v al inicio.
echo "Obteniendo versión del paquete de 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']"
El sexto paso es etiquetar bugfix versiones. Esto se hace con la Maven con la opción adecuada en Objetivo.
La opción Objetivos:
-Dtag=%TAG_FROM_VERSION% scm:tag
Fuente: habr.com
