Python geliştirme dünyasında, yerel ortamdan üretim dağıtımına geçiş süreci, "bende çalışıyor" kabuslarıyla doludur. Python ekosistemi önemli ölçüde gelişmiş olsa da, en kalıcı zorluk bağımlılık çözümü ve kilit dosyası tutarlılığı olmaya devam etmektedir. CI/CD pipeline'ları oluştururken, pip freeze tarafından oluşturulan requirements.txt dosyasına güvenmek felaketle sonuçlanır. Bu yazıda, kilit dosyası çatışmalarını çözmek ve üretim ortamınızı yerel geliştirme kurulumunuz kadar tekrarlanabilir kılmak için pip-tools ve Poetry'den yararlanarak nasıl deterministik (belirlenmiş) derlemeler elde edebileceğimizi inceleyeceğiz.
CI/CD'de Kilit Dosyası Sorunu
Geleneksel bağımlılık yönetimi genellikle kurulu paketlerin tam durumunu yakalayan bir "freeze" (dondurma) komutu içerir. Ancak bu dosyalar değiştirilebilirdir. Bir geliştirici yerel olarak bir paketi güncellerse, requirements.txt değişir ve bu da pipeline'a ince hatalar sokabilir. Daha da kritik olarak, pip install kurulum süreci sırasında dinamik olarak çözüm yapar. Bir CI ortamında bu, ağ koşulları veya paket deposu durumları derlemeler arasında hafifçe değişse bile, aynı kodun farklı ikili paketler veya bağımlılık ağaçları üretebileceği anlamına gelir.
Bunu çözmek için, sorumlulukların ayrılması gerekir: bağımlılıkları yazmak (kısıtlamalar) için bir araç ve onları kilitlemek için başka bir araç. İşte burada pip-tools ve Poetry parlar; staging ortamınızdaki ortamın üretimle tam olarak aynı olmasını sağlayan kapıcılar olarak hareket ederler.
Strateji A: Pratik Yaklaşım İçin pip-tools
pip-tools, özellikle giriş dosyasını derlenmiş kilit dosyasından ayırmak üzere tasarlanmış hafif bir çözümdür. Açıklayıcı bir yaklaşım kullanır; bağımlılıklarınızı düzenlenebilir kaynak olan requirements.in dosyasında tanımlarsınız ve bunları değiştirilemez kilit dosyası olan requirements.txt dosyasına derlersiniz. Bu, derleme adımının deterministik olmasını sağlar.
İş akışı, kilit dosyasını oluşturmak için pip-compile komutunu çalıştırmayı içerir. Bu dosya, her doğrudan ve dolaylı bağımlılığı belirli bir sürüm ve doğrulama koduna (checksum) sabitler. CI pipeline'ınızda, çözüm motorunu tamamen atlayarak yalnızca bu kilit dosyasından kurulum yaparsınız.
# requirements.in
django>=4.2
psycopg2-binary==2.9.6
# requirements.txt oluşturmak için derlemeyi yerel olarak çalıştırın
pip-compile requirements.in
# CI/CD'de, yalnızca kilit dosyasından kesinlikle kurulum yapın
pip-sync requirements.txt
pip-sync komutu, üretim pipeline'larında özellikle güçlüdür. Sadece kurulum yapmaz; senkronize eder. Kurulu ortamda kilit dosyasında listelenmeyen bir paket varsa, onu kaldırır. Bu, pipeline her çalıştığında ortam durumunun tertemiz olmasını garanti eder.
Strateji B: Proje Odaklı İş Akışları İçin Poetry
Poetry, daha modern ve entegre bir deneyim sunar. Projenin kendisini dağıtım birimi olarak ele alır ve hem bağımlılıkları hem de sanal ortamları yönetir. Poetry'nin pyproject.toml dosyası, gerçeklik kaynağı olarak hareket eder; meta verileri, yapılandırma yapılandırmasını ve bağımlılık tanımlarını birleştirir.
pip-tools'un aksine, Poetry bağımlılıkları, poetry.lock dosyasını oluşturmadan önce sürüm çatışmalarını en aza indirmeye çalışan gelişmiş bir bağımlılık çözümleyicisi kullanarak çözer. Bu kilit dosyası, CI/CD güvenilirliği açısından pip-tools kilit dosyası kadar kritiktir.
# pyproject.toml
[tool.poetry.dependencies]
python = "^3.11"
requests = "^2.31.0"
django = "^4.2.5"
[tool.poetry.group.dev.dependencies]
pytest = "^7.4.0"
CI ortamında iş akışı biraz değişir. Ayrı derleme/kurulum adımları yerine, Poetry çözümü yönetir. Pipeline'ı, kilit dosyasını açıkça kuracak şekilde yapılandırabilirsiniz; bu sayede, bugün yeni bir paket sürümü yayınlanırsa bile, kilit dosyası açıkça güncellenmediği sürece CI bunu kullanmaz.
# CI Pipeline Scripti (Bash)
# Poetry'yi yükleyin
curl -sSL https://install.python-poetry.org | python3 -
# Kilit dosyasını kullandığımızdan emin olun
poetry install --no-root --no-interaction
# Kilit dosyasının bütünlüğünü doğrulayın
poetry check
Aralığı Kapatma: Kilit Dosyası Çatışmalarını Yönetme
Güçlü yanlarına rağmen, kilit dosyası çatışmaları yaşanır. Bu genellikle iki bağımlılığın üçüncü bir dolaylı bağımlılığın uyumsuz sürümlerini gerektirmesi durumunda ortaya çıkar. Gerçek dünyada bu, genellikle CI derlemesi sırasında bir "sürüm uyumsuzluğu" hatası olarak tezahür eder.
pip-tools kullanırken, uyumlu bir sürümü zorlamak için requirements.in dosyanıza belirli sürüm kısıtlamaları ekleyip yeniden derleyerek bunu çözebilirsiniz. Poetry için, bir bağımlılığı veya ağacını seçici olarak güncellemek için poetry update --no-interaction package_name komutunu veya kilit dosyasının yeni sürümleri çözmeye çalışmadan pyproject.toml ile tam olarak eşleşmesini sağlamak için poetry lock --no-update bayrağını kullanmalısınız.
Yüksek riskli üretim ortamları için en iyi uygulama, kilit dosyasını kod olarak ele almaktır. Birleştirme istekleri (merge requests), yalnızca kaynak dosyayı (requirements.in veya pyproject.toml) değil, aynı zamanda resulting kilit dosyasını da güncellemelidir. Bu, çözüm kararının ana dalda birleştirilmeden önce akranlar tarafından gözden geçirilmesini sağlar.
Sonuç
Python'da üretim hazır bir dağıtım elde etmek, bağımlılıkları listelemekten fazlasını gerektirir. Bağımlılık çözümünün kurulumdan ayrıldığı, titiz bir süreç gerektirir. İster hafif, açık kontrolü olan pip-tools'u, ister kapsamlı proje yönetimi sunan Poetry'yi seçin, amaç aynıdır: deterministik, tekrarlanabilir derlemeler.
Bu araçları CI/CD pipeline'larınıza entegre ederek, bağımlılık çözümünün tahmin oyununu ortadan kaldırırsınız. Test ettiğiniz şeyin, tam olarak dağıttığınız şey olduğunu garanti edersiniz; bu da saatlerce süren hata ayıklama zamanını kurtarır ve beklenmedik sürüm yükseltmelerinden kaynaklanan kritik kesintileri önler. Tedarik zinciri güvenliği ve kararlılığın her şeyden önemli olduğu bir çağda, bağımlılıklarınızı kilit dosyalarıyla yönetmek bir seçenek değil, bir zorunluluktur.