Husky ile Git Hook’larını Yakalamak ve Yönetmek
Girizgah
Geliştirdiğimiz uygulamalarda kod kalitesini arttırmak için kimi denetlemeler yapmak, testlerimizi koşturmak, kullandığımız üçüncü parti bağımlılıklarda zafiyet taraması yapmak ve sair sebeplerden ötürü önceden tanımladığımız betikler (script) çalıştırmaya ihtiyaç duyuyoruz.
Tanımlanan bu betikleri her defasında elle çalıştırmak, özellikle yoğun tempoda çalışılan dönemlerde unutulmaya teşne olabiliyor. Kimi zaman da kasıtlı olarak ya da ihmal sonucu göz ardı ediliyor. Bunun önüne geçmek için süreci otomatikleştirmek ilk akla gelen çözüm. Asıl husus bu otomatikleştirmenin nerede yapılacağı.
İlgili kontrolleri yazdığımız kodun test ortamına veya canlı ortama çıkmadan hemen öncesine yani Continuous integration adımlarına konumlandırabiliriz. Bu tercihin şöyle olumsuz yönleri var.
- Bir testimiz geçmediğinde veya kullandığımız bağımlılıklarda bir zafiyet tespit edildiğinde tamamen koptuğumuz sürece yeniden dahil olmak durumundayız. İlgili değişiklikleri yapmamızın üstünden belli bir zaman geçmiş ve yaptıklarımızı unutmuş olabiliriz. Tüm süreci her defasında yeniden hatırlamak ve yaşamak zorundayız.
- Bulut hizmet sağlayıcıları CI/CD pipeline ücretlendirmelerini ekseriyetle çalışılan süre üzerinden yapıyor. Test çalıştırmak, kod denetlemek gibi işlemlerin sorumluluğunu her defasında CI araçlarına bırakırsak yekûn olarak baktığımızda günün sonunda ciddi bir maliyet oluşuyor.
İki durumda da zaman ve maliyet olarak gereksiz bir kayıp var.
Bunun alternatifi ilgili kontrolleri geliştirme ortamımızda yapmak. Fakat onun da şöyle dezavantajları var.
- Geliştirme ortamımızda tüm kontrollerimizi yapıp ilgili değişiklikleri uzak sunucuya gönderdik diyelim. Fakat yazdığımız kod bir sebepten (kod review vs.) test ortamında veya canlı ortama derhâl gitmedi. Bu arada geçen meçhul zamanda dış ortama bağlı şartlarda değişiklikler olabilir. Kodumuz değişmeyeceği için testlerimiz yine geçer fakat bir güvenlik zafiyetinden haberdar olmamız mümkün olmaz.
- Kodumuz değişmez dedik ama bir başka arkadaşımız kodumuzda değişiklik yapmış ve kendi geliştirme ortamında çalıştırması gereken testleri ihmal etmiş olabilir. Bundan da maalesef haberimizin olması ve hatalı kodun canlı ortama çıkmasına engel olmamız mümkün değil.
O yüzden en sonda söyleyeceğimi başta söylemiş olayım. Aynı kontrolleri hem geliştirme ortamımızda hem de CI araçlarında yapmak zaman, maliyet ve tutarlılık bakımından pratik bir yöntem olacaktır. Önem derecesine göre kimi kontrolleri CI sürecine hiç dahil etmemek de tartışılabilir fakat onu başka bir yazının konusu yapayım.
Husky 🐶
Tekrar geliştirme ortamımıza dönelim. İlgili kontrolleri elle çalıştırmanın unutulmaya teşne olduğundan bahsediyorduk. Tam burada imdadımıza Husky yetişiyor. Husky, JavaScript ekosistemi içerisinde geliştirilen uygulamalardapre-commit
, post-commit
, pre-push
, commit-msg
gibi tüm Git hook’larını yakalamamızı ve yönetmemizi sağlayan bir araç. Bu sayede bir anda envaitürlü senaryoyu uygulayabilir hâle geliyoruz. Kullanımı da oldukça basit, hemen başlayalım ve Husky’i projemize dahil edelim.
npm install husky
Akabinde kod formatımızın uygunluğunu kontrol etmesi için Prettier’ı da projeye dahil edelim.
npm install prettier
Konumuz Husky olduğu için Prettier’a herhangi bir özel kural tanımlamayıp varsayılan yapılandırmasıyla bırakacağız. Prettier’ın CLI aracı check
isimli bir parametre alıyor. Bu parametrede hangi dizindeki hangi dosyalar için format kontrolü yapılacağını belirtiyoruz. Bu kontrolü tetikleyecek bir betik oluşturup package.json
dosyasındaki scripts
objesine ekliyoruz.
Artık npm run prettier
komutunu çalıştırdığımızda Prettier, JavaScript dosyalarımızın formatını kontrol edecek. Hemen içerisinde girintileme stil hatası olan bir dosya oluşturup ardından Prettier’ı çalıştıralım.
Görüleceği üzere Prettier dosyamızdaki hatayı buldu ve bizi uyardı. Şimdi bu süreci commit öncesini yakalamamızı sağlayan pre commit
hook’u içerisinde otomatikleştirelim.
Bunun için projemizin ana dizinine husky.config.js
isminde bir dosya oluşturup hangi hook’da hangi komutun çalıştırılması gerektiğini CommonJS formatında yazarak belirtelim.
Ardından yaptığımız değişiklikleri commit etmeye çalışalım.
Husky, Git’in pre commit
hook’unu yakaladı ve commit öncesinde belirttiğimiz gibi npm run prettier
komutunu çalıştırdı. Prettier’ın format doğrulaması başarılı olamadığı için işlem yarıda kesildi ve herhangi bir commit atılmadı.
İlgili dosyadaki girintilemeyi düzeltip yeniden commit etmeye çalıştığımızda herhangi bir hata almadan işlemi tamamlayabildik.
Aslında Husky’nin yaptığı kabaca bundan ibaret. Husky’nin bu kabiliyeti, Git hook’larının marifetleriyle birleştirildiğinde yukarıda da söylediğim gibi envaitürlü senaryo canlanıyor insanın zihninde. Neler yapılabilir mesela? commit-msg
hook’unda bir önceki yazımda bahsettiğim şekilde konvansiyona uygun commit mesajları yazılması sağlanabilir. Yine pre-commit
hook’unda birim testler koşturulabilir veya NPM Audit çalıştırılabilir. pre-push
ile değişiklikler uzak sunucuya gönderilmeden önce atlanmaması gereken son kontroller yapılırkenpre-rebase
ile rebase öncesi ortam hazırlanabilir. Bu noktada yapılabilecekler tamamen ihtiyaçlara ve geliştiricilerin hayal gücüne kalmış durumda.
Tahmin ediyorum 2020'nin son yazısı bu oldu. Fena bir kapanış olmadığı kanaatindeyim. Yeni senede daha sık görüşmek üzere!
Kaynaklar
https://typicode.github.io/husky
https://github.com/typicode/husky