TeamCity Rollback (REST API)

TeamCity build for version(release) rolling back

more info for money

Как часто случается, что выкат новой версии прошел не совсем гладко и нужно срочно откатить изменения? Сколько ручной работы нужно сделать? А точно ли ваши сотрудники знают наверняка, что все делается верно, особенно в суматохе, когда сервис лежит и нужно срочно возвращаться на стабильную версию?

В этой статье я опишу основные принципы построения успешного скрипта (teamcity build), который обратит изменения до последней успешной версии.

Дисклеймер: все на bash костылях, как-то не пришлось переписать, да и работало отлично, не судите строго за bash. Также, этот механизм легко можно прицепить на триггер ‘if build failure’, чтобы сразу после неудачи запускался откат. Но в большинстве случаев хватает и ручного запуска rollback.
+ стоит не забывать, что откат будет только на код приложения, файлы или конфиги, но в большинстве случаев, database rollback не случится, если были изменения в базе, они там и останутся. Если только ваши сборки не выкатывают полные database dump при каждом релизе.

Дано:

  • билд для выката приложения
  • билд для автоматической сборки пакета
  • TeamCity Version 2017.1.2 (build 46812)

Концепция:

  • собрать пакет последней успешной версии
  • запустить билд выката приложения с конкретной ревизией ( Run -> Custom Build -> Include changes )

Входные данные:

apiURL=»http://teamcity.domain.com/app/rest»
buildID=»BuildDocker_BuildDevDefault»
autoBuildID=»AutoBuildDocker_BuildDevTesting»

С этим все понятно, Id сборок — это Build configuration ID из Build Settings


allSuccessBuildRevision=()
IFS=' ' read -r -a allSuccessBuildID <<< $(curl --user $user:$pass --silent $apiURL/builds/?locator=status:SUCCESS,state:finished,buildType:$buildID | grep -Po '(?<=build id=)[^\s]*' | grep -o '[0-9a-z]*')
currentBuildID=$(curl --user $user:$pass --silent $apiURL/builds/?locator=buildType:$buildID | grep -Po '(?<=build id=)[^\s]*' | grep -o '[0-9a-z]*' | head -n1)

Собираем Id последних успешных релизов (Id успешных деплоев сборки, ну путать с Id сборки)
И берем Id последнего выката, который мы собрались откатывать.

Далее собираем все номера успешных ревизий (revision)
И ревизию последнего деплоя, который будем откатывать.

i=0
for ID in ${allSuccessBuildID[@]}; do
allSuccessBuildRevision[i]=$(curl --user $user:$pass --silent --silent $apiURL/builds/$ID | grep -Po '(?<=version=)[^\s]*' | sed -n 2p | sed 's/\"//g')
# printf "${allSuccessBuildID[i]} - ${allSuccessBuildRevision[i]} \n"
((i++))
done
currentBuildRevision=$(curl --user $user:$pass --silent --silent $apiURL/builds/$currentBuildID | grep -Po '(?<=version=)[^\s]*' | sed -n 2p | sed 's/\"//g')

Далее дергаем из списка успешных ревизий самую последнюю и сравниваем с текущей. Так мы проверяем, что предыдущий деплой был успешным и нам нужно откатываться на него.
Если и предыдущий релиз был Failure, значит берем следующий предыдущий и так далее назад по списку, пока не найдем last success revision
lastSuccessBuildRevision=${allSuccessBuildRevision[0]}
echo "Current build revision $currentBuildRevision"
echo "Last Success build revision: $lastSuccessBuildRevision"

if [ $currentBuildRevision != $lastSuccessBuildRevision ]; then
echo «Current $currentBuildRevision not last success, Run != $lastSuccessBuildRevision »
else
i=0
while [[ $currentBuildRevision == $lastSuccessBuildRevision ]]; do
lastSuccessBuildRevision=${allSuccessBuildRevision[i]}
lastSuccessBuildID=${allSuccessBuildID[i]}
((i++))
done
echo «Run $lastSuccessBuildRevision»
fi

Окей, у нас есть номер ревизии, до которой следует откатиться. Но чтобы запустить выкат через API, необходимо узнать ChangeId этого RevisionId (а кто сказал что будет просто)

lastSuccessChangeId=$(curl --user $user:$pass --silent $apiURL/builds/$lastSuccessBuildID | grep -Po '(?<=change id=)[^\s]*' | grep -o '[0-9]*')
echo "lastSuccessChangeId=$lastSuccessChangeId ; revision=$lastSuccessBuildRevision"

Теперь все готово к выкату. Остается только проверить, есть ли в artifactory собранный пакет для последней успешной ревизии.
Если пакета нет, запускаем сборку автобилда и ждем ее окончания.

Если пакет все еще существует, остается просто запустить наш release build, использовав $buildID и $lastSuccessChangeId


 

Очень хочется увидеть целостный скрипт с запуском автобилда, ожиданием его завершения, запуском релиза и его ожиданием + тоже самое в формате teamcity?

Все в ваших руках
Master Card

Yandex.Money

____

Join to my channel https://t.me/ithangouts

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *