Git hooks

Kilka prostych hooks, które przydadzą się dla osób pracujących z git/gitlab oraz bugzilla i redmine. Dzięki nim można zautomatyzować trochę nasze procesy commit oraz push. A co najważniejsze: wszystko to możemy napisać w php.

Nazwa bugu z bugzilli w komentarzu

Załóżmy, że pracujemy z bugzilla. Gdy pracujemy nad jakimś błędem z bugzilli to tworzymy branch o nazwie bug/12345 gdzie 12345 jest numerem błędu w bugzilla. Teraz komitując coś w naszym branchu chcemy by komentarz zawierał nazwe błędu z bugzilla by łatwo mozna było zidentyfikować błąd nad którym pracowalismy.

W tym celu dodajemy hook do naszego projektu git ./git/hooks/prepare-commit-msg o następującej treści:

#!/usr/bin/php
<?php
define('BUG_USER', 'username'); //nasz user do bugzilla
define('BUG_PASS', 'password'); //nasze haslo do bugzilla
define('BUG_URL', 'http://link.to.your.bugzilla/'); //adres do naszego projektu bugzilla
function writeMessage($bugNumber, $oldMessage, $bugSummary = '') {
    global $argv;
    $message = $bugNumber;
    if ($bugSummary) {
        $message .= ': ' . $bugSummary;
    }
    if ($oldMessage) {
        $message .= ': ' . $oldMessage;
    }
    file_put_contents($argv[1], $message);
}
$message = trim(file_get_contents($argv[1]));
$currentBranch = trim(exec('git symbolic-ref --short HEAD'));
$ar = explode('/', $currentBranch);
//sprawdzamy czy nazwa branch to bug/bugnumber
if (count($ar) !== 2 || $ar[0] !== 'bug' || !is_numeric($ar[1])){
    exit;
}
$bugNumber = $ar[1];
//logujemy się do naszej bugzilli
$loginResponse = json_decode(file_get_contents(BUG_URL . 'rest/login?login=' . BUG_USER  . '&password=' . BUG_PASS), true);
if (empty($loginResponse['token'])){
    writeMessage($bugNumber, $message);
    exit;
}
$token = $loginResponse['token'];
//pobieramy info o błędzie z bugzilli
$bugResponse = json_decode(file_get_contents(BUG_URL . 'rest/bug/' .$bugNumber. '?token=' . $token), true);
if (empty($bugResponse['bugs'])){
    writeMessage($bugNumber, $message);
    exit;
}
//dodajemy nazwe błędu do naszego komentarza w commit
writeMessage($bugNumber, $message, $bugResponse['bugs'][0]['summary']);

Po stworzeniu powyższego hook gdy odpalimy w commit w naszym branchu bug/12345

git commit -m ''

Zostanie zrobiony commit z komentarzem: 12345: bug summary. Zaś gdy chcemy mieć też własny komentarz:

git commit -m 'nasz komentarz'

Zostanie zrobiony commit z komentarzem: 12345: bug summary: nasz komentarz.

Gitlab do bugzilla

No dobra, nadal pracujemy z bugzilla ale teraz jeszcze mamy do dyspozycji gitlab. Teraz gdy ktoś wrzuci jakiś branch do gitlab to chcielibyśmy mieć info o tym w naszym bugu w bugzilla. W tym celu na serwerze gdzie jest gitlab wrzucamy następujący hook /var/opt/gitlab/git-data/repositories/GITLAB_PROJECT.git/custom_hooks/post-receive o następującej treści:

