DevOps

azd Hooks Artık Python, JS, TS ve .NET Destekliyor

Şu cümleyi yıllardır söylüyorum müşterilere: “Azure Developer CLI güzel de, hook yazmak için Bash veya PowerShell’e geçmek zorunda kalmak biraz can sıkıcı.” Geçen hafta bir fintech projesinde tam da bu yüzden takıldık; ekip baştan sona Python kullanıyordu, kimse PowerShell’e dokunmak istemedi, sonunda biri istemeye istemeye preprovision.sh yazdı ve içine python3 setup.py çağırdı. Tahmin eder mısınız? Saçma bir köprü kurduk yanı.

Vallahi, Neyse, o dert büyük ölçüde bitti (ki bu çoğu kişinin gözünden kaçıyor). azd artık hook’ları doğrudan Python, JavaScript, TypeScript ve.NET ile yazmana izin veriyor. Shell araya girmiyor. Dosya uzantısına bakıyor, dili kendi anlıyor, bağımlılıkları kuruyor, sonra da çalıştırıyor. Kısa ve net.

Şimdi gelelim işin can alıcı noktasına.

Açık konuşayım — bu özelliği duyduğumda “nihayet” dedim. Çünkü hook’lar azd‘nın en çok kullanılan parçalarından biri; provisioning öncesi kaynak hazırlığı, deployment sonrası seed data yükleme, migration tetikleme gıbı işler hep oradan dönüyor. Şimdiye kadar bunlar için ayrı bir dil daha öğrenmek gerekiyordu (ya da işi AI’a atıp çıkan şeyi düzeltmeye uğraşıyorduk), ama bu yeni yaklaşım baya iş görüyor.

Peki neden önemli? Sadece “rahatlık” mı?

Hayır, işin içinde sadece konfor yok. Bakın şimdi biraz açayım:

Birinçisi, kod tekrarını azaltıyor. Python projeniz varsa, büyük ihtimalle zaten requirements.txt, ortak utility modülleri, environment yönetimi gıbı parçalar elinizin altında duruyor; hook’u Python ile yazınca bu düzeni yeniden kurmaya uğraşmıyorsunuz, aynı veritabanı bağlantı kütüphanesini hem uygulama içinde hem de migration hook’unda kullanabiliyorsunuz, eskiden buna baya uzak bakılıyordu.

İkincisi, hata ayıklamak daha rahat oluyor. Bash script’te bir hata alınca — hele ekip Windows ile macOS arasında gidip geliyorsa — işin yarısı satır sonu karakterine takılıyor. Hatırlıyorum, 2022’de bir bankacılık projesinde tam yarım gün \r
yüzünden oyalanmıştık. Python tarafında böyle saçma bir sürpriz çok daha az çıkıyor.

Bir dakika — bununla bitmedi.

Dürüst olmak gerekirse, Üçüncüsü, ve bence en can sıkıcı kısmı çözen şey bu: type safety. TypeScript ile hook yazınca ortam değişkenlerini, response objelerini tıp güvenliğiyle ele alabiliyorsunuz; Bash’te $DB_CONNECTION_STRING boş geldiğinde script bazen sessizce devam edip çöp üretiyordu, sonra siz log’a bakıp “bu ne şimdi?” diyordunuz. Artık bunu derleme aşamasında yakalayabiliyorsunuz.

“Hook yazmak için artık ‘shell scripting’ başlıklı bir Stack Overflow araması yapmak zorunda değilsiniz. Bence bu özellik tek başına azd kullanım oranını ciddi şekilde artıracak.”

Nasıl çalışıyor — hızlı bir tür

Mantık aslında baya basit. azure.yaml dosyanın içine bir hook yazıyorsun, run alanına da dosya yolunu veriyorsun; azd uzantıya bakıp dili çıkarıyor, ama is biraz muallakta kalırsa kind ile elle söylüyorsun. Kısa hâli bu.

# azure.yaml
hooks:
preprovision:
run:./hooks/setup.py
postdeploy:
run:./hooks/seed.ts
postprovision:
run:./hooks/migrate.cs

Bu kadar. Cidden bu kadar. Ilk denediğimde ben de “tamam da burada bir kanca vardır herhalde” diye bekledim, ama yok; akıyor gidiyor. Evet.

Dil bazında neler oluyor arkada?

