Git
Chapters ▾ 2nd Edition

6.5 GitHub - Pisanje skripti za GitHub

Pisanje skripti za GitHub

Sada smo porkili sve glavnije osobine i tokove rada na GitHub-u, ali svaka veća grupa ili projekat će želeti da se GitHub na određen način prilagodi njihovim potrebana, ili će želeti da integrišu neke eksterne servise.

Srećom po nas, GitHub je lako hakovati na mnoge načine. U ovom odeljku ćemo pokriti načine korišćenja GitHub-ovih sistema za povezivanje i njegovog API-ja kako bismo naterali GitHub da radi onako kako mi to želimo.

Hukovi

Odeljak Hooks an Services administrativnog dela GitHub repozitorijuma je najlakši način da interagujete sa eksternim sistemima.

Servisi

Prvo ćemo pogledati servise. Integracije i za hukove i za servise se mogu naći u odeljku Settings vašeg repozitorijuma, gde smo ranije pogledali kako da dodamo kolaboratore i promenili podrazumevanu granu za projekat. Sada odite na karticu Konfiguracioni odeljak za servise i hukove..

_Webhooks and services_
Figure 130. Konfiguracioni odeljak za servise i hukove.

Tu se nalazi na desetine servisa koje možete odabrati, koji su uglavnom integracije u druge komercijalne sisteme, ili sisteme otvorenog koda. Većina njih služi za servis kontinualne integracije, a tu su i trakeri za probleme i bagove, sistemi za ćaskanje i sistemi za dokumentaciju. Proći ćemo kroz podešavanje jednog jednostavnog, huk za mejl. Ako izaberete email iz padajućeg menija Add Service, dobićete ekran kao sa slike Konfigurcija za mejl servis..

Konfiguracija za mejl servis
Figure 131. Konfigurcija za mejl servis.

U ovom slučaju, ako pritisnemo dugme Add service, na mejl adresu koju smo specificirali ćemo dobiti mejl svaki put kada neko gurne promene na repozitorijum. Servisi slušaju puno različitih vrsta događaja, ali većina sluša samo događaje u vezi s guranjem promena i onda radi nešto s tim podacima.

Ako postoji sistem koji koristite i želite da ga integrišete sa GitHub-om, treba da proverite ovde i pogledate da li postoji postojeća integracija za servis. Na primer, ako koristite Jenkins da pokrenete testove u svojoj bazi koda, možete da uključite ugrađenu integraciju za servis Jenkins i da tako okinete testiranje svaki put kada neko gurne promene na repozitorijum.

Hukovi

Ako vam treba nešto specifičnije ili želite da se integrišete sa servisom ili sajtom koji se ne nalazi na ovom spisku, možete da probate neke generičke huk sisteme. Hukovi za GitHub repozitorijum su prilično jednostavni. Možete da specificirate URL i GitHub će slati koristne informacije putem HTTP-a ka tom URL-u za bilo koji događaj koji želite.

Generalno, način na koji ovo funkcioniše jeste da podesite mali veb servis i slušate korisne podatke sa GitHub-ovog huka i onda da uradite nešto sa tim podacima kada ih dobijete.

Kako biste omogućili huk, kliknite na dugme Add webhook u [__services_hooks]. Ovo će vas odvesti na stranicu Konfiguracija za Web hook..

_Web hook_
Figure 132. Konfiguracija za Web hook.

Konfiguracija za veb huk je prilično jednostavna. U većini slučajeva ćete samo uneti URL i tajni ključ i onda kliknuti na Add webhook. Postoji nekoliko opcija za koje događaje želite da vam GitHub šalje podatke — podrazumevana opcija je samo za push događaj, tj. kada neko gurne novi kôd na bilo koju granu vašeg repozitorijuma.

Da vidimo mali primer veb servisa koji ćete možda podesiti da biste rukovali veb hukom. Koristićemo Rubijev veb frejmvork Sinatru pošto je dosta koncizna i trebalo bi da lako možete da vidite šta radimo.

Recimo da želite da dobijete mejl kada određena osoba gurne promene na određenu granu vašeg projekta i modifikuje određeni fajl. Možemo vrlo lako da uradimo to kodom na sledeći način.

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

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

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

  # uzmi listova svih fajlova koji su dirani
  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  'Skot je promenio fajl'
      body     "ALARM"
    end
  end
