Автоматизация HotFix в Maven проектах с использованием TeamCity

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

В этом посте будет описана настройка автоматизации HotFix в Maven проектах с использованием Teamcity.


Чтобы сделать HotFix обычно делается много ручных действий:
1) Создать бранч для релиза, на который вы хотите выкатывать HotFix
2) Исправить ошибку в релизе
3) Измененить bugfix версию в релизном бранче
4) Выкатить тег bugfix версии


Пункты 1,3,4 можно автоматизировать.


Перед тем как перейдем к теме, хочется затронуть важную и сложную тему — версионирования программного обеспечения. Кратко о Semver можно понять на этом скриншоте.


Подробнее можно прочитать по ссылке: 1.


Все настройки описанные в этом посте опираются на Semver и Trunk-Based Development.


В Trunk-Based Development для каждого релиза нужно создать свой бранч. Все изменения (hotfix) в рамках этого релиза коммитятся в этот бранч.


В рамках этого поста автоматизируем следующие вещи:


  • CI сборка


  • Создание нового релиза


  • Создание бранча для релиза


  • Изменение bugfix версии




Требования:


  • Git репозиторий для хранения вашего кода. В посте будет использоваться репозиторий https://gitlab.com/anton_patsev/automation-maven-hotfix.
  • Teamcity сервер и агент. Вы можете поднять свой локальный Teamcity сервер и агент с помощью docker-compose
  • Там где у вас Teamcity агент, должны быть установлены java, maven, git

Создадим в Teamcity проект "Automation Maven Hotfix" и создадим там 4 таски.


  • CI Build (CI сборка)


  • Create branch for release (Создание бранча для релиза)


  • Maven increment bugfix (Изменение bugfix версии))


  • Maven release (Создание нового релиза)



Скриншот проекта:



Общие настройки


Во всех тасках необходимо выставить галку "Clean build: Delete all files in the checkout directory before the build", так как при отстутствии этой галки у меня появлялись ошибки.


Создаем единственный VCS. Особенности VCS обведенны красным.



Обычно VCS испольуют схему HTTPS. В Branch specification: указано смотреть все бранчи и все теги:


+:refs/heads/*
+:refs/tags/*

Необходимо создать 4 Configuration Parameters.


  • 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 'Branch is not master';
  echo 'Aborting';
  exit 1;
fi


Второй шаг это стандартный mvn release:prepare c опцией --batch-mode



Create branch for release


Чтобы создать hotfix для релиза нужно создать бранч. Этим занимается таска Create branch for release. У нее 2 шага.


Первый шаг проверяет что бранч не master, и второе проверяет что версия в файле pom.xml не содержало слово SNAPSHOT


BRANCH=$(git branch | grep \* | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" == "master" ]]; then
  echo 'Branch is master';
  echo 'Aborting';
  exit 1;
fi

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 "Check SNAPSHOT"
if [[ $version == "*SNAPSHOT*" ]]; then
    echo "******************* W A R N I N G *************************"
    echo "************ You are create branch for 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 increment bugfix


Таска состоит из 6 частей. Можно было отрефакторить, но и так работает.


Первый шаг — проверка что бранч не master. Если бранч master таска падает.


BRANCH=$(git branch | grep \* | cut -d ' ' -f2)
echo "$BRANCH"
if [[ "$BRANCH" == "master" ]]; then
  echo 'Branch is master';
  echo 'Aborting';
  exit 1;
fi

# Здесь получаем версию из файла pom.xml
echo "Get version package from 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.


Goals: у maven все одной строкой


build-helper:parse-version versions:set -DnewVersion=${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.nextIncrementalVersion} versions:commit


Третий шаг — вывод информации Git status и другие:


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 "Get version package from 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 с нужной опцией в Goal.


Опция Goals:


-Dtag=%TAG_FROM_VERSION% scm:tag

Источник: https://habr.com/ru/post/483242/


Интересные статьи

Интересные статьи

Всем доброго здравия! В преддверии Нового года хочу продолжить рассказывать про использование С++ на микроконтроллерах, на этот раз попытаюсь рассказать про использование шаблона Наблюдатель (...
Сейчас многие команды систематизируют дизайн своих приложений. Мы решили пойти дальше и автоматизировать синхронизацию кода с нашей библиотекой компонентов.  Дело в том, что в hh для проектиро...
Предисловие У меня дома есть пара комплектов хороших советских акустических систем. Но техника эта довольная старая и просто не может включаться с пульта или автоматически, а постоянно подходи...
Классическое PHP-приложение — однопоточность, тяжелая загрузка (если вы конечно не пишите на микрофреймворках) и неизбежная смерть процесса после каждого запроса… Такое приложение тяжелое и медле...
В «1С-Битрикс» считают: современный интернет-магазин должен быть визуально привлекательным, адаптированным для просмотра с мобильных устройств и максимально персонализированным с помощью технологии Бо...