Her dil için azd‘nın yaptığı şey aynı değil, hatta ufak farklar var ve bunlar bazen işin tadını değiştiriyor; mesela Python tarafında önce ortam hazırlanıyor, sonra bağımlılıklar kuruluyor, en son da script kosuluyor (yanı klasik ama temiz bir akış), JavaScript’te işe paket yönetimi devreye giriyor ve is daha tanıdık hâle geliyor (buna dikkat edin). Bak şimdi tabloyu biraz açayım.

Dil Aranan Dosya Otomatik Yapılan
Python requirements.txt veya pyproject.toml venv oluşturma, bağımlılık kurulumu, çalıştırma
JavaScript package.json npm install, node ile çalıştırma
TypeScript package.json npx tsx ile direkt çalıştırma (compile yok)
.NET .csproj (opsiyonel) dotnet restore + build ya da.NET 10+ ile tek dosya

Dikkat et; TypeScript tarafında taggerconfig.json? yok gibi bir şey bile gerekmiyor.

Şimdi gelelim işin can alıcı noktasına.

Tamam tamam, orada dalga geçiyorum ama mesele su: bayağı iş görüyor. (evet, doğru duydunuz)

Beni aşırı şaşırtan kısım da buydu zaten. Tsconfig olmadan düz gitmesi iyi geldi, çünkü tsconfig hayatimin en sevmediğim ayar dosyalarindan biri; hep bir şey eksik kalıyor gıbı hissediyorsun, sonra iki saat önü kurcalayıp yine aynı yere dönüyorsun. Siz de yaşadınız mi hiç?

Evet.

Python ile bir örnek — gerçek bir senaryo

Açık konuşayım, Geçen ay bir sigorta şirketinin App Service + PostgreSQL Flexible Server işinde tam da bunu denedik. Seed data atmamız gerekiyordu, ama öyle “bir dosya kopyalayalım bitsin” tarzı değil; provisioning sonrası veritabanı ayağa kalkınca birkaç tabloyu doldurup uygulamayı temiz bir başlangıçla çalıştırmak istiyorduk. Önceden Bash ile psql kullanıyorduk, idare ediyordu. Biraz dağınıktı, sonra Python hook tarafına geçince iş şaşırtıcı biçimde sadeleşti.

# hooks/seed.py
import os
import psycopg
from pathlib import Path
DB_URL = os.environ["POSTGRES_CONNECTION_STRING"]
SEED_FILE = Path(__file__).parent / "data" / "initial.sql"
def main():
print("Seed başlıyor...")
with psycopg.connect(DB_URL) as conn:
with conn.cursor() as cur:
cur.execute(SEED_FILE.read_text())
conn.commit()
print("Tamam, seed bitti.")
if __name__ == "__main__":
main()

Yanına bir de requirements.txt koyduk: psycopg[binary]==3.2.0. Hepsi bu kadar. azd, dizin ağacını yukarı doğru tarayıp requirements.txt‘yi buluyor, sonra virtual environment oluşturuyor, bağımlılığı kuruyor ve script’i koşturuyor; açık konuşayım, burada elle yaptığınız şey neredeyse yok. Evet, sıfıra yakın.

💡 Bilgi: Python hook’ları için azd her çalıştırmada yeni venv kurmuyor; ilk seferde oluşturup cache’liyor. Yanı CI/CD pipeline’larında “her deploy’da baştan kurulum mu çıkacak?” diye düşünmeyin. Yine de büyük bağımlılıklarınız varsa (mesela pandas, numpy) ilk koşum biraz uzayabiliyor.

Türkiye’deki ekipler için ne anlama geliyor?

Kurumsal tarafta, açık konuşayım, Türkiye’de azd benimsenmesi biraz ağır gidiyor. Sebep de çok karmaşık değil; ekiplerin bir kısmı Terraform’a gömülmüş durumda, bir kısmı da hâlâ ARM template’leriyle uğraşıyor, o yüzden azd onlara ilk bakışta biraz “fazla yönlendiren” bir araç gıbı geliyor. Microsoft Agent Framework’te Chat History: Nerede yazımızda bu konuya da değinmiştik.

Durun, bir saniye.

Ama hook meselesi var ya, işte asıl kilit nokta orasıydı. Bizdeki ekiplerin çoğu, (belki yanılıyorum ama) özellikle finans ve telekom tarafında, geliştirici profili olarak .NET ağırlıklı ilerliyor; PowerShell’e tamam diyorlar ama Bash görünce yüz biraz ekşiyor, macOS/Linux kullananların sayısı da öyle ahım şahım değil. Şimdi migrate.cs yazıp doğrudan çalıştırabiliyorsanız, bu bariyer bayağı düşüyor.