end

Uzimamo podatke u JSON formatu koje nam GitHub dobavlja i gledamo ko je gurnuo promene, na koju su granu gurnute i koji su fajlovi dirani za svaki komit koji bude gurnut. Onda proverimo da li to zadovoljava naše uslove i zatim pošaljemo mejl ako se uklapa u njih.

Kako biste isprogramirali i testirali nešto ovako, možete da koristite lepu konzolu za razvitak na istom ekranu gde ste podesili huk. Možete da vidite poslednjih nekoliko isporuka koje je GitHub probao da napravi tim veb hukom. Za svaki huk možete da pronađete podatak kada je dostavljen, da li je dostavljane bilo uspešno, kao i telo i zaglavlja i zahteva i odgovora. Zbog ovoga je neverovatno lako da testirate i debagirate svoje hukove.

Debagiranje veb hukova
Figure 133. Informacija tokom debagiranja veb hukova.

Još jedna odlična odlika ovoga je to što možete da ponovo isporučite bilo koji od podataka kako biste lako testirali svoj servis.

Za više informacija o tome kako da pišete veb hukove i za sve različite događaje koje možete da slušate, odite na GitHub Developer dokumentaciju koja se nalazi na https://developer.github.com/webhooks/.

GitHub-ov API

Servisi i hukovi vam omogućavaju da dobijate obaveštenja u vezi s događajima koji se dogode na vašim repozitorijumima, ali šta ako vam treba više informacija o ovim događajima? Šta ako treba da automatizujete nešto kao dodavanje kolaboratora ili dodavanje labela tiketima?

Ovde se GitHub-ov API pokazuje kao korstan. GitHub ima gomilu kranjih tačaka u svom API-ju koje vam omogućavaju da radite skoro sve što možete na vebsajtu, ali automatizovano. U ovom odeljku ćemo naučiti kako da autentifikujete i povežete se na API, kako da ostavite komentar na tiket i kako da promenite status zahteva za povlačenjem kroz API.

Osnove korišćenja

Najosnovnija stvar koju možete da uradite je običan GET zahtev na krajnjoj tački koji ne zahteva autentifikaciju. Ovo može da bude informacija dostupna samo za čitanje u vezi s projektom otvorenog koda. Na primer, ako želimo da saznamo nešto više o korisniku koji se zove schacon, pokrenućemo nešto ovako:

$ 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"
}

Postoji gomila krajnjih tačaka kao što je ova sa kojih možete da dobijete informacije o organizacijama, projektima, tiketima, komitovima — o svemu što javno možete da vidite na GitHub-u. Možete čak i da koristite API da renderujete proizvoljni Markdaun ili da nađete šablon za .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*
"
}

Komentarisanje na tiketu

Ipak, ako želite da delate na vebsajtu, na primer da komentarišete na tiket ili zahtev za povlačenjem ili želite da pogledate ili interagujete sa privatnim sadržajem, morate da se autentifikujete.

Postoji nekoliko načina da uradite to. Možete da koristite osnovnu autentifikaciju sa samo svojim korisničkim imenom i šifrom, ali u opštem slučaju je bolja ideja da koristite lični pristupni token. Možete da ga generišete iz kartice Applications na stranici sa podešavanjima.

Pristupni token
Figure 134. Generišite svoj pristupni token sa kartice Applications na stranici sa podešavanjima.

Pitaće vas da se odlučte za područje za ovaj token i za opis. Obavezno unesite dobar opis kako bi bilo lakše da uklonite token sa skripte ili aplikacije kada prestane da se koristi.

GitHub će vam pokazati token samo jednom, zato ga obavezno kopirajte. Sada možete da koristite ovo da potvrdite svoj identitet u skripti umesto da koristie korisničko ime i lozinku. Ovo je lepo jer možete da ograničite područje nad kojim želite da skripta dela, a token se može opozvati.

Pored toga, ovo vam povećava granicu stope. Bez autentifikacije, ograničeni ste na 60 zahteva po satu. Sa autentifikacijom, možete da napravite do 5000 zahteva po satu.

