<

Bir Yılda 40 Sürüm: Küçük Ekipte Sürüm Mühendisliği

Aralık başında yıllık değerlendirme için git geçmişini kazarken sayıyı görüp bir kez daha saydım: son on iki ayda üretime 40 sürüm çıkmışız. Dört kişilik geliştirme ekibiyle, haftada ortalama 0.8 sürüm. İki yıl önce aynı büyüklükteki ekibimiz yılda 6 sürüm çıkarıyordu ve her biri, öncesinde iki gün test maratonu, gecesinde pizza kutuları ve sabahında "neyi geri alacağız" toplantısı demekti. Sayı 6'dan 40'a çıkarken gece mesaisi sayısı 6'dan 1'e indi. Bu yazı, aradaki iki yılda nelerin değiştiğinin dökümü.

Korkunun Gerçek Kaynağı Sürüm Değil, Boyut

İlk fark ettiğimiz şey psikolojikti: sürümden korkmuyorduk aslında, büyük sürümden korkuyorduk. Yılda 6 sürüm çıkarınca her sürüm iki aylık birikmiş değişiklik taşır: 40-50 commit, üç büyük özellik, iki şema değişikliği, dokunulmamış köşe kalmaz. Böyle bir paketin nesi bozulur sorusunun cevabı "her şeyi" olduğu için test etmesi de, bozulunca suçluyu bulması da, geri alması da kâbustur. Sürüm sıklaştıkça her paket küçüldü; bugün tipik sürümümüz 3-6 commit taşıyor. Bir şey bozulursa şüpheli listesi üç maddelik. Sıklık riski artırmadı; riski böldü. Sürüm mühendisliğinde öğrendiğim ilk ilke bu: korkuyorsanız seyrekleştirmeyin, küçültün.

14 Dakikalık Pipeline'ın Ekonomisi

Bunu mümkün kılan mekanik omurga, sıkılıkla korunan bir CI/CD hattı. İki yıl önce build 34 dakika sürüyordu ve testlerin bir kısmı "ara sıra kırmızı" olduğu için kimse sonuca güvenmiyordu. Bugün commit'ten üretime hazır imaja 14 dakika: derleme, birim testleri, kritik yolları kapsayan entegrasyon testleri, imaj oluşturma. Buradaki asıl yatırım hız değil, güvendi. Kararsız testleri tek tek avlayıp ya düzelttik ya acımadan sildik; çünkü yüzde 95 güvenilir bir test takımı, pratikte yüzde 0 güvenilirdir — insanlar kırmızıyı "yine saçmalıyordur" diye geçmeye başladığı gün takım ölmüştür. Pipeline yeşilse üretime çıkabilir kuralının anlamlı olması için, yeşilin gerçekten yeşil olması gerekiyordu.

Dallanma stratejimiz de bu dönüşümün parçasıydı. Uzun ömürlü feature branch'lerden, ana dala küçük ve sık birleşen bir akışa geçtik; kod incelemesi hâlâ zorunlu ama inceleme birimi küçüldüğü için bir PR'ın bekleme süresi ortalama yarım güne indi. İki bin satırlık bir PR'ı kimse gerçekten incelemez, iki yüz satırlığı herkes inceler; küçük parti boyutunun kalite etkisi, sürat etkisinden bile büyük çıktı. Deploy'un kendisi de tek komut: birleşen her değişiklik pipeline'dan geçip staging'e otomatik iniyor, üretime çıkış ise bir kişinin bilinçli onayıyla oluyor. O onay düğmesine kimin basacağı da kurala bağlandı — değişikliği yazan basar, çünkü sorun çıkarsa bağlamı en sıcak taşıyan odur.

Şema Değişikliği: Sürümlerin Ayak Bağı

Bu ilkeyi ekibe kabul ettirmenin yolu da tartışma değil, ölçüm oldu: altı aylık sürüm kayıtlarını dizip her sürümün taşıdığı commit sayısıyla çıkardığı sorun sayısını yan yana koyduk. Eğri kimseyi ikna etmeye çalışmadan ikna etti; büyük paketler orantısız biçimde daha çok sorun çıkarıyordu.

Sıklaşmanın önündeki en inatçı engel veritabanı migration'larıydı; kod iki dakikada geri alınır ama çalıştırılmış bir ALTER TABLE geri alınmaz. Çözümümüz expand-contract disiplini oldu. Her şema değişikliği en az iki sürüme yayılır: önce genişletme — yeni sütun eklenir, kod hem eskisini hem yenisini yazacak şekilde çıkar — sonra, yeni yapı birkaç sürüm boyunca sorunsuz çalıştıktan sonra daralma sürümüyle eski sütun kaldırılır. Bu sayede her sürüm, şema açısından bir önceki kod sürümüyle de çalışabilir durumda kalıyor ve rollback her zaman güvenli bir işlem olarak masada duruyor. Yavaş görünür; ama yılda 40 kez sürüm çıkaran bir ekipte "geri alamayız, ileri düzelteceğiz" cümlesini bir kez bile kurmamak, bu yavaşlığın karşılığını fazlasıyla ödüyor.