Bir de startup tarafını düşünün. Çoğu ekip Python ya da TypeScript dünyasında dönüyor zaten. Azure Developer CLI ve Copilot: Terminalde AI Dönemi yazımda da söylemiştim, azd hızlı prototiplemede fena iş görüyor; hook’lar artık native dilde yazılınca, küçük ekiplerde o “tek dilde tüm proje” fikri bir anda daha gerçekçi hâle geliyor. Evet.

İşte tam da bu noktada devreye giriyor.

Enterprise vs startup: hangisi için ne mantıklı?

  • Küçük ekip / startup: Hangı dilde uygulama yazıyorsanız hook’u da o dille yazın. Context switch derdi azalıyor, bakım yükü de hafifliyor; TypeScript projeniz varsa seed.ts, Python projeniz varsa setup.py gıbı ilerlemek gayet doğal duruyor. — bunu es geçmeyin
  • Orta ölçek: Hook’ları bir hooks/ klasöründe toplamak iyi fikir oluyor. package.json ya da requirements.txt‘yi de orada tutarsanız, ana projeyi bağımlılık çorbasına çevirmemiş oluyorsunuz; şey, ufak gıbı duran ama sonra hayat kurtaran bir detay bu.
  • Büyük kurumsal yapı: Burada tablo değişiyor. Bence hâlâ PowerShell veya Bash daha mantıklı olabilir, çünkü güvenlik ekipleri bu script’leri ayrıca inceleyebiliyor; ekstra bir runtime eklemek (npm install, pip install gıbı) compliance tarafında soru işareti çıkarabiliyor.

Son noktayı hafife almamak lazım. Geçen yıl bir bankacılık müşterimde npm install‘ın hook içinde çalışması bile compliance’a takılmıştı; sebep de supply chain riskleriydi (evet, doğru duydunuz). Bu arada Axios npm Saldırısı: Azure Pipelines Kullananlar İçin Rehber yazımı da burada bırakayım,. NPM ekosistemindeki riskler bazen insanı şaşırtıyor açıkçası. Daha fazla bilgi için GitHub App Token Formatı Değişiyor: ghs_ Sonrası Yeni Dönem yazımıza bakabilirsiniz.

Peki, peki neden? Çünkü kurumsalda mesele sadece “çalışsın” değil. Bu konuyla ilgili Kubernetes v1.36’da User Namespaces GA: Rootless Devri Geldi yazımıza da göz atmanızı tavsiye ederim. Daha fazla bilgi için Gateway API v1.5: Stable’a Taşınan Özellikler ve Notlarım yazımıza bakabilirsiniz.

İşin garibi, Emin değilim ama sanırım en kritik ayrım tam burada başlıyor: küçük ekip hız istiyor, büyük yapı işe izlenebilirlik. Kontrol arıyor. Azd ikisini de aynı anda hedeflemeye çalışınca güzel tarafı çıkıyor, ama yanlış yerde kullanırsanız insanı yorabiliyor. Kubelet Fine-Grained Authorization GA: nodes/proxy Devri yazımızda bu konuya da değinmiştik.

Neyse, tam da öyle.

.NET tarafı — özellikle.NET 10 ile gelen single-file modu

Bakın, Bu bölüm bende ayrı bir heyecan yarattı..NET 10 ile dotnet run script.cs geldi ya, işte orada olay biraz değişiyor; yanı .csproj açmadan tek bir C# dosyasını doğrudan koşturabiliyorsunuz, azd de hook tarafında bunu kullanıyor, fena da olmamış açık konuşayım.

// hooks/migrate.cs
using System;
using Azure.Identity;
using Azure.ResourceManager;
var credential = new DefaultAzureCredential();
var armClient = new ArmClient(credential);
Console.WriteLine("Migration başlıyor...");
//... iş mantığı
Console.WriteLine("Bitti.");

Tek dosya. Tek script. Çalışıyor. Tahmin eder mısınız? Bak şimdi, bu kadar sade görünmesine rağmen arka planda baya iş görüyor; azd ekibinin.NET 10’un çıkmasını beklemesi de bu yüzden mantıklı geliyor, çünkü bu “file-based apps” işi tam da böyle senaryolarda kendini gösteriyor (benim Ubuntu 26.04 ve.NET 10: Resolute Raccoon ile Yeni Dönem yazısında anlattığım nokta da buydu aslında) — itiraf edeyim, beklentimin üstündeydi —

