Neste post, será descrita a configuração da automação de HotFix em projetos Maven utilizando o Teamcity.
Para fazer um HotFix, geralmente são necessárias muitas ações manuais:
- Criar um branch para a versão na qual você deseja implementar o HotFix
- Corrigir o erro na versão
- Alterar a versão bugfix no branch de lançamento
- Criar uma tag para a versão bugfix
Os itens 1, 3 e 4 podem ser automatizados.
Antes de avançarmos para o tema, gostaria de abordar uma questão importante e complexa — de versionamento software. Um resumo sobre Semver pode ser compreendido nesta captura de tela. 
Você pode ler mais através do link: .
Todas as configurações descritas neste post são baseadas em e .
No Desenvolvimento Baseado em Trunk, para cada versão, é necessário criar seu próprio branch. Todas as alterações (hotfix) dentro dessa versão são comitadas neste branch.
Neste post, vamos automatizar as seguintes coisas:
Build CI
Criação de um novo lançamento
Criação de um branch para a versão
Alteração da versão bugfix

Requisitos:
- Repositório Git para armazenar seu código. Neste post, será utilizado o repositório .
- Servidor e agente Teamcity. Você pode levantar seu próprio servidor e agente Teamcity localmente usando
- Onde você tem o agente Teamcity, devem estar instalados java, maven, git
Vamos criar no Teamcity o projeto "Automação Maven Hotfix" e lá criaremos 4 tarefas.
Build CI (Construção CI)
Criar branch para a versão (Criação de branch para o lançamento)
Maven incrementar bugfix (Alteração da versão bugfix)
Maven release (Criação de um novo lançamento)
Captura de tela do projeto:

Configurações gerais
Em todas as tarefas, é necessário marcar a opção "Limpar build: Deletar todos os arquivos no diretório de checkout antes da construção", pois na ausência dessa opção, erro apareceram.
Criamos um único VCS. As características do VCS estão destacadas em vermelho.

Normalmente, o VCS utiliza o esquema HTTPS. Em Especificação do branch: indica observar todos os branches e todas as tags:
+:refs/heads/*
+:refs/tags/*É necessário criar 4 Parâmetros de Configuração.
- BRANCH_FOR_INCREMENT
- TAG_FROM_VERSION
- TEAM_USER
- TEAM_USER_EMAIL
O campo value em BRANCH_FOR_INCREMENT e TAG_FROM_VERSION deve permanecer vazio.

É necessário carregar/adicionar uma chave privada. Em todas as tarefas, exceto na Build CI, a chave privada é necessária.

Em cada tarefa, exceto na Build CI, na seção Recursos de Construção, você deve conectar a chave privada.
Exemplo para Maven release.

Build CI.
Na tarefa Build CI, há apenas um passo mvn clean test

Maven release.
Na tarefa Maven release. 2 passos. O primeiro passo verifica se o branch é master. Se o branch não for master, a tarefa falha.
BRANCH=$(git branch | grep * | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" != "master" ]]; then
echo 'O branch não é master';
echo 'Abortando';
exit 1;
fi
O segundo passo é o padrão mvn release:prepare com a opção modo-batch

Criar ramificação para o lançamento
Para criar um hotfix para o lançamento, é necessário criar uma ramificação. Isso é feito pela tarefa Criar ramificação para o lançamento. Ela tem 2 etapas.
A primeira etapa verifica se a ramificação não master, e a segunda verifica se a versão no arquivo pom.xml não contém a palavra SNAPSHOT
BRANCH=$(git branch | grep * | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" == "master" ]]; then
echo 'A ramificação é a master';
echo 'Abortando';
exit 1;
fi
echo "Obter versão do pacote a partir do 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 "Verificar SNAPSHOT"
if [[ $version == "*SNAPSHOT*" ]]; then
echo "******************* A L E R T A *************************"
echo "************ Você está criando uma ramificação para SNAPSHOTS ******************"
echo "***********************************************************"
exit 1
fi
A segunda etapa altera no developerConnection o esquema de conexão de HTTPS para 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
Correção de bug de incremento do Maven
A tarefa consiste em 6 partes. Poderia ter sido refatorada, mas assim funciona.
A primeira etapa é verificar se a ramificação não master. Se a ramificação master a tarefa falha.
BRANCH=$(git branch | grep * | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" == "master" ]]; then
echo 'A ramificação é a master';
echo 'Abortando';
exit 1;
fi
# Aqui obtemos a versão do arquivo pom.xml
echo "Obter versão do pacote a partir do 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)"`
# É necessário fazer checkout na ramificação desejada.
# Caso contrário, o git status mostrará detached na ramificação desejada.
# Precisamos que o git status mostre apenas a ramificação
git checkout $BRANCH
# Exportamos a variável bash na variável Teamcity para uso posterior.
echo "##teamcity[setParameter name='BRANCH_FOR_INCREMENT' value='$BRANCH']"
A segunda etapa do Maven altera a versão bugfix no arquivo pom.xml.
Objetivos: no maven tudo em uma linha
build-helper:parse-version versions:set -DnewVersion=${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.nextIncrementalVersion} versions:commit
A terceira etapa é exibir informações do Git status e outras:
echo 'cat pom.xml'
cat pom.xml
echo 'git status'
git status
echo 'git remote -v'
git remote -v
echo 'git branch'
git branch
A quarta etapa altera no developerConnection o esquema de conexão de HTTPS para GIT.
E faz push das alterações na ramificação especificada na variável 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%
A quinta etapa obtém do arquivo pom.xml a versão e a define em Teamcity a variável TAG_FROM_VERSION. Observe que a versão do arquivo pom.xml não possui a letra v à frente. E a tag, com base nessa versão, já tem a letra v no início.
echo "Obter versão do pacote a partir do 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']"
A sexta etapa é a tagueação bugfix da versão. Isso é feito com Maven com a opção desejada em Objetivo.
Opção Objetivos:
-Dtag=%TAG_FROM_VERSION% scm:tag
Fonte: habr.com
