Git
Chapters ▾ 2nd Edition

6.5 GitHub - Писање скрипти за GitHub

Писање скрипти за GitHub

До сада смо прешли све главније особине и процесе рада на сервису GitHub, али свака већа група или пројекат ће пожелети да се сервис GitHub на одређени начин прилагоди њиховим потребама, или ће пожелети да интегришу неке спољне сервисе.

Срећом по нас, сервис GitHub је лако хаковати на многе начине. У овом одељку ћемо показати начине коришћења система GitHub кука и његовог API тако да натерамо сервис GitHub да ради онако како нама одговара.

Сервиси и Куке

Одељак административног дела GitHub репозиторијума „Hooks and Services” је најлакши начин за подешавање сервиса Github тако да врши интеракцију са спољним системима.

Сервиси

Прво ћемо погледати сервисе. Интеграције за куке и за сервисе се могу наћи у Settings одељку вашег репозиторијума, где смо раније ишли да додамо сараднике и мењамо подразумевану грану пројекта. Под картицом „Webhooks and Services” ћете видети нешто као Конфигурациони одељак за сервисе и куке.

Сервиси и куке
Слика 129. Конфигурациони одељак за сервисе и куке

Ту се налази на десетине сервиса које можете одабрати. То су углавном интеграције у друге комерцијалне системе, или системе отвореног кода. Већина њих служи за сервисе континуалне интеграције, а ту су и трекери за проблеме и багове, системи за ћаскање и системи за документацију. Проћи ћемо кроз подешавање једног врло једноставног, куке за имејл. Ако из падајућег менија „Add Service” изаберете „email”, добићете конфигурациони екран као са слике Конфигурација имејл сервиса.

Имејл сервис
Слика 130. Конфигурација имејл сервиса

У овом случају, ако притиснемо дугме „Add service”, на имејл адресу коју смо навели ћемо добити имејл сваки пут када неко гурне промене на репозиторијум. Сервиси могу да слушају пуно различитих врста догађаја, али већина слуша само догађаје гурања и онда раде нешто с тим подацима.

Ако постоји систем који користите и желите да га интегришете са сервисом GitHub, треба да проверите овде и погледате да ли већ постоји доступна интеграција за тај сервис. На пример, ако користите Jenkins да извршавате тестове над својом кодом, можете да укључите уграђену интеграцију за сервис Jenkins и да тако окинете тестирање сваки пут када неко гурне промене на репозиторијум.

Куке

Ако вам треба нешто одређеније или желите да се интегришете са сервисом или сајтом који се не налази на овом списку, можете да пробате општији систем кука. Куке за GitHub репозиторијум су прилично једноставне. Можете да наведете URL и GitHub ће слати HTTP товар ка тој URL адреси када се деси било који догађај који желите.

У општем случају, ово функционише тако да можете подесити мали веб сервис који слуша товар GitHub куке и онда ради нешто са подацима када их прими.

Да бисте омогућили куку, кликните на дугме „Add webhook” у Конфигурациони одељак за сервисе и куке. То ће вас одвести на страницу која изгледа као Конфигурација веб куке.

Веб кука
Слика 131. Конфигурација веб куке

Конфигурација за веб куку је прилично једноставна. У већини случајева једноставно унесете УРЛ и тајни кључ, па онда кликнете на „Add webhook”. Постоји неколико опција за које догађаје желите да вам сервис GitHub шаље товар — подразумевано се товар прима само за push догађај, тј. када неко гурне нови кôд на било коју грану вашег репозиторијума.

Хајде да видимо мали пример веб сервиса који бисте могли да подесите за обраду веб куке. Користићемо Рубијев веб радни оквир Синатра пошто је доста концизан и требало би да лако можете видети шта радимо.

Рецимо да желите да добијете имејл када одређена особа гурне промене на одређену грану вашег пројекта која мења одређени фајл. То прилично лако да урадимо следећим кодом:

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

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

  # prikupi podatke koje tražimo
  pusher = push["pusher"]["name"]
  branch = push["ref"]

  # uzmi listu svih fajlova koji su menjani
  files = push["commits"].map do |commit|
    commit['added'] + commit['modified'] + commit['removed']
  end
  files = files.flatten.uniq

  # proveri naš uslov
  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  'Скот је променио фајл'
      body     "АЛАРМ"
    end
  end
end

Овде од сервиса GitHub добијамо товар u JSON формату и испитујемо ко је гурнуо промене, на коју грану и који су фајлови су промењени сваким комит који је гурнут. Затим проверимо да ли то задовољава наше услове и затим пошаљемо имејл ако задовољава.

Да бисте испрограмирали и тестирали нешто овако, можете да користите лепу конзолу за развој на истом екрану у коме сте подесили куку. Можете видети последњих неколико испорука које је сервис GitHub пробао да направи за ту веб куку. За сваку куку можете пронаћи податак када је достављена, да ли је достављање било успешно, као и тело и заглавља за захтев и за одговор. Због свега овога је невероватно лако да тестирате и отклањате грешке у својим кукама.

Дибаг veb куке
Слика 132. Информације за отклањање грешака у веб куки

