Merhaba! Bir önceki dersimizde, ruff aracını kullanarak PySpark ETL projemizdeki kod kalitesini artırmak için linting ve formatting kurallarını nasıl yapılandıracağımızı öğrendik. Bu kuralları manuel olarak çalıştırmak, kodumuzu belirli bir standarda getirmek için harika bir yöntem. Ancak, bu süreci her seferinde hatırlamak ve manuel olarak tetiklemek zamanla verimsiz hale gelebilir.
Bu derste, bu kalite kontrol sürecini otomatikleştireceğiz. Hedefimiz, "kirli" veya standart dışı kodun Git reposuna dahil edilmesini en başından, yani commit aşamasında engellemek.
Öğrenme Hedefimiz: git commit işlemi öncesinde ruff ile linting ve formatting kontrollerini otomatik olarak çalıştırmak için pre-commit hook'ları kurmak.
Bu, CI/CD'ye giden yolda "sola kaydırma" (shift-left) prensibinin mükemmel bir örneğidir: Hataları ve tutarsızlıkları geliştirme döngüsünün mümkün olan en erken aşamasında yakalamak.

Git Hooks ve pre-commit Çerçevesi Nedir?
Projenizdeki .git klasörünü hiç merak ettiniz mi? Bu klasör, versiyon geçmişinizin yanı sıra "hooks" adı verilen bir mekanizma da içerir. Git hook'ları, commit, push gibi belirli Git olayları gerçekleşmeden önce veya sonra çalışan betiklerdir (script'ler). pre-commit hook'u, bir commit mesajı yazılıp commit işlemi tamamlanmadan hemen önce çalışır.
Bu hook'ları manuel olarak yönetmek karmaşık olabilir. İşte bu noktada pre-commit Python paketi devreye giriyor. Bu araç:
.pre-commit-config.yamladlı basit bir yapılandırma dosyası ile hook'ları yönetmenizi sağlar.- Farklı dillerde yazılmış yüzlerce hazır hook'u kolayca projenize eklemenize olanak tanır.
- Ekipteki herkesin aynı hook'ları kullanmasını sağlayarak tutarlılığı artırır.
Bu konsepti daha iyi anlamak için kısa bir video izleyelim.
The easy way to keep your repos tidy.
mCoding kanalından bu video, Git hook'larının ne olduğunu ve pre-commit çerçevesinin bu süreci nasıl basitleştirdiğini mükemmel bir şekilde açıklıyor.
Videonun ilk 1 dakika 32 saniyesini (00:00 - 01:32) izleyin. Konuşmacının, Git'in .git/hooks dizinini nasıl kullandığını ve pre-commit aracının neden bu hook'ları yönetmek için daha pratik bir çözüm olduğunu nasıl açıkladığına dikkat edin.
Projemize pre-commit Kurulumu
Şimdi bu güçlü otomasyon aracını projemize entegre edelim.
1. Kurulum
Öncelikle, pre-commit paketini Python ortamımıza kuralım. Projenizin ana dizinindeki terminalde şu komutu çalıştırın:
pip install pre-commit
2. Yapılandırma Dosyası Oluşturma
pre-commit, yapılandırmasını projenizin ana dizinindeki .pre-commit-config.yaml dosyasından okur. Bu dosyayı şimdi oluşturun ve içine aşağıdaki temel yapıyı ekleyin.
# .pre-commit-config.yaml
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.4
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- id: ruff-format
Bu yapılandırma ne anlama geliyor?
repos: Hook'ları içeren Git repolarının bir listesidir.repo: Hook'un bulunduğu GitHub reposunun URL'si.rev: Kullanılacak reponun spesifik bir etiketi (versiyonu). Bu, hook'ların zamanla beklenmedik şekilde değişmesini engeller.hooks: Bu repodan kullanmak istediğimiz hook'ların listesi.id: Hook'un benzersiz kimliği.args: Hook çalıştırılırken kullanılacak komut satırı argümanları.ruffiçin--fixargümanı, bulunabilen hataları otomatik olarak düzeltmesini söyler.exit-non-zero-on-fixise bir dosya düzeltildiğinde commit işlemini durdurur, böylece düzeltilmiş halini kontrol edip yenidengit addyapabilirsiniz.
Bu örnekte iki repo tanımladık:
pre-commit-hooks: Dosya sonu boşlukları, YAML sözdizimi doğruluğu gibi genel dosya temizliği görevleri için standart hook'lar içerir.ruff-pre-commit: Önceki derste yapılandırdığımızrufflinter'ını ve formatlayıcısını çalıştıran resmi hook'ları içerir.
Bu yapılandırma sürecini adım adım görmek için aşağıdaki kaynağı inceleyebilirsiniz.
Top pre-commit hooks for Data / ML / Analytics projects
Bu Medium makalesi, veri projeleri için popüler pre-commit hook'larını listelerken, ruff için yapılandırmayı net bir şekilde gösteriyor.
Makalenin 'pre-commit configuration' bölümündeki YAML örneğini ve hemen altındaki 'Python lint + format — Ruff' başlığını inceleyin. ruff-pre-commit reposunun nasıl eklendiğine ve amacının ne olduğuna odaklanın.
3. Git Hook'unu Yükleme
Yapılandırma dosyamız hazır. Şimdi pre-commit'e bu yapılandırmayı kullanarak asıl Git hook betiğini oluşturmasını söylemeliyiz. Bu işlemi projenizde yalnızca bir kez yapmanız yeterlidir:
pre-commit install
Bu komut, .git/hooks/pre-commit yolunda bir betik oluşturur. Artık git commit komutunu her çalıştırdığınızda, bu betik otomatik olarak .pre-commit-config.yaml dosyanızdaki hook'ları çalıştıracaktır.
pre-commit'i İş Başında Görelim
Teoriyi pratiğe dökme zamanı!
Uygulama Adımları:
- Projenizdeki herhangi bir Python dosyasına (örneğin,
transformations.py) gidin ve kasıtlı olarak bir stil hatası yapın. Örneğin, bir fonksiyonun başına kullanılmayan bir import ekleyin veya formatlamayı bozun.import os # Kullanılmayan import def my_function ( a, b ) : # Kötü formatlama return a+b - Bu değişikliği Git'e ekleyin ve commit etmeye çalışın:
git add . git commit -m "Test: pre-commit ile hatalı kod" - Terminal çıktısını izleyin.
pre-commit'in devreye girdiğini ve tanımladığınız hook'ları sırayla çalıştırdığını göreceksiniz.

