18 Aug

Gittegylet 4 - Jegyeket, bérleteket


A verziókövetésnek bármelyikről is beszéljünk, van egy bizonyos workflow-ja, amit ha nem is teljesen, de egyes részeit bizonyára megismertük már a használat közben. A Git, más rendszerekhez hasonlóan biztosít lehetőséget arra, hogy leszálljunk a buszról, mielőtt a közteresek megjönnek ha belenyúlni nem is, plugin módjára hozzácsapjunk ezt azt a workflow bizonyos pontjaihoz. Aki vette a bátorságot és foglalkozott népszerű CMS-ekkel, annak a hook fogalma nem lesz ismeretlen.


A lényege annyi, hogy egy adott actionhöz hozzáakasztunk egy általunk készített actiont.
Mielőtt egyesek infarktus közeli állapotba kerülnének, nem, nem a git kódjában fogunk túrkálni, habár némi bash script tudás nem árt majd. Ha beletúrtunk igényesen a .git mappába, akkor bizonyára találkoztunk már a hooks könyvtárral, esetleg a tartalmával is. Nos ennek semmi köze a kalauzokhoz kalózokhoz, viszont a témánkhoz annál inkább:Captain_Hook_(Hook)



Mi kell ahhoz, hogy mindezt életre leheljük?


Nos, első körben kitartás az, hogy a script neve pontosan megegyezzen azzal, amit a kedves Git-ünk keresni fog. A másik pedig az, hogy futtatható legyen az adott felhasználó által. Ez a felhasználó lehet az, akivel beSSH-zunk, vagy a webszerver usere, ha HTTPS-en keresztül csináljuk, vagy éppen mi, ha lokálban piszkáljuk. Nem történik itt semmi más csoda, csupán annyi, hogy amikor a git az adott workflow-hoz ér, megnézi a hooks könyvtárat és keresi az action-höz tartozó hook-ot. Ha megtalálja, akkor megpróbálja elindítani és ha elindult, akkor a process visszatérési értéke (Exit code) alapján csinál/nem csinál valamit.
A script lehet bash script, perl, python, php, stb. Amíg a bemeneti paraméterek és az exit code stimmel.

A hook-okat feloszthatjuk két csoportra, kliens és szerveroldaliakra. Most nézzük először a kliensoldaliakat:
Commit specifikus hook-ok:

Ezek a script-ek a commit folyamat bizonyos pontjain hívódnak meg. Név szerint:
pre-commit, prepare-commit-msg, commit-msg

Pre-commit

Ez a script fog először lefutni amikor commitolunk, még a commit message képernyő előtt. A kódot szokták ezen a ponton ellenőrízni, hogy bizonyos minőségügyi követelményeknek megfelel-e, mielőtt beengednék a verziókövetésbe. Az ilyen ellenőrzések közé tartozik a lint ( php -l ), a tesztek lefuttatása, PHP mess detector,  Check style és hasonlók.

Na de nézzük meg hogy is lehet ebbe a fájlba beleoktrojálni valami finomságot (és nem, most nem evil perl script lesz az, ami életünk hátralevő részében kísérteni fog, hanem plain PHP)!
#!/usr/bin/env php // php lesz az interpreterünk

<?php 

$allFiles = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(__DIR__."/../../")); // itt egy recursive iteratoron át lekérjük a könyvtárban található összes fájlt

$phpFiles = new RegexIterator($allFiles, '/\.php$/'); // majd leszűkítjük a kört a .php végződésűekre.


foreach ($phpFiles as $file) { // ha már iterátor, akkor végigiterálunk rajta

 $retval = 0; 
 $escapedFile = escapeshellarg($file); // escapeljük a shell argumentumnak valót

 echo exec('php -l ' . $escapedFile, $output, $retval)."\n"; // majd futtatunk a fájlon egy syntax analízist a php interpreterünkel és kiíratjuk az output-ot

 if ($retval !== 0) { // ha a visszatérési érték nullától eltérő,

    exit(1); akkor bizony mi se nullával fogunk visszatérni és ezzel a commit-nak elejét is vettük
 } 
} 
exit(0);
?>

