Git
Chapters ▾ 2nd Edition

6.5 GitHub - Создание сценариев GitHub

Создание сценариев GitHub

Итак, мы рассмотрели все основные функции и рабочие процессы GitHub, но у любой большой группы или проекта могут быть настройки, которые они могут захотеть сделать, или внешние сервисы, которые они могут захотеть интегрировать.

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

Сервисы и хуки

Раздел Hooks and Services администрирования репозитория GitHub — это самый простой способ взаимодействия GitHub с внешними системами.

Сервисы

Сначала мы рассмотрим сервисы. Интеграцию хуков и сервисов можно найти в разделе «Настройки» («Settings») вашего репозитория, где ранее мы рассматривали возможность добавления соавторов и изменения ветки вашего проекта по умолчанию. На вкладке «Вебхуки и сервисы» («Webhooks and Services») вы увидите что-то вроде Раздел настройки сервисов и хуков.

Services and hooks
Рисунок 129. Раздел настройки сервисов и хуков

Вы можете выбирать из десятков сервисов, большинство из которых интегрируются в другие коммерческие системы и системы с открытым исходным кодом. Большинство из них предназначены для сервисов непрерывной интеграции, систем отслеживания ошибок и проблем, систем чатов и систем документации. Мы рассмотрим настройку очень простого хука электронной почты. Если вы выберете «email» в раскрывающемся списке «Добавить сервис» («Add Service»), вы получите экран конфигурации, например Конфигурация службы электронной почты.

Email service
Рисунок 130. Конфигурация службы электронной почты

В этом случае, если мы нажмём кнопку «Добавить сервис» («Add Service»), указанный нами адрес электронной почты будет получать электронное письмо каждый раз, когда кто-то отправляет в репозиторий. Сервисы могут прослушивать множество различных типов событий, но большинство из них прослушивают только push-события, а затем что-то делают с этими данными.

Если вы используете систему, которую хотите интегрировать с GitHub, вам следует проверить здесь, чтобы узнать, доступна ли существующая интеграция сервиса. Например, если вы используете Jenkins для запуска тестов своей кодовой базы, вы можете включить интеграцию встроенного сервиса Jenkins, чтобы запускать тестовый прогон каждый раз, когда кто-то отправляет данные в ваш репозиторий.

Хуки

Если вам нужно что-то более конкретное или вы хотите интегрироваться с сервисом или сайтом, не включённым в этот список, вы можете вместо этого использовать более общую систему хуков. Хуки репозитория GitHub довольно просты. Вы указываете URL-адрес, и GitHub отправит полезные данные HTTP на этот URL-адрес для любого события, которое вы хотите.

Как правило, это работает так: вы можете настроить небольшой веб-сервис для прослушивания полезных данных хука GitHub, а затем что-то делать с данными, когда они будут получены.

Чтобы включить хук, вы нажимаете кнопку «Добавить вебхук» («Add webhook») в Раздел настройки сервисов и хуков. Это приведёт вас на страницу, которая выглядит как Конфигурация вебхука.

Web hook
Рисунок 131. Конфигурация вебхука

Конфигурация вебхука довольно проста. В большинстве случаев вы просто вводите URL и секретный ключ и нажимаете «Добавить вебхук» («Add webhook»). Есть несколько вариантов, для каких событий вы хотите, чтобы GitHub отправлял вам полезные данные — по умолчанию вы получаете полезные данные только для события push, когда кто-то отправляет новый код в любую ветку вашего репозитория.

Давайте рассмотрим небольшой пример веб-сервиса, который вы можете настроить для обработки вебхука. Мы будем использовать веб-фреймворк Ruby Sinatra, так как он довольно лаконичен, и вы сможете легко увидеть, что мы делаем.

Допустим, мы хотим получать электронное письмо, если конкретный человек отправляет на определённую ветку нашего проекта, изменённый определённый файл. Мы могли бы довольно легко сделать это с помощью такого кода:

require 'sinatra'
require 'json'
require 'mail'

post '/payload' do
  push = JSON.parse(request.body.read) # parse the JSON

  # gather the data we're looking for
  pusher = push["pusher"]["name"]
  branch = push["ref"]

  # get a list of all the files touched
  files = push["commits"].map do |commit|
    commit['added'] + commit['modified'] + commit['removed']
  end
  files = files.flatten.uniq

  # check for our criteria
  if pusher == 'schacon' &&
     branch == 'ref/heads/special-branch' &&
     files.include?('special-file.txt')

    Mail.deliver do
      from     'tchacon@example.com'
      to       'tchacon@example.com'
      subject  'Scott Changed the File'
      body     "ALARM"
    end
  end