ruff hook'u, yaptığınız hataları (kullanılmayan import, kötü formatlama) tespit edecek ve --fix argümanı sayesinde bunları otomatik olarak düzeltecektir. Ancak, dosyalar değiştirildiği için commit işlemi başarısız olacaktır. Çıktıda "files were modified by this hook" gibi bir mesaj görmelisiniz.
- Bu çok önemlidir:
pre-commitdosyalarınızı düzeltti, ancak bu düzeltilmiş halleri henüz "staged" (hazırlık aşamasında) değil.git statuskomutunu çalıştırırsanız,rufftarafından değiştirilen dosyaları göreceksiniz. - Düzeltilmiş dosyaları tekrar
git addkomutuyla hazırlık alanına ekleyin ve commit işlemini tekrarlayın:git add . git commit -m "Test: pre-commit ile hatalı kod" - Bu sefer, hook'lar tekrar çalışacak, ancak düzeltilecek bir sorun bulamadıkları için hepsi "Passed" durumunda olacak ve commit işleminiz başarıyla tamamlanacaktır.
Bu döngüyü (commit -> fail -> re-add -> re-commit) gösteren videoyu izleyerek süreci pekiştirelim.
The easy way to keep your repos tidy.
mCoding'in videosundaki bu bölüm, bir commit'in pre-commit tarafından nasıl engellendiğini ve düzeltmelerden sonra nasıl başarıyla tamamlandığını canlı olarak gösteriyor.
Videonun 2:37 - 3:47 arasındaki bölümünü izleyin. Konuşmacının hatalı kodu commit etmeye çalıştığında commit'in nasıl başarısız olduğuna, formatlayıcının dosyayı nasıl düzelttiğine ve dosyayı tekrar ekledikten sonra commit'in nasıl başarılı olduğuna dikkat edin.
Hook'ları Manuel Çalıştırma
Bazen tüm projedeki dosyaları commit yapmadan kontrol etmek isteyebilirsiniz. Bunun için şu komutu kullanabilirsiniz:
pre-commit run --all-files
Bu komut, yapılandırmanızdaki tüm hook'ları projenizdeki ilgili tüm dosyalara karşı çalıştırır.
Sonuç
Tebrikler! Artık projenizin kod kalitesini otomatik olarak güvence altına alan bir sisteminiz var. pre-commit hook'ları sayesinde, tutarsız formatlama veya basit linting hataları gibi sorunlar, kod tabanınıza hiç girmeden engellenir. Bu, özellikle ekip olarak çalışırken veya sizin gibi kurumsal ölçekte sürdürülebilir veri işlem hatları geliştirirken paha biçilmez bir pratiktir.
Temel Çıkarımlar:
pre-commit, Git commit döngüsüne otomatik kalite kontrolleri ekleyen bir çerçevedir.- Yapılandırma, projenin kök dizinindeki
.pre-commit-config.yamldosyası ile yönetilir. pre-commit installkomutu, hook'ları yerel Git reponuz için etkinleştirir.- Bir hook dosyayı değiştirirse, commit başarısız olur. Düzeltilmiş dosyaları
git addile tekrar ekleyip yeniden commit etmeniz gerekir. - Bu otomasyon, kod kalitesini artırır ve kod incelemelerinde stil tartışmalarını azaltır.
Gelecek Dersin Önizlemesi:
Yerel ortamımızdaki kalite kontrollerini otomatikleştirdik. Peki ya bu kod, ana repoya gönderildiğinde ne olacak? Ekipteki başka birinin bu kontrolleri atlamadığından nasıl emin olabiliriz? Bir sonraki modülde, bulutta çalışan ve kod her itildiğinde (push) veya birleştirme isteği (pull request) açıldığında otomatik olarak tetiklenen bir Sürekli Entegrasyon (Continuous Integration - CI) işlem hattı kurmaya başlayacağız. İlk adımımız, bu CI iş akışlarını tanımlamak için GitHub Actions'ın temel bileşenlerini öğrenmek olacak.