Make love, not var_dump())

Captain's Log

Her ne kadar "geliştirici istediği yöntemle kodu geliştirsin, geliştiriciyi sınırlamamalıyız" desek de, her geliştiricinin belirlenen "kod standartlarına" uymasını bekliyoruz. Biz de, içeride geliştirdiğimiz kodlarda bazı standartlar belirledik

Biz;
  • gönderilen PHP kodlarında syntax hatası olmaması (evet evet, milyon dolarlık şirketlerde, master branch'e syntax hatalı PHP kodu gidiyor hâla!!)
  • belirlenen PHP kodlama standartlarına uyması (biz Zend Standartlarını extend edip, satır başına karakter sayısını 80'den 120'ye çıkardık)
  • dosyalarda Byte Order Mark olmaması
  • tüm dosyaların 'unix endline'a sahip olması
  • yazılan tüm JavaScript dosyalarının JSHint'den geçirilmesi
gibi bir kaç tane standard belirledik.

Bu tip standardları, neredeyse daha önce çalıştığım her yerde belirlesem de, kimse bunlara uymamıştı (poker face). Biz, Sonsuzdöngü'de "bu böyle olmasın, standarda uymayan kod, hele hele syntax hatalı kod depoya hiç girmesin" diyerek, "insan gücü" harcadığımız code review'larda "abi bu fonkisyondan sonraki süslü parantesi aşağı alsaydın keşke, kod standardlarına uymuyor bu :(" dememek, insan gücünü daha faydalı şeyler için kullanmak için Muhafiz'ı geliştirdik. Muhafız, şimdilik bir pre-commit Git hook'u. Kısaca, eğer bu yukarıda belirttiğimiz standartlara uymayan bir kod varsa, commit etmeye çalıştığımızda "hoop hemşerim, bu dosyanın satır sonu Windows satır sonu? sen ne ayaksın" diyor ve commit'e izin vermiyor.


Nasıl kurulur?

İstediğiniz bir dizine
git clone git://github.com/sonsuzdongu/muhafiz.git
ile depoyu çekin. Şöyle bir dizin yapısına sahip olacaksınız.
├── git-hooks
│   └── pre-commit
├── README.md
└── src
    ├── AutoLoader.php
    ├── bootstrap.php
    ├── Exceptions
    │   ├── RuleFailed.php
    │   ├── RunnerNotDefined.php
    │   └── ToolNotFound.php
    ├── Muhafiz.php
    ├── Runners
    │   ├── Bom.php
    │   ├── Jshint.php
    │   ├── Lineend.php
    │   ├── Phpcs.php
    │   ├── Php.php
    │   └── RunnersAbstract.php
    └── Utils
        ├── Git.php
        ├── Log.php
        └── System.php
"src" ve "git-hooks" isimli iki ana dizin göreceksiniz. "src", Muhafız'ın çalışabilmek için gerek duyduğu PHP dosyaları, "git-hooks" dizini de, şimdilik sadece pre-commit hook'unun bulunduğu dizin.

Depodaki git-hooks dizinindeki pre-commit dosyasını, çalıştığınız projenin Git deposu içindeki .git/hooks/ dizini altına koyup, çalıştırılabilir olduğundan emin olun.



Daha sonra, git hook'larına, yukarıdaki src dizininin yerini göstermelisiniz. Bunun için çalıştığınız projede
$ git config muhafiz.bootstrap-file /MUHAFIZ/DEPOSUNUN/YERI/muhafiz/src/bootstrap.php
veya daha güzeli kullanıcı hesabınızda veya sistem genelinde etkin olması için
$ git config  --global muhafiz.bootstrap-file /MUHAFIZ/DEPOSUNUN/YERI/muhafiz/src/bootstrap.php
$ sudo git config --system muhafiz.bootstrap-file /MUHAFIZ/DEPOSUNUN/YERI/muhafiz/src/bootstrap.php

Âla :) Artık, commit'leriniz muhafız tarafından korunuyor :)

Hangi kontroller var?

Muhafız'da kontrolleri yapan runner'lar var. Bunlar, commit öncesi, stage'deki her dosyaya belli kurallar uyguluyorlar. Şu anda 5 tane "runner" var. Öntanımlı olarak hepsi aktif olsa da,
git config muhafiz.active-runners
git config parametresine, virgül ile ayrılmış runner listesi vererek, sadece o runner'ların çalışmasını sağlayabilirsiniz.

Runner'lar ise şunlar;

php

php dosyasının, syntax hatası olup olmadığını 'php -l' komut satırı aracı ile denetler, hata varsa commit'e izin vermez. Herhangi bir konfigurasyon parametresi yoktur.


phpcs

PHP CodeSniffer kullanarak, kodun standardlara uyup uymadığını kontrol eder. İki tane konfigurasyon parametresi vardır.

  • 'muhafiz.runners.phpcs.standard' : CodeSniffer'ın, kodu hangi standarda göre denetleyeceğini belirtir, öntanımlı olarak 'PEAR' standardında denetler (daha fazla bilgi)
  • 'muhafiz.runners.phpcs.report' : CodeSniffer'ın, hataları nasıl raporlayacağını belirtir, öntanımlı olarak 'emacs' biçiminde raporlar (daha fazla bilgi)

jshint

JSHint kullanarak, JavaScript dosyalarının standarda uyup uymadığını kontrol eder. Bir tane konfigurasyon parametresi vardır

  • 'muhafiz.runners.jshint.config' : JSHint seçeneklerinin bulunduğu JSON dosyasının yerini belirtir. Öntanımlı olarak '.jshintrc' dosyasından okumaya çalışır

bom

Dosyada, Byte Order Mark olup olmadığını kontrol eder. Eğer BOM varsa commit'e izin vermez. Herhangi bir konfigurasyon parametresi yoktur.


lineend

Dosyanın, belirlenen satır sonu karakterlerinden oluşup oluşmadığını kontrol eder. Eğer izin verilen satır sonu karakterlerinden farklı bir satır sonu varsa commit'e izin vermez. Bir tane konfigurasyon parametresi vardır.

  • 'muhafiz.runners.lineend.allowed' : 'unix' veya 'windows' degerlerini alır

Bu mudur?

Şimdilik budur. Muhafız'ın gideceği biraz daha yol var. post-receive hook'u olarak da çalışmasını sağlamak/denemek gerekecek mesela. Bir gecede ilk sürümü çıkmış, sonrasında yine bulunan ilk zamanda 3-4 saatte de diğer Runner'ları yazılmış olan bu gariban Muhafiz'in bir çok hatası/eksiği olabilir. Eğer "vay lan, güzel kafaymış, ben de buna bir Runner" yazayım derseniz https://github.com/sonsuzdongu/muhafiz adresinden forklayıp, pull request gönderebilir veya karşılaştığınız hataları bildirebilirsiniz. Şimdilik Ubuntu ve MacOsX'de denedik çalışıyor. Eğer herhangi bir hata görürseniz bildirirseniz seviniriz :)



2 gün sonra gelen güncelleme: Artık, pre-receive hook'u olarak da kullanabiliyorsunuz. Bu, yukarıdaki denetimleri istemci bazında değil, sunucu bazında da yapabiliyorsunuz demek :)

4 ay sonra gelen güncelleme: Artık, "şu şu regexp desenine uyan dosyalara kural uygulama" (exclude-path) ve sunucu tarafında (pre-receive), "şu şu branch'lere push yasak"(disabled-branches) diyebiliyorsunuz :)