Git
Chapters ▾ 2nd Edition

6.5 GitHub - Скриптування GitHub

Скриптування GitHub

Отже тепер ми розглянули весь основний функціонал та процеси роботи GitHub, проте будь-яка велика група чи проект матимуть необхідність в додаткових налаштуваннях або в інтеграції зовнішніх сервісів.

На щастя, GitHub дуже легко змінювати у багатьох напрямках. У цій секції ми розглянемо як користуватись системою хуків GitHub та його API щоб GitHub працював саме так, як ви хочете.

Сервіси й хуки

Секції Хуки та Сервіси адміністративної сторінки сховища GitHub — це найпростіший метод налаштувати взаємодію між GitHub та зовнішніми системами.

Сервіси

Спочатку ми подивимось на Сервіси. І Хуки і Сервіси можна знайти в секції Settings (налаштування) вашого сховища, де ми раніше бачили як додавати Співпрацівників та змінювати типову гілку вашого проекту. У вкладці “Webhooks and Services” (веб хуки та сервіси) ви побачите щось таке Секція конфігурації Сервіси та Хуки..

Сервіси та Хуки
Figure 129. Секція конфігурації Сервіси та Хуки.

Є десятки сервісів, з яких ви можете вибирати, більшість з них є інтеграціями в інші комерційні та відкриті системи. Більшість з них є сервісами Безперервної Інтеграції, систем відстеження помилок, чатів та систем документації. Ми детально розглянемо налаштування простого прикладу: поштовий хук. Якщо ви виберете “email” з випадного віконця “Add Service” (додати сервіс), ви побачите екран налаштування Налаштування сервісу Email.

Сервіс Email
Figure 130. Налаштування сервісу Email.

У цьому випадку, якщо ми натиснемо кнопку “Add service” (додати сервіс), на вказану поштову адресу буде надходити лист щоразу, коли хтось викладатиме зміни до сховища. Сервіси можуть слідкувати за різноманітними типами подій, проте більшість слідкує виключно за подіями запису до сховища, а тоді щось роблять з цією інформацією.

Якщо ви бажаєте інтегрувати з GitHub якусь систему, що ви зараз використовуєте, спочатку перевірте тут — можливо для неї вже існує сервіс інтеграції. Наприклад, якщо ви використовуєте Jenkins для виконання тестів вашого коду, ви можете ввімкнути вбудований сервіс інтеграції Jenkins щоб розпочинати тести щоразу, коли хтось заливає зміни до вашого сховища.

Хуки

Якщо ви бажаєте зробити щось більш специфічне або ви бажаєте інтегрувати сервіс чи сайт, якого нема в цьому списку, ви можете використати більш загальну систему хуків. Хуки сховища GitHub доволі прості. Ви задаєте URL та GitHub буде запит HTTP до цього URL на будь-які події, що вас цікавлять.

Зазвичай це працює так: ви запускаєте маленький веб сервіс, що слухає запити від хуку GitHub, а потім робить щось з отриманими даними.

Щоб увімкнути хук, треба натиснути на кнопку “Add webhook” (додати веб-хук) у Секція конфігурації Сервіси та Хуки.. Це переведе вас на сторінку, що виглядає як Конфігурація веб хуку..

Веб хук
Figure 131. Конфігурація веб хуку.

Налаштувати веб хук доволі просто. Найчастіше вам просто треба задати URL та секретний ключ, і натиснути “Add webhook”. Є декілька опцій щодо яких подій ви бажаєте щоб GitHub відправляв вам інформацію — без додаткових налаштувань GitHub відправляє запит тільки щодо події push, коли хтось викладає новий код до будь-якої гілки вашого сховища

Подивимося на маленький приклад веб сервісу, що ви можете налаштувати для обробки веб хуку. Ми використаємо веб фреймворк Sinatra (Ruby), адже він доволі лаконічний та вам має бути легко зрозуміти, що ми робимо.

Припустімо, що ми бажаємо отримувати листа якщо окрема людина викладає зміни до окремої гілки нашого проекту та змінює окремий файл. Цього доволі легко досягти за допомогою такого коду:

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 для цього вебхуку. Для кожного хуку ви можете дізнатись, коли він був відправлений, чи був він успішним, а також тіло та заголовки і запиту, і відповіді. Це все дуже допомагає при тестуванні та виправленні ваших хуків.

Інформація про вебхук
Figure 132. Інформація для виправлення веб хуків.

Ще одна чудова функція — це те, що ви можете ще раз надіслати будь-який з запитів щоб легко протестувати ваш сервіс.