Feature flag altyapımız bu tempoyla iç içe çalışıyor; ağustosta ayrıntısıyla yazmıştım, burada yalnızca sürüm perspektifinden değineyim. Bayraklar sayesinde "kod hazır ama özellik tamamlanmadı" durumu sürümü bloklamıyor: yarım özellik kapalı bayrağın arkasında üretime çıkıyor, entegrasyon çatışmaları küçükken çözülüyor. Uzun ömürlü feature branch'ler bu sayede tarihe karıştı; en yaşlı açık branch'imiz genellikle birkaç günlük. Sürüm sıklığının gizli düşmanı merge çatışması birikimidir ve bayraklar o birikimi kaynağında kurutuyor.

İnsan Faktörü: Checklist'ten Refleks Üretmek

Süreç tarafında iki âdet yerleşti. Sürüm saati sabah 10:00; çünkü bir sorun çıkarsa önümüzde uyanık ve tam kadro yedi saat var. Akşam 18:00 sürümü kahramanlık hikâyesi gibi anlatılır ama sorunu gece yarısı tek kişiyle çözersiniz. İkinci âdet, her sürümün tek sayfalık otomatik künyesi: hangi commit'ler, hangi migration'lar, hangi feature flag'ler etkileniyor, geri alma adımı ne. Bunu elle yazdığımız dönemde ihmal ediliyordu; şimdi pipeline üretiyor, sürümü yapan kişi yalnızca okuyup onaylıyor. Rollback prosedürünü de yılda iki kez, gerçek ihtiyaç yokken tatbikat olarak koşuyoruz. Paraşütün katlanmış durması yetmiyor; arada bir açıldığını görmek gerekiyor.

Sayının Kendisi Hedef Değil

Müşteriye dönük iletişim tarafı da beklenmedik biçimde önem kazandı. Yılda 6 sürümken her sürüm bir duyuru e-postasıydı; yılda 40 sürümde kimse 40 e-posta okumaz. Ayrıma gittik: kullanıcıya görünür değişiklikler aylık toplu bültende anlatılıyor, teknik sürüm künyeleri ise isteyen müşterinin eriştiği bir değişiklik günlüğü sayfasında birikiyor. Sürüm numaralandırmasını da sadeleştirdik; anlamsal sürümleme API'ler için yaşıyor ama uygulama sürümleri artık tarih tabanlı, çünkü "bu hata hangi sürümde düzeldi" sorusunun cevabını takvimle vermek herkes için daha kolay.

Bir itiraf ve bir sonraki hedefle bitireyim. İtiraf: 40 sürümün 3'ü, çıktığı gün küçük bir düzeltme sürümü gerektirdi ve üçünde de sebep aynıydı — staging ortamının üretimden sapmış bir ayarı. Staging'i üretimle aynı imajlardan, aynı konfigürasyon mekanizmasıyla kurmak o yüzden gelecek çeyreğin ilk işi. Hedef ise sayıyı büyütmek değil; 40 yeterli. Hedef, sürüm gününün takvimde özel bir gün olmaktan tamamen çıkması. En iyi sürüm, kimsenin fark etmediği sürüm; biz oraya yaklaşıyoruz ama henüz varmadık.

Yanlış anlaşılmasın: 40 sayısını kovalamadık, o bir sonuçtu. Kovaladığımız şey, "bu değişiklik hazır" ânı ile "kullanıcı bunu kullanıyor" ânı arasındaki bekleme süresini eritmekti. İki yıl önce bu süre ortalama beş haftaydı; bugün üç gün. Değişiklik başarısızlık oranımız — bir sürümün düzeltme veya geri alma gerektirme oranı — aynı dönemde yüzde 18'den 5'e indi. Yani daha sık çıkmak daha çok bozmak anlamına gelmedi; tam tersi, küçük adımlar ve işleyen bir omurga sayesinde hem hızlandık hem sağlamlaştık. Küçük ekipler için iyi haber şu: bunların hiçbiri platform ekibi ya da pahalı araç gerektirmedi; disiplin, otomasyon ve küçültme cesareti yetti. Kendi ekibinizde sürüm temposunu artırmak istiyor ama nereden başlayacağınızı bilmiyorsanız iletişim sayfasından ulaşın; ilk adım neredeyse her zaman aynı — bir sonraki sürümü yarıya bölün.

📅 Yayınlanma:  ·  Yakup Zengin