Skip to main content

Создание сервера непрерывной интеграции

Создайте собственную систему непрерывной интеграции с помощью API состояния.

С помощью REST API можно связать фиксации со службой тестирования, чтобы каждый push-запрос можно протестировать и представить в запросе на вытягивание GitHub Enterprise Server. Дополнительные сведения о соответствующих конечных точках см. в разделе Конечные точки REST API для состояния фиксации.

В этом руководстве данный интерфейс API используется для демонстрации возможной конфигурации. В описываемом сценарии мы выполним указанные ниже действия.

  • Запустите наш набор непрерывной интеграции (CI) при открытии запроса на вытягивание (мы зададим состояние CI "в ожидании").
  • По завершении непрерывной интеграции мы зададим соответствующее состояние запроса на вытягивание.

Система непрерывной интеграции и сервер размещения будут вымышленными. Это может быть Travis, Jenkins или что-то совершенно иное. Основная цель этого руководства — настроить сервер, управляющий взаимодействием.

Если вы еще не сделали этого, скачайте 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 Enterprise Server будет отправлять на наш сервер каждый раз, когда происходит соответствующее действие. Давайте обновим сервер так, чтобы пока он обрабатывал только сценарий запроса на вытягивание:

post '/event_handler' do
  @payload = JSON.parse(params[:payload])

  case request.env['HTTP_X_GITHUB_EVENT']
  when "pull_request"
    if @payload["action"] == "opened"
      process_pull_request(@payload["pull_request"])
    end
  end
end

helpers do
  def process_pull_request(pull_request)
    puts "It's #{pull_request['title']}"
  end
end

Почему? К каждому событию, которое отправляет GitHub Enterprise Server, прикреплен заголовок HTTP X-GitHub-Event. Пока нас интересуют только события, связанные с запросами на вытягивание. Из них мы возьмем полезные данные и вернем поле заголовка. В идеальном сценарии сервер должен обрабатывать каждое обновление запроса на вытягивание, а не только его открытие. Это позволяет гарантировать, что каждая новая отправка проходит тесты CI. Однако в этой демонстрации нас будет интересовать только открытие запроса.

Чтобы проверить этот эксперимент, внесите какие-нибудь изменения в ветвь тестового репозитория и откройте запрос на вытягивание. Ваш сервер должен вернуть соответствующий ответ.

Работа с состояниями

Реализовав сервер, мы готовы приступить к выполнению первого требования: заданию (и обновлению) состояний CI. Обратите внимание, что при каждом обновлении сервера можно щелкнуть Доставить повторно, чтобы отправить те же полезные данные. Создавать новый запрос на вытягивание каждый раз, когда вы вносите изменения, не нужно.

Так как мы взаимодействуем с API GitHub Enterprise Server, мы используем Octokit.rb для управления взаимодействием. Мы настроим этот клиент с помощью personal access token:

# !!! DO NOT EVER USE HARD-CODED VALUES IN A REAL APP !!!
# Instead, set and test environment variables, like below
ACCESS_TOKEN = ENV['MY_PERSONAL_TOKEN']

before do
  @client ||= Octokit::Client.new(:access_token => ACCESS_TOKEN)
end

После этого нужно просто обновить запрос на вытягивание на GitHub Enterprise Server, чтобы было ясно, что обработка выполняется в рамках непрерывной интеграции:

def process_pull_request(pull_request)
  puts "Processing pull request..."
  @client.create_status(pull_request['base']['repo']['full_name'], pull_request['head']['sha'], 'pending')
end

Здесь мы выполняем три основных задачи:

  • Мы ищем полное имя репозитория
  • Мы ищем последний SHA запроса на вытягивание
  • Мы устанавливаем состояние "ожидающий"

Вот и все! Далее можно запустить любой необходимый процесс для выполнения набора тестов. Возможно, вы собираетесь передать код в Jenkins или вызвать другую веб-службу через ее API, например Travis. После этого потребуется еще раз обновить состояние. В нашем примере мы просто задаем "success":

def process_pull_request(pull_request)
  @client.create_status(pull_request['base']['repo']['full_name'], pull_request['head']['sha'], 'pending')
  sleep 2 # do busy work...
  @client.create_status(pull_request['base']['repo']['full_name'], pull_request['head']['sha'], 'success')
  puts "Pull request processed!"
end

Заключение

В GitHub для управления CI уже много лет используется одна из версий Janky. Процесс в целом такой же, как и в случае с созданным выше сервером. Мы делаем следующее:

  • активируем Jenkins при создании или обновлении запроса на вытягивание (через Janky);
  • ожидаем ответа о состоянии CI;
  • если код зеленый, выполняется слияние запроса на вытягивание.

Все это взаимодействие передается в наши комнаты чата. Чтобы использовать этот пример, не нужно создавать собственную конфигурацию CI. Всегда можно воспользоваться интеграциями GitHub.