Git hooks, Git'in "commit, push, receive" gibi komut kullanımlarının öncesinde ve sonrasında tetiklenmesini sağlayan kabuk "shell, bash" dosyalarıdır. Git hooks standart Git yüklemesi ile gelen yerleşik bir özelliktir, ayrıca indirilmesine ve kurulmasına gerek yoktur. Git hooks, local olarak çalıştırılır.
Git hooks, geliştiricinin hayal gücüne bağlı olarak kullanılabilir.
Her deponun kendine ait bir .git/hooks klasörü ve içinde her hooks için bir dosyası bulunur.
Konun daha iyi anlaşılması için aşağıda yazdığımız kodları git üzerinde commit yapmadan kontrol eden bir script yazacağız. Python programlama dili ile geliştirdiğimiz https://github.com/huseyinozdemir/pythontr_api [github.com] deposu için bu yapıyı uygulayabiliriz.
Senaryomda yapmak istediğim commitlemeden yada pushlamadan önce git tarafından yazdığım unit testleri çalıştırılsın ve ardından flake8 için uygunluğu kontrol edilsin ve ben bu projeyi docker-compose kullandığım için yapıma uygun bir şekilde çalışsın.
Benim tercihim pre-commit şimdi bunun üzerinde senaryomuzu uygulamamıza uygulayalım. .git klasörünün bulunduğu dizininde olduğumuzu varsayıyorum.
mkdir scripts vim scripts/run-django-tests.sh
#!/usr/bin/env bash # kod icerisinde herhangi bir dosya hata dondururse cık ve olusan hatayi döndur set -e # hangi dizinde olursak olalım uygulamamızın kok dizini uzerinden calismasi icin cd "${0%/*}/.." echo "Running unit test and flake 8 for Django Framework on Docker Container" echo "............................" docker-compose run --rm app sh -c "python manage.py test && flake8"
Yukarıdaki kod satırlarında açıklamalara yer vermeye çalıştım bu kodumuz bizim unit test imizi ve flake8 çalıştırır ardından yazılım çıktısını verir ayrıca uygulama sonlandığı zaman bunun flag değerini döndürecektir.
Farklı diller için ve docker kullanmıyor iseniz aşağıdaki kullanımlara bakabilirsiniz.
vim scripts/pre-commit.sh
#!/usr/bin/env bash echo "Running pre-commit hook" ./scripts/run-django-tests.sh # $? son komut sonlanma degerini saklar if [ $? -ne 0 ]; then echo "Unit Tests or Flake8 must pass before commit!" exit 1 fi
Bu betik dosyamız ise bir önceki yazdığımız kontrol dosyasını tetikler sonlanma değerine göre süreci devam ettirir yada sonlandırır.
vim scripts/install-hooks.sh
#!/usr/bin/env bash GIT_DIR=$(git rev-parse --git-dir) echo "Installing hooks..." ln -s ../../scripts/pre-commit.sh $GIT_DIR/hooks/pre-commit echo "Done!"
Install işleminde aslında yaptığımız iş path verme symblink link oluşturma işlemidir.
Yazdığımız dosyaları çalıştırabilir hale getirmek için gerekli izinlerimizi verelim.
chmod +x scripts/run-django-tests.sh scripts/pre-commit.sh scripts/install-hooks.sh
Ardından aşağıdaki şekilde install betik dosyamızı çalıştıralım.
./scripts/install-hooks.sh Installing hooks... Done!
Evet şimdi testlerimizi yapalım örnek olarak yazdığım ünit testlerden birinde değişiklik yapıyorum bakalım sonuç ne olacak.
git add . git commit -m "test" Running pre-commit hook Running unit test and flake 8 for Django Framework on Docker Container ............................ Starting pythontr_api_db_1 ... done Creating test database for alias 'default'... System check identified no issues (0 silenced). .........Waiting for database... Database unavailable, waiting 1 second... Database unavailable, waiting 1 second... Database unavailable, waiting 1 second... Database unavailable, waiting 1 second... Database unavailable, waiting 1 second... Database available! .Waiting for database... Database available! ....................F............ ====================================================================== FAIL: test_comment_create (recipe.tests.test_comment_api.PublicCommentApiTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/app/recipe/tests/test_comment_api.py", line 41, in test_comment_create self.assertEqual(res.status_code+2, status.HTTP_201_CREATED) AssertionError: 203 != 201 ---------------------------------------------------------------------- Ran 43 tests in 7.685s FAILED (failures=1) Destroying test database for alias 'default'... Unit Tests or Flake8 must pass before commit!
Süper tam istediğim şekilde çalıştı. Fakat burada bilmemiz gereken bir konu var continuous integration süreçleriyle ilgili takım üyelerinin bu konuda bilinçlendirilmesi önemlidir. Evet bu yapı git sunucu tarafında kurulabilir fakat ben localde kullanmayı tavsiye ediyorum. Ayrıca son olarak aşağıdaki şekilde bu yapıyı atlayabiliriz.
--no-verify flagı kullanarak bu hooks a takılmada commitleyebiliriz.
git commit --no-verify -m "test"
Yorumlar
Cok faydalı bir yazı olmuş, çok teşekkürler, herhangi bir sorum olduğumda ileteceğim,