Şunu söyleyeyim, Tabi burada küçük bir parantez açayım: büyük migration script’leri için ben yine proje modunu seçerim, çünkü .csproj sana test yazma rahatlığı veriyor, dependency’leri sabitleyebiliyorsun ve işler biraz daha derli toplu gidiyor; tek dosya hızlı deneme için güzel ama production migration tarafında bazen biraz çiğ kalabiliyor.

İlk denemede karşılaştığım bir sorun

Açık konuşayım, ilk Python hook’umu yazdığımda ortalık biraz karıştı. Hata şuydu: azd requirements.txt’yi bulamadı, çünkü dosyayı projenin köküne koymuştum; hook işe hooks/setup.py‘daydı, üstüne bir de benim ortamda Python virtualenv başka yerde kuruluydu ve PATH tarafı da hafifçe şaşmıştı.

Bir dakika — bununla bitmedi.

Çözüm aslında basit çıktı. requirements.txt‘yi hooks/ klasörünün içine taşıdım. Yanı:

hooks/
├── setup.py
└── requirements.txt

Böyle yapınca sorun kapandı. Dökümantasyonda “parent directory’lere kadar tarar” deniyor, doğru,. Benim gördüğüm şey şu öldü: aynı klasörde tutmak daha az sürpriz çıkarıyor. Mantıklı değil mi? Hele birden fazla hook varsa, her biri için ayrı klasör ve ayrı requirements kullanmak baya iş görüyor.

Evet.

Working directory meselesi

Bir başka detay da dir alanı. Bazen hook script’ınız proje köküne göre relative bir yola erişmek istiyor, sonra bir bakıyorsunuz yol çözümlenmiş gıbı duruyor ama çalışırken farklı klasörden okunuyor; işte o noktada şöyle bir tanım kullanıyorsunuz:

hooks:
postprovision:
run:./hooks/migrate.py
dir:./src/database

Bu şekilde script ./src/database klasöründen çalışıyor, dolayısıyla dosya yolu derdi azalıyor. Küçük bir ayrıntı gıbı duruyor, ama insanı gereksiz debug turundan kurtarıyor. Peki neden? Çünkü bazen sorun kodda değil, çalışma dizininde oluyor.

Neyse, çok dağıttım, konuyu toparlayayım: dir ayarını doğru verdiğinizde hem script daha öngörülebilir davranıyor hem de relative path kullanan adımlar daha sakın çalışıyor.

Tam da öyle.

Maliyet ve performans tarafı

Şimdi kimse çok konuşmuyor ama önemli bir nokta var: hook’lar biraz ağırlaştı. Çünkü bağımlılık yönetimi devreye giriyor, CI/CD pipeline’ında her azd up çalıştığında npm install ya da pip install tetikleniyor; agent cache’ınızı düzgün ayarlamadıysanız, build süresi uzayıp gidiyor, sonra da herkes “neden bu kadar yavaş” diye bakıyor.

İnanın, Azure DevOps pipeline’larında bunu ben de test ettim. Bir Node.js hook’u olan projede ilk çalıştırma 90 saniye sürdü, sonraki çalıştırmalar işe cache sayesinde 12 saniyeye indi. Yanı işin aslı cache kritik, baya fark ediyor; node_modules. .venv klasörlerini cache’leyin, yoksa aynı paketi tekrar tekrar indirip durursunuz (ciddiyim)

Garip gelecek ama, Bu arada azd’nın temposu da hızlanıyor. Azure MCP Server.mcpb Paketi: Runtime Derdine Veda yazımda da değindiğim gıbı, Microsoft developer tooling tarafında runtime sorunlarını azaltmaya odaklanmış durumda; hook’ların multi-language desteği de aynı çizginin devamı gıbı duruyor, hani bir taraftan sadeleşme var, diğer taraftan da kullanım alanı genişliyor.

Pratik öneriler — başlamak için

  1. azd’yi güncelleyin. Bu kısmı atlamayın. Özellik yeni geldi, eski sürümde bazen hiç açılmıyor; azd version ile bir bakın, sonra da gerekirse winget upgrade Microsoft.Azd ya da brew upgrade azd ile işi toparlayın.
  2. Küçük başlayın. Bir anda tüm Bash hook’ları çevirmeye kalkmayın, açık konuşayım, o iş genelde gereksiz stres çıkarıyor; önce tek bir yeni hook ekleyin, native dili orada deneyin, sonra karar verin.
  3. Klasör yapısını netleştirin. Her hook için ayrı klasör açın, yanına da kendi bağımlılık dosyasını koyun (mesela Python işe requirements, Node işe package dosyası), yoksa iki hafta sonra kim neyi nereye koydu diye uğraşırsınız.
  4. kind alanını kullanın. Uzantı belirsizse, mesela uzantısız bir dosya geldiyse, kind: python diyerek durumu netleştirin; küçük bir satır gıbı duruyor ama sürprizi baya azaltıyor. — bunu es geçmeyin
  5. CI/CD cache’leyin. .venv, node_modules, ~/.nuget/packages klasörlerini pipeline cache’ine ekleyin; ilk koşuda biraz uğraştırır ama sonraki çalışmalarda farkı hemen hissedersiniz, yanı boşuna bekleme süresi yemiyorsunuz.

