Рубрики
Uncategorized

Реализация модели выпуска GIT-потока в процессе непрерывного интеграции

Возможно, большинство разработчиков знакомы с моделью GIT-потока, которая делает контроль процесса выпуска. В этой статье вы узнаете один из подходов для внесения выпуска GIT-потока в ваш проект, который может быть интегрирован с постоянным инструментом для интеграции по вашему выбору (например, Atlassian Bamboo.)

Автор оригинала: Vyacheslav.

Вступление

Возможно, большинство разработчиков знакомы с моделью GIT-потока, которая делает контроль процесса выпуска. В этой статье я продемонстрирую один из подходов для внесения выпуска GIT-потока в ваш проект, и этот поток GIT может быть интегрирован с постоянным инструментом непрерывного интеграции на ваш выбор. В этой статье я буду использовать Atlassian Bamboo в качестве примера.

Фон

Если вы никогда не слышали о GIT-потоке ранее, я предлагаю вам изучить классический пост ( http://nvie.com/posts/a-successful-git-branching-model/ ) & Как Atlassian интерпретирует ту же идею ( https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow ).

Для тех, кто уже знает поток Git, позвольте мне напомнить вам о этой известной диаграмме:

диаграмма

Реализация — инструменты

Обычно я вводю подход с набором файловых помощников, которые мигрируют и развиваются с каждым последующим проектом. Я поддерживаю идею, что инфраструктура кода должна храниться рядом с кодом проекта. Таким образом, у меня обычно есть папка развертывания, где живут сценарии DEVOPS (обычно я использую непрерывный инструмент, хотя у меня был опыт работы с развертыванием шеф-поваров), и предположим, что разработчики предоставит мне логику сборки, которая выводит целевые файлы артефакта под Buiild/папку. В результате типичные DevOps Magic Stright выглядит как:

|-- build
|-- deployment
|   |-- release_finish.sh
|   |-- release_finish_bamboo.sh
|   |-- release_start.sh
|   `-- release_start_bamboo.sh
|-- bump-version-drynext.sh
|-- bump-version.sh
|-- package.sh
|-- unpackage.sh
`-- version.txt

Давайте посмотрим на содержимое файлов и целей.

version.txt.

Простой текстовый файл, содержащий текущую версию проекта. Мне нравится идея с метками Git в Git-потоке, но действительно предпочла бы иметь возможность контролировать версию самостоятельно. Типичная версия Пример — x.y.z:

0.0.1

bump-version-drynext.sh

В большинстве сценариев непрерывной интеграции последующие выпуски меняют только второстепенную версию. Благодаря удобному сценарию Bash зачисляется в источнике, мы можем получить значение следующей второстепенной версии через

➜  releasing  ./bump-version-drynext.sh
0.0.2

Логика достаточно проста — мы читаем текущую версию от Version.txt и примените магию оболочки, чтобы получить следующее значение.

#!/bin/bash

# credits: http://stackoverflow.com/questions/8653126/how-to-increment-version-number-in-a-shell-script

increment_version ()
{
  declare -a part=( ${1//\./ } )
  declare    new
  declare -i carry=1

  for (( CNTR=${#part[@]}-1; CNTR>=0; CNTR-=1 )); do
    len=${#part[CNTR]}
    new=$((part[CNTR]+carry))
    [ ${#new} -gt $len ] && carry=1 || carry=0
    [ $CNTR -gt 0 ] && part[CNTR]=${new: -len} || part[CNTR]=${new}
  done
  new="${part[*]}"
  echo -e "${new// /.}"
}


VERSION=`cat version.txt`

increment_version $VERSION

bump-version.sh

Это очень важный файл. Обычно я предпочитаю версию приложения в моих файлах проекта (например Bower.json , Package.json ), чтобы соответствовать текущей версии проекта. Это место, где может быть реализован исправления.

Какой код делает — это применяет параметр версии для файлов, и записывает новый в Version.txt

#!/bin/bash

set -e

CURRENT_DIR=`pwd`
VERSION=$1

echo $VERSION > version.txt

#Optionally - Update your app version in app files, like package.json, bower.json , etc
# Example for nodejs package.json:

#sed -i.bak "s/[[:space:]]*\"version\"[[:space:]]*:[[:space:]]*\".*\",/  \"version\":\"$VERSION\",/g" $CURRENT_DIR/package.json
#rm $CURRENT_DIR/package.json.bak || true

package.sh

Эта логика позволяет создавать файл артефакта TGZ-IPPED либо в форме Project-name-version.tgz или в форме Project-name-version-buildnumber.tgz ; Последний случай может быть важен, если вам нужно хранить историю артефактов для каждой сборки.

Ваш файл можно отрегулировать, изменив переменную проекта, чтобы соответствовать имени вашего проекта. Кроме того, если вы когда-нибудь хотели узнать больше информации о Artifact, IT Packs Version.txt файл, который содержит всю информацию о major_version , minal_version , git_hash. и Созданная дата . С этой информацией вы можете определить коммит, который использовался для создания сборки.

Кроме того, такие файлы могут быть легко прочитаны серверами сборки, такие как Bamboo или Jenkins и преобразованы во внутренние переменные.

Полученные файлы будут размещены в сборке/и упакован.

#!/bin/sh
if [ -z "$1" ]
then
  SUFFIX=""
else
  SUFFIX="-$1"
fi

PROJECT=project-name

rm -rf ./build || true
rm ${PROJECT}-*.tgz || true
mkdir -p ./build || true

VERSION=`cat version.txt`
GITCOMMIT=`git rev-parse --short HEAD`
DATE=`date +%Y-%m-%d:%H:%M:%S`

# do build here, that produces necessary files for artifact under build/ folder

echo "major_version=$VERSION" > build/version.txt
echo "minor_version=$1" >> build/version.txt
echo "git_hash=$GITCOMMIT" >> build/version.txt
echo "built=$DATE" >> build/version.txt

echo PRODUCING ARTIFACT $PROJECT-$VERSION$SUFFIX.tgz  in build/
tar cfz  $PROJECT-$VERSION$SUFFIX.tgz build

Unpackage.sh

Этот файл обычно выполняется на следующем шаге во время вашего процесса сборки, где артефакт ранее был упакован на шаг сборки, и теперь вам нужно сделать что-то с контентом, например, инициировать развертывание. В 100% сценариях я ожидал только один артефактный файл, но если есть несколько версий, я выбираю только самый последний.

В результате вы будете распаковывать артефакт в папке сборки.

#!/bin/sh
PROJECT=project-name
rm -rf ./build || true
current_artefact=$(find ./${PROJECT}*.tgz -type f -exec stat -c "%n" {} + | sort -r | head -n1)
echo Working with artefact: $current_artefact
tar xvzf $current_artefact
echo artefact unpacked: $current_artefact

Развертывание/Release_Start.sh.

Это создает релиз и толкает ветку выпуска на сервер, чтобы инструмент непрерывной интеграции может забрать его и построить его.

Я должен сказать, что здесь присутствует некоторая часть Святой войны: когда вытащить версию.

У меня были два типа клиентов: начнут клиента настаивает на том, что version.txt содержит версию, которую он собирается выпустить, при этом, как только я начну процесс выпуска, я должен немедленно поднять версию в разработке, поскольку все новые функции будут принадлежать Следующий выпуск.

С другой стороны, клиент-конец обычно не заботится о Version.txt, и на его понимание, наталкивая версию — это последний шаг в выпуске — то есть, после этого толкать, все, что было зачислено ранее, было 0,01 постоянного развития И теперь мы выпустили 0.0.2.

Я бы предпочел поднять версию в конце. Как вы видите, оба подхода поддерживаются с помощью комментирования литлов.

This batch implements release start by either providing new release version as a parameter, or getting the one from version.txt

#!/bin/sh

cd ${PWD}/../
VERSION=$1
if [ -z $1 ]
then
  VERSION=`cat version.txt`
fi

#Initialize gitflow
git flow init -f -d

# ensure you are on latest develop  & master
git checkout develop
git pull origin develop
git checkout -

git checkout master
git pull origin master
git checkout develop

git flow release start $VERSION

# bump released version to server
git push

git checkout develop

# COMMENT LINES BELOW IF YOU BUMP VERSION AT THE END
NEXTVERSION=`./bump-version-drynext.sh`
./bump-version.sh $NEXTVERSION
git commit -am "Bumps version to $NEXTVERSION"
git push origin develop

Развертывание/Release_finish.sh.

К счастью, этот шаг не требует никаких внешних параметров. Текущая версия выпуска обнаруживаются от имени ветви (релиз/0.0.2) и остальных шаги очевидны. Опять здесь, если вы будете следовать классическому подходу на версию Classic — вам нужно будет растреметься ./bump-version.sh $ releasetag

#!/bin/sh

cd ${PWD}/../

# PREVENT INTERACTIVE MERGE MESSAGE PROMPT AT A FINAL STEP
GIT_MERGE_AUTOEDIT=no
export GIT_MERGE_AUTOEDIT

GITBRANCHFULL=`git rev-parse --abbrev-ref HEAD`
GITBRANCH=`echo "$GITBRANCHFULL" | cut -d "/" -f 1`
RELEASETAG=`echo "$GITBRANCHFULL" | cut -d "/" -f 2`

echo $GITBRANCH
echo $RELEASETAG

if [ $GITBRANCH != "release" ] ; then
   echo "Release can be finished only on release branch!"
   return 1
fi

if [ -z $RELEASETAG ]
then
  echo We expect gitflow to be followed, make sure release branch called release/x.x.x
  exit 1
fi

#Initialize gitflow
git flow init -f -d

# ensure you are on latest develop  & master and return back
git checkout develop
git pull origin develop
git checkout -

git checkout master
git pull origin master
git checkout -

# UNCOMMENT THESE TWO LINES IF YOU BUMP VERSION AT THE END
#./bump-version.sh $RELEASETAG
#git commit -am "Bumps version to $RELEASETAG"

git flow release finish -m "release $RELEASETAG" $RELEASETAG

git push origin develop && git push origin master --tags

Связывание к серверу сборки

Все популярные серверы Build Build поддерживают филиал обнаружения и строительство. Например, Atlassian Bamboo имеет это легко настраиваемо через интерфейс UI, в то время как, например, в Jenkins вам нужно будет играть больше.

Процесс на сервере сборки может быть реализован таким образом, чтобы вы инициируете выпуск из разрабатывающего ветви, используя дополнительный шаг по сборке:

И ввести возможность доработки выпуска в качестве необязательного шага на ветке выпуска:

Если вы попытаетесь использовать рецепты без корректировок, вы попадете в беду. Практически любой сервер сборки для преимуществ скорости и размера не проверяет полную историю хранилища, поэтому шаги потерпят неудачу.

Для бамбука можно представить следующий «взлом»: мы вручную устанавливаем новый пульт дистанционного управления, с помощью команды Git Remote Добавить центральный «$ Git_Remote» И все последующие операции реализуются с пользовательским удаленным.

Развертывание/RELEAL_START_BAMBOO.SH.

Пожалуйста, найдите ниже слегка модифицированного Release_Start для бамбука:

#!/bin/sh

cd ${PWD}/../

VERSION=$1
if [ -z $1 ]
then
  VERSION=`cat version.txt`
fi

# PREVENT INTERACTIVE MERGE MESSAGE PROMPT
GIT_MERGE_AUTOEDIT=no
export GIT_MERGE_AUTOEDIT
GIT_REMOTE=git@github.com:Voronenko/gitflow-release.git

# add remote due to bamboo git cache shit
git remote add central "$GIT_REMOTE"

#Initialize gitflow
git flow init -f -d

# ensure you are on latest develop  & master
git checkout develop
git pull central develop
git checkout -

git checkout master
git pull central master
git checkout develop

git flow release start $VERSION

# bump released version to server
git push central release/$VERSION

git checkout develop

# COMMENT LINES BELOW IF YOU BUMP VERSION AT THE END
NEXTVERSION=`./bump-version-drynext.sh`
./bump-version.sh $NEXTVERSION
git commit -am "Bumps version to $NEXTVERSION"
git push central develop

Развертывание/Release_finish_bamboo.sh.

#!/bin/sh

# IMPORTANT - THIS FILE IS INTENDED TO BE EXECUTED ONLY IN BAMBOO ENVIRONMENT

cd ${PWD}/../

# PREVENT INTERACTIVE MERGE MESSAGE PROMPT AT A FINAL STEP
GIT_MERGE_AUTOEDIT=no
export GIT_MERGE_AUTOEDIT

GITBRANCHFULL=`git rev-parse --abbrev-ref HEAD`
GITBRANCH=`echo "$GITBRANCHFULL" | cut -d "/" -f 1`
RELEASETAG=`echo "$GITBRANCHFULL" | cut -d "/" -f 2`
GIT_REMOTE=git@github.com:Voronenko/gitflow-release.git

echo $GITBRANCH
echo $RELEASETAG

if [ $GITBRANCH != "release" ] ; then
   echo "Release can be finished only on release branch!"
   return 1
fi

if [ -z $RELEASETAG ]
then
  echo We expect gitflow to be followed, make sure release branch called release/x.x.x.x
  exit 1
fi

# add remote due to bamboo git cache shit
git remote add central "$GIT_REMOTE"

#Initialize gitflow
git flow init -f -d

# ensure you are on latest develop  & master and return back
git checkout develop
git pull central develop
git checkout -

git checkout master
git pull central master
git checkout -

# UNCOMMENT THESE TWO LINES IF YOU BUMP VERSION AT THE END
#./bump-version.sh $RELEASETAG
#git commit -am "Bumps version to $RELEASETAG"

git flow release finish -m "release $RELEASETAG" $RELEASETAG

git push central develop && git push central master --tags

Точки интереса

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

Упомянутые образцы можно увидеть или разведать из https://github.com/voronenko/gitflow-release

Оригинал: «https://www.codementor.io/@slavko/implementing-git-flow-releasing-model-in-continuous-integration-process-du1083k06»