end

Здесь мы берём полезные данные JSON, которые доставляет нам GitHub, и ищем, кто их отправил, в какую ветку они отправили и какие файлы были затронуты во всех отправленных коммитах. Затем мы проверяем это на соответствие нашим критериям и отправляем электронное письмо, если оно соответствует.

Чтобы разработать и протестировать что-то подобное, у вас есть хорошая консоль разработчика на том же экране, где вы устанавливаете связь. Вы можете увидеть последние несколько доставок, которые GitHub пытался сделать для этого вебхука. Для каждого хука вы можете узнать, когда он был доставлен, если он был успешным, а также тело и заголовки как для запроса, так и для ответа. Это делает невероятно простым тестирование и отладку ваших хуков.

Webhook debug
Рисунок 132. Информация об отладке вебхуков

Другая замечательная особенность этого заключается в том, что вы можете повторно доставить любые полезные данные, чтобы легко протестировать свой сервис.

Для получения дополнительной информации о том, как писать вебхуки и обо всех различных типах событий, которые вы можете прослушивать, перейдите к документации GitHub Developer по адресу https://developer.github.com/webhooks/.

GitHub API

Сервисы и хуки дают вам возможность получать push-уведомления о событиях, происходящих в ваших репозиториях, но что, если вам нужна дополнительная информация об этих событиях? Что, если вам нужно автоматизировать что-то вроде добавления соавторов или маркировки проблем?

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

Основное использование

Самое простое, что вы можете сделать, — это отправить простой запрос GET на конечную точку, не требующую аутентификации. Это может быть пользовательская или доступная только для чтения информация о проекте с открытым исходным кодом. Например, если мы хотим узнать больше о пользователе с именем «schacon», мы можем запустить что-то вроде этого:

$ curl https://api.github.com/users/schacon
{
  "login": "schacon",
  "id": 70,
  "avatar_url": "https://avatars.githubusercontent.com/u/70",
# …
  "name": "Scott Chacon",
  "company": "GitHub",
  "following": 19,
  "created_at": "2008-01-27T17:19:28Z",
  "updated_at": "2014-06-10T02:37:23Z"
}

Существует множество подобных конечных точек для получения информации об организациях, проектах, проблемах, коммитах — почти обо всём, что вы можете публично увидеть на GitHub. Вы даже можете использовать API для визуализации произвольного Markdown или найти шаблон .gitignore.

$ curl https://api.github.com/gitignore/templates/Java
{
  "name": "Java",
  "source": "*.class

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.ear

# virtual machine crash logs, see https://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
"
}

Комментирование проблемы

Однако, если вы хотите выполнить какое-либо действие на веб-сайте, например прокомментировать проблему или запрос на слияние, или если вы хотите просмотреть или взаимодействовать с частным контентом, вам необходимо пройти аутентификацию.

Существует несколько способов аутентификации. Вы можете использовать обычную аутентификацию только с вашим именем пользователя и паролем, но, как правило, лучше использовать токен личного доступа. Вы можете сгенерировать его на вкладке «Приложения» («Applications») на странице настроек.

Access Token
Рисунок 133. Сгенерируйте токен доступа на вкладке «Приложения» («Applications») на странице настроек

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

GitHub покажет вам токен только один раз, поэтому обязательно скопируйте его. Теперь вы можете использовать это для аутентификации в своём скрипте вместо использования имени пользователя и пароля. Это хорошо, потому что вы можете ограничить объём того, что вы хотите сделать, и токен может быть отозван.

Это также имеет дополнительное преимущество в виде увеличения лимита скорости. Без аутентификации вы будете ограничены 60 запросами в час. Если вы аутентифицируетесь, вы можете делать до 5000 запросов в час.