Још једна одлична могућност овога је то што можете поново да испоручите било који товар у циљу лакшег тестирања свог сервиса.

За више информација о томе како да пишете веб куке и о свим различитим догађајима које можете да ослушкујете, посетите GitHub Developer документацију која се налази на https://developer.github.com/webhooks/.

GitHub API

Сервиси и куке представљају начин да добијате обавештења у вези с догађајима који се догоде на вашим репозиторијумима, али шта ако вам треба више информација о овим догађајима? Шта ако треба да аутоматизујете нешто као додавање сарадника или додавање ознака тикетима?

Овде се као користан показује 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 да прикажете произвољни Маркдаун или да нађете шаблон за .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*
"
}

Коментарисање на тикету

Ипак, ако желите да нешто урадите на веб сајту, на пример да коментаришете на тикет или захтев за повлачење, или желите да погледате или да имате интеракцију са приватним садржајем, морате да се аутентификујете.

Постоји неколико начина за аутентификацију. Можете да користите основну аутентификацију само са својим корисничким именом и лозинком, али у општем случају је боља идеја да користите лични приступни токен. Можете да га генеришете из картице „Applications” на вашој страници за подешавања.

Приступни токен
Слика 133. Генеришите свој приступни токен са картице „Applications” на вашој страници за подешавања

Питаће вас да се одлучите за која подручја ће важити овај токен и за опис. Обавезно унесите добар опис како би вам било лакше да уклоните токен из скрипте или апликације када престанете да га користите.

GitHub ће вам показати токен само једном, зато га обавезно копирајте. Ово сада можете користити да потврдите свој идентитет у скрипти уместо да користите корисничко име и лозинку. Добро је што можете ограничити подручје над којим желите да скрипта делује, а токен се може опозвати.

Поред тога, ово вам повећава границу учесталости захтева. Без аутентификације, ограничени сте на 60 захтева по сату. Са аутентификацијом, можете да направите до 5000 захтева по сату.

Хајде да искористимо токен тако да направимо коментар на једном од наших тикета. Рецимо да хоћемо оставити коментар на одређеном тикету, Issue #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 коментар
Слика 134. Коментар постављен употребом GitHub API

API можете употребити да урадите скоро све што можете да урадите на сајту — да направите и подешавате прекретнице, да додељујете људе тикетима и захтевима за повлачење, да правите и мењате ознаке, да приступате подацима о комиту, да правите нове комитове и гране, да отварате, затварате и спајате захтеве за повлачење, да правите и мењате тимове, да коментаришете линије кода у захтеву за повлачење, да претражујете сајт и тако даље.

Промена статуса захтева за повлачење

Још један пример који ћемо погледати је рад са захтевима за повлачење, пошто то уме да буде јако корисно. Сваки комит може имати један или више статуса који су му придружени и постоји API који служи да додате статус и да вршите упит статуса.

Већина сервиса за континуалну интеграцију и тестирање користе овај API да реагују на гурање тако што тестирају кôд који је гурнут, па онда извештавају да ли је тај комит прошао све тестове. Ово можете користити и да проверите да ли је комит порука форматирана како ваља, да ли је подносилац захтева пратио све смернице за допринос, да ли је комит ваљано потписан — много тога.

Рецимо да на свом репозиторијуму подесите веб куку која гађа мали веб сервис који у комит поруци проверава стринг Signed-off-by.

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

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

  # pogledaj svaku komit poruku
  push["commits"].each do |commit|

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

    # pošalji status na 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/<корисник>/<репозиторијум>/statuses/<SHA-комита> API крајњу тачку са статусом.

У овом случају можете да пошаљете стање ('success' тј. успех, 'failure' тј. неуспех, 'error' тј. грешка), опис онога што се десило, одредишни URL на који корисник може да оде за више информација и „context” у случају да има више статуса за један комит. На пример, сервис за тестирање може да јави статус, а и сервис за валидацију као што је овај може такође да јави статус — разлика између њих се прави путем „context” поља.

Ако неко отвори нови захтев за повлачење на сервису GitHub и овај кука се окине, могли бисте видети нешто као Статус комита преко API.

Статус комита
Слика 135. Статус комита преко API

Сада можете да видите мали зелени знак за штиклирање поред комита који у поруци има стринг Signed-off-by и црвени крстић кроз онај где је аутор заборавио да се потпише. Можете и да видите да захтев за повлачење узима статус последњег комита са гране и упозорава вас ако је дошло до неуспеха. То је веома корисно ако користите овај API за резултате теста тако да случајно не спојите нешто чији последњи комит не пролази тестове.

Октокит

Иако смо скоро све радили кроз curl и једноставне HTTP захтеве у овим примерима, постоји неколико библиотека отвореног кода које овај API обезбеђују на природнији начин. У тренутку писања, подржани језици су Go, Објектни C, Руби и .NET. За више информација о овоме, погледајте http://github.com/octokit, јер они уместо вас рукују већином HTTP размене.

Надамо се да ће вам ови алати помоћи да прилагодите сервис GitHub својим потребама у складу са процесом рада који користите. За комплетну документацију и потпун API, као и упутства за неке честе задатке, погледајте https://developer.github.com.