Skip to main content

Эта версия GitHub Enterprise Server была прекращена 2024-09-25. Исправления выпускаться не будут даже при критических проблемах безопасности. Для повышения производительности, повышения безопасности и новых функций выполните обновление до последней версии GitHub Enterprise Server. Чтобы получить справку по обновлению, обратитесь в службу поддержки GitHub Enterprise.

Доставка развертываний

С помощью REST API развертывания можно создавать пользовательские средства для взаимодействия с сервером и сторонним приложением.

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.