Hajde da isprogramiramo skriptu tako da napravi komit na jednom od tiketa. Recimo da želimo da ostavimo komentar na određenom tiketu, Issue #6. Da bismo uradili to, moramo da pošaljemo HTTP POST zahtev na repos/<korisnik>/<repozitorijum>/issues/<broj>/comments pomoću tokena koji smo upravo generisali kao zaglavlje autentifikacije.

$ 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:"
}

Ako sada odete na taj tiket, videćete Komentar postavljen korišćenjem GitHub API-ja. koji smo upravo uspešno poslali.

API komentar
Figure 135. Komentar postavljen korišćenjem GitHub API-ja.

Možete da koristite API da uradite skoro sve na sajtu — da napravite i podešavate prekretnice, da dodeljujete ljude tiketima i zahtevima za povlačenjem, da pravite i menjate labele, da pristupate podacima iz komita, da pravite nove komitove i grane, da otvarate, zatvarate i spajate zahteve za povlačenjem, da pravite i menjate timove, da komentarišete na linije koda u zahtevu za povlačenjem, da pretražujete sajt i tako dalje.

Promena statusa zahtevu za povlačenjem

Još jedan primer koji ćemo pogledati je rad sa zahtevima za povlačenjem, pošto to ume da bude jako korisno. Većina komitova mogu da imaju jedan ili više statusa povezani s njima i postoji API oji služi da dodate upit tom statusu.

Većina servisa za kontinualnu integraciju i testiranje koriste ovaj API da reaguju na guranje tako što testiraju kôd koji je gurnut, i onda izveštavaju da li je taj komit prošao sve testove. Možete da koristite ovo i da proverite da li je komit poruka formatirana kako valja, da li je podnosilac zahteva pratio sve smernice za doprinos, da li je komit valjano potpisan — mnogo toga.

Recimo da podesite veb huk na svom repozitorijumu koji gađa mali veb servis koji proverava string Signed-off-by u komit poruci.

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

post '/payload' do
  push = JSON.parse(request.body.read) # parsuj 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

Nadamo se da je ovo lako ispratiti. U ovom veb huk hendleru, pregledava se svaki gurnuti komit, i tražimo string Signed-off-by u komit poruci i konačno radimo POST preko HTTP-a na /repos/<korisnik>/<repozitorijum>/statuses/<komitov-SHA> krajnu tačku API-ja sa statusom.

U ovom slučaju možete da pošaljete stanje (uspeh tj. success, neuspeh tj. failure, greška tj. error), opis onoga što se desilo, odredišni URL na koji korisnik može da ode za više informacija i "kontekst" u slučaju da ima više statusa za jedan komit. Na primer, servis za testiranje može da obezbedi status, ali i servis za validaciju kao što je ovaj može takođe da obezbedi status — razlikuju se preko kontekst polja.

Ako neko otvori novi zahtev za povlačenjem na GitHub-u i ovaj huk se okine, videćete [_commit _status].

Status komita
Figure 136. Status komita preko API-ja.

Sada možete da vidite mali zeleni znak za štikliranje pored komita uz koji piše string Signed-off-by u poruci i crveni krstić kroz onaj gde je autor zaboravio da se potpiše. Možete i da vidite da zahtev za povlačenjem uzima status poslednjg komita sa grane i upozova vas ako je došlo do neuspeha. Ovo je veoma korisno ako koristite ovaj API za rezultate testa kako ne biste slučajno spojili nešto gde poslednji komit pada testove.

Oktokit

Iako smo sve radili kroz curl i jednostavne HTTP zahteve u ovim primerima, postoji nekoliko biblioteka otvorenog koda koje koriste ovaj API na idiomatskiji način. U trenutku kada je ovo pisano, podržani jezici su Go, Objektni C, Rubi i .NET. Pogledajte http://github.com/octokit za više informacija o ovome, jer oni rukuju većinom HTTP-a.

Nadamo se da će vam ovi alati pomoći da prilagotie GitHub svojim potrebama u skladu sa tokom rada koji koristite. Za punu dokumentaciju i ceo API kao i upustva za neke česte zadatke, pogledajte https://developer.github.com.