Автор оригинала: 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»