Итак, давайте воспользуемся им, чтобы прокомментировать одну из наших проблем. Допустим, мы хотим оставить комментарий к конкретной проблеме № 6 (Issue #6). Для этого нам нужно выполнить HTTP-запрос POST к repos/<user>/<repo>/issues/<num>/comments с токеном, который мы только что сгенерировали в качестве заголовка авторизации.

$ curl -H "Content-Type: application/json" \
       -H "Authorization: token TOKEN" \
       --data '{"body":"A new comment, :+1:"}' \
       https://api.github.com/repos/schacon/blink/issues/6/comments
{
  "id": 58322100,
  "html_url": "https://github.com/schacon/blink/issues/6#issuecomment-58322100",
  ...
  "user": {
    "login": "tonychacon",
    "id": 7874698,
    "avatar_url": "https://avatars.githubusercontent.com/u/7874698?v=2",
    "type": "User",
  },
  "created_at": "2014-10-08T07:48:19Z",
  "updated_at": "2014-10-08T07:48:19Z",
  "body": "A new comment, :+1:"
}

Теперь, если вы перейдёте к этой проблеме, вы увидите комментарий, который мы только что успешно разместили, например Комментарий, отправленный из GitHub API.

API Comment
Рисунок 134. Комментарий, отправленный из GitHub API

Вы можете использовать API, чтобы делать практически всё, что вы можете делать на веб-сайте: создавать и устанавливать вехи (milestones), назначать людей для проблем и запросов на слияние, создавать и изменять метки, получать доступ к данным коммитов, создавать новые коммиты и ветки, открывать, закрывать или объединение запросов на слияние, создание и редактирование команд, комментирование строк кода в запросе на слияние, поиск по сайту и так далее.

Изменение статуса запроса на слияние

Есть ещё один последний пример, который мы рассмотрим, так как он действительно полезен, если вы работаете с запросами на слияние. С каждым коммитом может быть связан один или несколько статусов, и существует API для добавления и запроса этого статуса.

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

Допустим, вы настроили вебхук в своём репозитории, который обращается к небольшому веб-сервису, который проверяет наличие строки «Signed-off-by» в сообщении коммита.

require 'httparty'
require 'sinatra'
require 'json'

post '/payload' do
  push = JSON.parse(request.body.read) # parse the JSON
  repo_name = push['repository']['full_name']

  # look through each commit message
  push["commits"].each do |commit|

    # look for a Signed-off-by string
    if /Signed-off-by/.match commit['message']
      state = 'success'
      description = 'Successfully signed off!'
    else
      state = 'failure'
      description = 'No signoff found.'
    end

    # post status to GitHub
    sha = commit["id"]
    status_url = "https://api.github.com/repos/#{repo_name}/statuses/#{sha}"

    status = {
      "state"       => state,
      "description" => description,
      "target_url"  => "http://example.com/how-to-signoff",
      "context"     => "validate/signoff"
    }
    HTTParty.post(status_url,
      :body => status.to_json,
      :headers => {
        'Content-Type'  => 'application/json',
        'User-Agent'    => 'tonychacon/signoff',
        'Authorization' => "token #{ENV['TOKEN']}" }
    )
  end
end

Надеюсь, следовать этому довольно просто. В этом обработчике вебхука мы просматриваем каждый только что отправленный коммит, ищем строку «Signed-off-by» в сообщении коммита и, наконец, отправляем POST через HTTP в /repos/<user>/<repo> /statuses/<commit_sha> Конечная точка API со статусом.

В этом случае вы можете отправить состояние («успех» ('success'), «сбой» ('failure'), «ошибка» ('error')), описание того, что произошло, целевой URL-адрес, по которому пользователь может перейти для получения дополнительной информации, и «контекст» в случае наличия нескольких статусов за один коммит. Например, сервис тестирования может предоставить статус, а сервис проверки, подобная этой, также может предоставить статус — поле «контекст» — это то, как они различаются.

Если кто-то откроет новый запрос на слияние на GitHub и этот хук настроен, вы можете увидеть что-то вроде Статус коммита через API.

Commit status
Рисунок 135. Статус коммита через API

Теперь вы можете увидеть маленькую зелёную галочку рядом с коммитом, в сообщении которой есть строка «Signed-off-by», и красным крестиком тот коммит, который автор забыл подписать. Вы также можете видеть, что запрос на слияние принимает статус последнего коммита в ветке и предупреждает вас, если это сбой. Это действительно полезно, если вы используете этот API для результатов тестирования, чтобы случайно не объединить что-то, где последний коммит не прошёл тесты.

Octokit

Хотя в этих примерах мы делали почти всё с помощью curl и простых HTTP-запросов, существует несколько библиотек с открытым исходным кодом, которые делают этот API доступным более идиоматичным образом. На момент написания этой статьи поддерживаемые языки включают Go, Objective-C, Ruby и .NET. Посетите https://github.com/octokit для получения дополнительной информации о них, так как они обрабатывают большую часть HTTP для вас.

Надеюсь, эти инструменты помогут вам настроить и модифицировать GitHub, чтобы он лучше работал с вашими конкретными рабочими процессами. Для получения полной документации по всему API, а также руководств по общим задачам посетите https://developer.github.com.

scroll-to-top