A fenti script segíthet nekünk abban, hogy végignyálazzuk a fájljainkat, syntax errorokra vadászva. Nem egy atomfizika, ugye? Ezeket persze ki lehet szervezni fájlokba és akkor sokkal egyszerűbben lehet rendszerezni az egészet.
Prepare-commit-msg

Ez a script akkor fut le, mikor az iménti pre-commit végzett és még nem készült el a commit message, viszont egy default message már készen áll. Ennek a default message-nek a szerkesztésére és módosítására szolgál ez a hook. Itt már paraméterként kapunk ezt-azt, mégpedig: a fájl nevét, amiben a commit message található amit megadtunk az -m paraméterrel, a commit típusát, valamint a SHA-1 azonosítóját a commitnak, ha amend commitról van szó. Nézzük csak meg, mit tudunk ezzel kezdeni!
#!/usr/bin/env php

<?php 

$name = "user.name="; // a config kiíratásakor ebben a sorban lesz a név

$email = "user.email="; // ebben pedig az e-mail cím



if (array_key_exists(1,$argv)) { // megnézzük, hogy van-e commit message fájl, 

 $commit_msg = file_get_contents($argv[1]); // beolvassuk a meglévő commit message-et

 exec('git config -l', $output); // kiíratjuk a config beállításokat

 foreach ($output as $row) { // végigiterálunk a git config outputjának sorain

   if (strpos($row, $name) !== false) { // ha megtaláljuk a nevet

     $commit_msg .= " by ". substr($row, strlen($name)); // hozzácsapjuk az üzenethez

   } elseif (strpos($row, $email) !== false) { // ha az e-mailt is,

     $commit_msg .= "<".substr($row, strlen($email)). ">";  // akkor azt is

   }
 }
 file_put_contents($argv[1], $commit_msg); // végül felülcsapjuk a régi commmit message-et tartalmazó fájllal

 
}

exit(0); // és visszatérünk 0-val.

A fenti hook sem túl bonyolult, csupán annyit csinál, hogy a már meglévő commit message után fűzi a gitben megadott username-t és emailt. Így az "Initial commit"-ból

"Intial commit by Felhasználónév<email@cim>" lesz. Sajnos túl sok más use-case-t nem találtam erre a hookra, úgyhogy sunyi módon tovább is lépnék :)
Commit-msg

Ez a hook a commit message validálására szolgál. Ha 0-tól különböző kóddal tér vissza, akkor a commit folyamat megszakad.
#!/usr/bin/env php

<?php
if (array_key_exists(1,$argv)) {
 $commit_msg = file_get_contents($argv[1]); // kinyerjük a commit message-et

 
 if (strlen($commit_msg) < 5) { // ha az üzenet hossza kisebb, mint 5 karakter,

   echo "Commit message must be at least 5 characters!\n"; // kiírjuk a hibaüzenetet

   exit(1); // akkor visszatérünk 1-el, így megszakad a commit

 }
 exit(0); // ellenkező esetben továbbengedjük azt

}
exit(1); // ha nincs commit message fájl, akkor is visszadobjuk a commit-ot.



Fontos! Amikor a repóból lerántjuk a dolgokat, pl. clone-al, akkor a kliensoldali hook-ok NEM jönnek vele együtt,

 

Egyelőre a hookokról ennyit, kapkodtam kicsit, de már régóta ígértem (valakinek :P).

A legközelebbi cikkemben szó lesz egyéb kliensoldal hook-okról, valamint arról is, mivel lehet a szerveroldalon megpiszkálni a dolgokat!

Hozzászólások betöltése
2014-2018 © Letscode.hu. Minden jog fenntartva. Build verzió: 1.2.11