REST API можно использовать для развертывания проектов, размещенных на GitHub на сервере, который вы владеете. Дополнительные сведения о конечных точках для управления развертываниями и состояниями см. в разделе "Конечные точки REST API для развертываний". Вы также можете использовать REST API для координации развертываний в момент, когда код приземляется на ветвь по умолчанию. Дополнительные сведения см. в разделе Создание сервера непрерывной интеграции.
В этом руководстве будет использоваться REST API для демонстрации настройки, которую можно использовать. В описываемом сценарии мы выполним указанные ниже действия.
- Выполним слияние запроса на вытягивание.
- По завершении непрерывной интеграции мы зададим соответствующее состояние запроса на вытягивание.
- После слияния запроса на вытягивание мы запустим развертывание на нашем сервере.
Система непрерывной интеграции и сервер размещения будут вымышленными. Это может быть Heroku, Amazon или что-то совершенно иное. Основная цель этого руководства — настроить сервер, управляющий взаимодействием.
Если вы еще не сделали этого, обязательно скачайтеngrok
и узнайте, как его использовать. Мы считаем, что это очень полезное средство для предоставления локальных приложений в Интернете.
Note
Кроме того, вы можете использовать перенаправление веб-перехватчиков для настройки локальной среды для получения веб-перехватчиков. Дополнительные сведения см. в разделе Использование интерфейса командной строки GitHub для пересылки веб-перехватчиков для тестирования.
Примечание. Полный исходный код для этого проекта можно скачать из репозитория 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, прикреплен заголовок HTTP X-GitHub-Event
. Пока нас интересуют только события, связанные с запросами на вытягивание. При слиянии запроса на вытягивание (состояние 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.