Задля докладнішої інформацією щодо написання вебхуків та про усі різноманітні типи подій, на які ви можете реагувати, перейдіть до документації розробника GitHub за адресою https://developer.github.com/webhooks/

GitHub API

Сервіси та хуки надають вам можливість отримувати повідомлення про події, що стались з вашими сховищами, проте що як вам потрібно більше інформації про ці події? Що як вам треба автоматизувати щось на кшталт додавання співпрацівників або додавання міток (label) до завдань (issues)?

Саме з цим нам допоможе GitHub API. 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 http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
"
}

Коментування завдання

Втім, якщо ви бажаєте щось зробити на веб сайті, наприклад додати коментар до Завдання чи Запиту на Пул, або ви бажаєте побачити або взаємодіяти з приватними даними, вам доведеться авторизуватись.

Є декілька шляхів це зробити. Ви можете використати базову авторизацію, просто зі своїм ім’ям та паролем, проте зазвичай краще використовувати особисту помітку авторизації (access token). Ви можете згенерувати її з вкладки “Applications” вашої сторінки налаштувань.

Помітка авторизації
Figure 133. Згенеруйте свою помітку авторизації з вкладки “Applications” вашої сторінки налаштувань.

Вас запитають опис та в яких контекстах ви бажаєте щоб ця помітка працювала. Переконайтесь, що ви використовуєте зрозумілий опис, щоб ви відчували впевненість при видаленні цієї помітки, коли ваш скрипт або програма більше не потрібні.

GitHub покаже вам помітку тільки одного разу, отже обов’язково скопіюйте її. Тепер ви можете використовувати її щоб авторизуватись у ваших скриптах замість використання імені та паролю. Це добре, бо ви можете обмежити контекст використання цієї помітки, та її легко скасувати.

Також це підвищує обмеження частоти запитів. Без авторизації, ви можете робити не більше 60 запитів на годину. Якщо ви авротизуєтеся, ви можете робити до 5000 запитів на годину.

Отже використаймо її щоб прокоментувати одне з наших завдань. Припустімо, що ми бажаємо залишити коментар до окремого завдання, Завдання №6. Щоб це зробити, ми маємо надіслати HTTP POST запит до repos/<ім’я користувача>/<сховище>/issues/<номер>/comments з поміткою, що ми щойно згенерували в заголовку Authorization.

$ 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 Коментар
Figure 134. Відправлений за допомогою GitHub API коментар.

Ви можете використовувати API майже для всього, що ви можете робити на сайті — створення та встановлення віх, призначення людей на Завдання та Запити на Пул, створення та зміна міток, отримувати дані про коміт, створювати нові коміти та гілки, відкривання, закривання та зливання Запитів на Пул, створення та редагування команд, коментування рядків коду з Запиту на Пул, пошук на сайті тощо.

Зміна статусу Запиту на Пул

Ми розглянемо ще один останній приклад, адже це дійсно корисно, якщо ви працюєте з Запитами на Пул. Кожен коміт може мати один чи більше статусів, що з ним асоційовані, та існує API щоб додавати та отримувати ці статуси.

Більшість сервісів Безперервної Інтеграції та тестування використовують цей 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 у повідомленні коміту, та нарешті відправляємо HTTP POST запит до кінцевої точки /repos/<користувач>/<сховище>/statuses/<хеш_коміту> зі статусом.

У цьому випадку ви можете відправити статус (success - успіх, failure - невдача, error - помилка), опис того, що сталося, а також посилання, за яким користувач може перейти щоб отримати більше інформації та “контекст” (context) у разі декількох статусів для одного коміту. Наприклад, сервіс тестування може надати статус та такий як цей перевірочний сервіс також може надати статус — поле “context” дозволяє їх розрізнити.

Якщо хтось відкриє новий Запит на Пул на GitHub, та цей хук налаштований, ви можете побачити щось схоже на Статус коміту через API..

Статус коміту
Figure 135. Статус коміту через API.

Тепер ви можете бачити маленьку зелену пташку біля коміту поруч з рядком “Signed-off-by” у повідомленні, а також червоний хрестик біля того коміту, який автор забув підписати. Ви також можете бачити, що Запит на Пул отримує статус останнього коміту гілки, та попереджає вас, якщо він невдалий. Це дійсно корисно, якщо ви використовуєте це API для результатів тестів, щоб ви випадково не злили якийсь Запит на Пул, в якому останній коміт не проходить тести.

Octokit

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

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