Rest API можно использовать для развертывания проектов, размещенных на GitHub на сервере, который вы владеете. Дополнительные сведения о конечных точках для управления развертываниями и состояниями см. в разделе Конечные точки REST API для развертываний. Вы также можете использовать REST API для координации развертываний в момент, когда код приземляется на ветвь по умолчанию. Дополнительные сведения см. в разделе Создание сервера непрерывной интеграции.
В этом руководстве будет использоваться REST API для демонстрации настройки, которую можно использовать. В описываемом сценарии мы выполним указанные ниже действия.
- Выполним слияние запроса на вытягивание.
- По завершении непрерывной интеграции мы зададим соответствующее состояние запроса на вытягивание.
- После слияния запроса на вытягивание мы запустим развертывание на нашем сервере.
Система непрерывной интеграции и сервер размещения будут вымышленными. Это может быть Heroku, Amazon или что-то совершенно иное. Основная цель этого руководства — настроить сервер, управляющий взаимодействием.
Если вы еще не сделали этого, обязательно скачайтеngrok
и узнайте, как его использовать. Мы считаем, что это очень полезное средство для предоставления локальных приложений в Интернете.
Примечание. Полный исходный код для этого проекта можно скачать из репозитория platform-samples.
Создание сервера
Мы создадим небольшое приложение Sinatra, чтобы подтвердить работоспособность локальных подключений. Начнем с этого:
require 'sinatra'
require 'json'
post '/event_handler' do
payload = JSON.parse(params[:payload])
"Well, it worked!"
end
(Если вы не знакомы с тем, как работает Sinatra, рекомендуем ознакомиться с руководством по Sinatra.)
Запустите этот сервер. По умолчанию Sinatra начинается с порта 4567
, поэтому вы также хотите настроить ngrok
для этого прослушивание.
Чтобы этот сервер работал, необходимо настроить репозиторий с веб-перехватчиком. Веб-перехватчик должен быть настроен так, чтобы он активировался каждый раз при создании или слиянии запроса на вытягивание.
Давайте создадим репозиторий, с которым можно спокойно экспериментировать. Мы предлагаем репозиторий @octocat Spoon/Knife.
После этого вы создадите в репозитории новый веб-перехватчик, задав URL-адрес, ngrok
который дал вам, и выберите application/x-www-form-urlencoded
тип контента.
Щелкните Обновить веб-перехватчик. Вы должны увидеть текст ответа Well, it worked!
.
Отлично! Установите переключатель в положение Разрешить мне выбрать отдельные события и выберите следующее:
- Развертывание
- Состояния развертывания
- Запрос на вытягивание
Это события GitHub отправляются на наш сервер всякий раз, когда происходит соответствующее действие. Пока мы настроим сервер так, чтобы он обрабатывал только слияния запросов на вытягивание:
post '/event_handler' do
@payload = JSON.parse(params[:payload])
case request.env['HTTP_X_GITHUB_EVENT']
when "pull_request"
if @payload["action"] == "closed" && @payload["pull_request"]["merged"]
puts "A pull request was merged! A deployment should start now..."
end
end
end
Почему? Каждое событие, которое GitHub отправляет присоединенный X-GitHub-Event
заголовок HTTP. Пока нас интересуют только события, связанные с запросами на вытягивание. При слиянии запроса на вытягивание (состояние closed
, merged
имеет значение true
) запускается развертывание.
Чтобы проверить этот эксперимент, внесите какие-нибудь изменения в ветвь тестового репозитория, откройте запрос на вытягивание и выполните его слияние. Ваш сервер должен вернуть соответствующий ответ.
Работа с развертываниями
Реализовав сервер, проверив код и выполнив слияние запроса на вытягивание, теперь мы хотим развернуть проект.
Сначала мы изменим прослушиватель событий для обработки запросов на вытягивание при их слиянии и приступим к развертыванию:
when "pull_request"
if @payload["action"] == "closed" && @payload["pull_request"]["merged"]
start_deployment(@payload["pull_request"])
end
when "deployment"
process_deployment(@payload)
when "deployment_status"
update_deployment_status
end
На основе сведений из запроса на вытягивание мы начнем заполнять метод start_deployment
:
def start_deployment(pull_request)
user = pull_request['user']['login']
payload = JSON.generate(:environment => 'production', :deploy_user => user)
@client.create_deployment(pull_request['head']['repo']['full_name'], pull_request['head']['sha'], {:payload => payload, :description => "Deploying my sweet branch"})
end
Развертывания могут сопровождаться метаданными в виде payload
и description
. Хотя эти значения являются необязательными, они полезны для ведения журнала и представления сведений.
При создании нового развертывания активируется отдельное событие. Вот почему нужен новый случай switch
в обработчике событий deployment
. Эти сведения можно использовать для получения уведомления об активации развертывания.
Развертывания могут занимать довольно много времени, поэтому необходимо прослушивать различные события, например создание развертывания и изменение его состояния.
Давайте сымитируем развертывание, которое выполняет некоторые действия, и посмотрим, какое влияние оно оказывает на выходные данные. Сначала завершим метод process_deployment
:
def process_deployment
payload = JSON.parse(@payload['payload'])
# you can send this information to your chat room, monitor, pager, etc.
puts "Processing '#{@payload['description']}' for #{payload['deploy_user']} to #{payload['environment']}"
sleep 2 # simulate work
@client.create_deployment_status("repos/#{@payload['repository']['full_name']}/deployments/#{@payload['id']}", 'pending')
sleep 2 # simulate work
@client.create_deployment_status("repos/#{@payload['repository']['full_name']}/deployments/#{@payload['id']}", 'success')
end
Наконец, сымитируем сохранение сведений о состоянии путем вывода их в консоли:
def update_deployment_status
puts "Deployment status for #{@payload['id']} is #{@payload['state']}"
end
Давайте разберемся, что происходит. Развертывание создается методом start_deployment
, который активирует событие deployment
. Далее мы вызываем метод process_deployment
, который имитирует выполнение некоторых задач. Во время этой обработки мы также вызываем create_deployment_status
, чтобы получатель мог узнать, что происходит, когда состояние переведено в pending
.
После завершения развертывания задается состояние success
.
Заключение
В GitHub для управления развертываниями уже много лет используется одна из версий Heaven. Процесс в целом такой же, как и в случае с созданным выше сервером.
- Ожидается ответ о состоянии проверок непрерывной интеграции (успешно или сбой).
- Если необходимые проверки пройдены успешно, выполняется слияние запроса на вытягивание.
- Heaven принимает объединенный код и развертывает его на промежуточных и рабочих серверах.
- В то же время Heaven также уведомляет всех участников о сборке посредством бота Hubot в наших комнатах чата.
Вот и все! Чтобы использовать этот пример, не нужно создавать собственную конфигурацию развертывания. Всегда можно воспользоваться интеграциями GitHub.