#!/usr/bin/php
<?php
function getAuthor($revision) {    
    //tablica z userami w bugzilla
    //można tu ustawić tylko jednego domyślnego usera i wszystkie komentarze w bugzilla będą dodawane przez tego usera
    $authors = [
        'author1' => 'password1',
        'author2' => 'password2',
    ];
    //Pobranie email z rewizji
    $text = trim(exec("git show $revision | grep 'Author'"));
    preg_match('/<(.*?)>/', $text, $matches);
    $email = $matches[1];
    
    $key = isset($authors[$email]) ? $email : key($authors);
    return [
        'email' => $email,
        'credentials' => ['user' => $key, 'password' => $authors[$key]]
    ];
}
define('BUG_URL', 'http://link.to.your.bugzilla/'); //adres do naszej bugzilli
define('GITLAB_URL', 'http://link.to.your.gitlab/'); //adres do naszego gitlab
$stdin = fopen('php://stdin', 'r');
$line = trim(fgets(STDIN));
$ar = explode(' ', $line);
if (count($ar) !== 3) {
    exit;
}
//pobranie nazwy projektu
$path = exec('echo $PWD');
$search = [
    '/var/opt/gitlab/git-data/repositories/',
    '.git'
];
$projectName = str_replace($search, '', $path);
$revision = $ar[1];
if ($revision === '0000000000000000000000000000000000000000') { //gdy usuniemy branch po jego zmergowaniu do master to takie kwiatki możemy mieć
    exit;
}
//pobranie nazwy brancha
$branchName = str_replace('refs/heads/', '', $ar[2]);
$ar = explode('/', $branchName);
//sprawdzenie czy branch ma nazwe bug/bugnumber
if (count($ar) !== 2 || $ar[0] !== 'bug' || !is_numeric($ar[1])){
    exit;
}
$bugNumber = $ar[1];
$author = getAuthor($revision);
//zalogowanie do bugzilli
$loginResponse = json_decode(file_get_contents(BUG_URL . 'rest/login?login=' . $author['credentials']['user']  . '&password=' . $author['credentials']['password']), true);
if (empty($loginResponse['token'])){
    exit;
}
$token = $loginResponse['token'];
$comment = "Code change by $author[email]:
    Latest change
    " . GITLAB_URL . "{$projectName}/commit/$revision";
//dodanie komentarza do błędu w bugzilli
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, BUG_URL . 'rest/bug/' .$bugNumber. '/comment?token=' . $token);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true );
curl_setopt($curl, CURLOPT_POSTFIELDS, [
    'comment' => $comment,
    'is_private' => false,
    'is_markdown' => false,  
]);
curl_exec($curl);
curl_close($curl);

Po stworzeniu tego hook, gdy wrzucimy jakiś branch bug/12345 do gitlab, w danym bug w bugzilli zostanie dodany komentarz z linkiem do naszego wrzutu w gitlab. Dzięki temu można bardzo łatwo śledzić w bugzilla wszelkie zmiany dla danych błędów.

Hash redmine w komentarzu

Teraz coś dla osób pracujących z redmine. Pracując nad jakimś zadaniem z redminem chcemy, by razem z komitem szedł hash z numerem zadania z redmine, dzięki czemu w redmine będziemy mogli śledzić zmiany w zadaniach. W tym celu tworzymy hook w naszym projekcie git ./git/hooks/prepare-commit-msg o treści:

#!/usr/bin/php
<?php
function writeMessage($bugNumber, $oldMessage) {
    global $argv;
    $message = $oldMessage;
    if ($bugNumber) {
        $message .= ' refs #' . $bugNumber;
    }
    file_put_contents($argv[1], $message);
}
$message = trim(file_get_contents($argv[1]));
$currentBranch = trim(exec('git symbolic-ref --short HEAD'));
$ar = explode('/', $currentBranch);
$bugNumber = end($ar);
//sprawdzenie czy ostatni człon nazwy brancha to numer
if (!is_numeric($bugNumber)){
    exit;
}
writeMessage($bugNumber, $message);

Teraz gdy już mamy hook i gdy zamierzamy pracować nad jakimś zadaniem z redmine tworzymy branch o nazwie np. feature/12345 - ważne by ostatnim członem był numer zadania w redmine. Gdy będziemy robić commit na naszym branchu zostanie dodany na koniec naszego komentarza hash z numerem zadania z redmine co umożliwi nam śledzenie zmian z poziomu redmine.

Podsumowanie

Wszystkie opisane tu hooks możecie znaleźć na moim github

ps: Pamiętajcie, by wszystkie pliki hooks tworzyć jako pliki wykonywalne.

Komentarze

 

Dodaj komentarz

 

Dostępne bbcode: b, u, i, url, code, php, css, html, sql, js

Skrypty użytkowników

  1. Klasa obsługi szablo... Lirdoner
  2. Sekcje user76
  3. Klasa walidująca for... user76
  4. Licznik Gości online korey
  5. Form Builder Comandeer
  6. Dynamiczny licznik z... korey
  7. Captcha Comandeer