Evet.

Neyse uzatmayalım. Bu beş maddeyi oturttuğunuzda akış daha sakın oluyor, debug tarafı da daha az can sıkıyor; özellikle azd ile çalışan hook yapılarında küçük detaylar bazen asıl farkı yaratıyor. Siz ne dersiniz?

Sıkça Sorulan Sorular

Eski Bash hook’larım bozulur mu?

Küçük bir detay: Hayır, hiç merak etme. Bu özellik mevcut Bash ve PowerShell desteğinin üstüne eklendi, yanı aslında hiçbir şey ortadan kalkmıyor. Eski hook’larınız eskisi gıbı çalışıyor. Geçişi acele yapmak zorunda değilsiniz, istediğiniz hızda yavaş yavaş geçebilirsiniz.

TypeScript hook için tsconfig.json şart mı?

Hayır, gerekmiyor. azd, TypeScript dosyalarını npx tsx ile çalıştırıyor; yanı JIT olarak derleniyor. Tek yapmanız gereken package.json‘da bağımlılıklarınızı belirtmek. tsx zaten transient olarak yükleniyor, başka bir şeye gerek yok.

Aynı projede farklı dillerde hook yazılabilir mi?

Evet, teknik olarak mümkün. Mesela bir hook’u Python ile, diğerini TypeScript ile yazabilirsiniz; her birinin bağımlılık dosyası kendi klasöründe olduğu sürece sorun çıkmıyor. Ama açıkçası bunu production’da önermem. Bakım maliyeti ciddi şekilde artıyor. Ekipteki herkesin tüm dillere hâkim olması gerekiyor, bu da pratikte pek gerçekçi değil.

.NET single-file modu hangı sürümden itibaren geliyor?

Bunu yaşayan biri olarak söyleyeyim,.NET 10 ve üstü gerekiyor. Daha eski sürümlerde .csproj dosyası zorunlu. Hani.NET 8 veya 9 kullanıyorsanız, hook klasörünüze küçük bir .csproj eklemeniz yeterli; azd gerisini hallediyor, otomatik olarak dotnet restore. build yapıyor.

Hook içinden azd ortam değişkenlerine nasıl ulaşırım?

Bir şey dikkatimi çekti: Tüm hook’lar, azd’nın set ettiği environment variable’larla başlıyor. Python’da os.environ["AZURE_LOCATION"], Node.js’te process.env.AZURE_LOCATION,.NET’te işe Environment.GetEnvironmentVariable("AZURE_LOCATION") şeklinde erişebilirsiniz. Tam listeyi görmek istiyorsanız azd env get-values komutu oldukça işe yarıyor, tecrübeme göre bunu başta çalıştırmak çok zaman kazandırıyor.

Kaynaklar ve İleri Okuma

Aslında — hayır dür, daha doğrusu, Azure SDK Blog: Write azd hooks in Python, JavaScript, TypeScript, or.NET — Orijinal duyuru yazısı, Kristen Womack tarafından.

Microsoft Learn: Azure Developer CLI Hooks Documentation — Resmî dokümantasyon, tüm hook lifecycle event’leri ve yapılandırma seçenekleri (şaşırtıcı ama gerçek)

GitHub: Azure/azure-dev Repository — azd kaynak kodu, issue tracker ve örnek template’ler. Yeni özelliklerin ilk göründüğü yer burası.

Aşkın KILIÇ

20+ yıl deneyimli Azure Solutions Architect. Microsoft sertifikalı bulut mimari ve DevOps danışmanı. Azure, yapay zekâ ve bulut teknolojileri üzerine Türkçe teknik içerikler üretiyor.

AZ-305AZ-104AZ-500AZ-400DP-203AI-102

Bu içerik işinize yaradı mı?

Benzer içerikleri kaçırmamak için beni sosyal medyada takip edin.

← Onceki Yazi
Entra External ID Native Auth: SSO ile WebView Köprüsü Geldi

Yorum Yaz

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

İçindekiler
← Entra External ID Native Auth:...