Не так давно Appveyor добавили поддержку Linux агентов сборки, а это значит, что пришло новое счастье для множества open source проектов. Ведь раньше для сборки проекта под Linux необходимо было использовать что-то другое, например Travis CI, и выглядело это все как-то так:
И все бы хорошо, но скорость Travis CI для открытых проектов оставляет желать лучшего. Сейчас же мы можем построить полный цикл неприрывной интеграции (CI) на Appveyor. Я хочу рассказать, как настроить сборку docker образа, публикацию образа в репозиторий, а так же запуск скрипта для обновления docker контейнеров. Все примеры подразумевают использование open source проектов и не требуют оформления подписки. Если интересно, как скрыть приватные файлы конфигураций в открытом проекте, а так же не иметь проблем с доступом к этим файлам уже в docker контейнере, пишите комментарии, опишу отдельно этот вопрос.
Appveyor поддерживает конфигурацию в 2х режимах - через визуальную админ часть или через конфигурационные файлы *.yml. Оба подхода имеют одну и ту же суть, разница в том, что админ часть создает конфигурационный файл на сервере и после использует его, а ручной вы можете создать в любом текстовом редакторе и использовать его, храня у себя в исходном коде. По умолчанию используется серверная конфигурация, но если добавить конфигурационный файл в репозиторий вашего проекта, то будет использоваться он. Я покажу всю настройку на примере собственного файла. В качестве подопытного выступает непосредственно этот блог. Для него сформирована следующая конфигурация:
# Версия, которая будет присваиваться каждой сборке. Переменная build - инкремент номера сбороки.
version: 1.0.0.{build}
# Образ виртуальной машины на которой будет происходить сборка.
image: ubuntu
# Глубина клонирования репозитория. По умолчанию клонируется вся история. Флаг 1 указывает клоинирование без истории.
clone_depth: 1
# Номер сборки не будет инкрементироваться при создании pull request'а.
pull_requests:
do_not_increment_build_number: true
# Переменные окружения.
environment:
DOCKER_PASS:
secure: tyCs62GdU59M1vNsnAwKrw==
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
# Параметр указывает, что сборка будет производиться только при изменении master ветки. По умолчанию сборка производится на всех ветках.
branches:
only:
- master
skip_commits:
files:
- README.md
install:
- docker version
build_script:
- ps: .\build.ps1
# Этап выполнения тестов отключен
test: off
# Используется потому как не поддерживается скрипт и провайдер одновременно в deploy
before_deploy:
- ps: .\deploy.ps1
deploy:
- provider: Webhook
url:
secure: bwtxM3PwlQqNCxXgKZ7Aul9FWEx9OTMjV4suCKf0E6vOI
authorization:
secure: xFex7sajn/RKjS/cZrqSJnEjrhRO4535ALSzvC+OjzY7xVlq==
on:
branch: master
К каждому пункту конфигурации добавлены комментарии, так будет проще и быстрее понять общий сценарий. Отдельно отмечу официальную документацию https://www.appveyor.com/docs/ в ней расписаны детально все ньюансы, но только на английском языке. Давайте посмотрим непосредственно на скрипты build.ps1 и deploy.ps1. Они запускаются в соответствующие названию этапы обработки. К каждому этапу можно добавить сразу несколько скриптов.
build.ps1 - скрипт запускает сборку docker образа и присваивает ему сразу несколько тегов.
$Version=$env:APPVEYOR_BUILD_VERSION
Write-Host Starting build $Version
docker build -t d2funlife/blog:latest -t d2funlife/blog:$Version .
deploy.ps1 - скрипт логинится в docker hub репозиторий и выполняет push образа, который мы собрали на предыдущем этапе.
$Version=$env:APPVEYOR_BUILD_VERSION
Write-Host Starting deploy $Version
docker images
Write-Host Docker login
$env:DOCKER_PASS | docker login --username d2funlife --password-stdin
Write-Host Push to docker hub
docker push d2funlife/blog
И когда образ опубликован, остается только один вопрос - как же обновить его на нашем хосте. Список доступных вариантов деплоя представлен в документации https://www.appveyor.com/docs/deployment/. К сожалению, не поддерживается выполнение ssh команды на удаленном сервере. С использованием docker контейнеров мы можем запустить такой сценарий, но это что-то из разряда костылей и подпорок + необходимо быть внимательным к вопросу безопасности. Хорошей альтернативой является Webhook. Это веб-запрос на указаный вами url, с параметрами авторизации (для безопасности). Приняв запрос на сервере, вы можете выполнить необходимую команду для обновления docker контейнеров. Я сделал простой веб-сервис на .NET Core, который принимает запрос и запускает shell скрипт обновления. Таким образом мы получаем полностью настроенную непрерывную интегарцию с помощью Appveyor.