Temel Kurallar
Sürüm Kontrolü
- 1.1. Ana branch'imizin ismi
mainolacak şekildetrunk-basedgeliştirme yapıyoruz. Her ne kadar
feature-basedbranch'ler daha yetenekli yapılar gibi görünse de, kendimize dürüst olduğumuzda bu karmaşanın oluşturacağı derleme, ortam ve manual operasyon yükünü karşılamaya değecek bir yazılım geliştirme ihtiyacımızın olmaması gerekiyor.Bir noktadan sonra yönetilemez bir karmaşa haline gelecek branch sayısı, sürekli ana branch'e yaklaşmak için rebase ve test yükü, kullanıcı testlerinin yapılabilmesi için ortam kurulumları ve çalışmalar bittiğinde birleşecek feature'ların getireceği refactor zahmeti maalesef verimlilik sürecini oldukça baltalıyor.
Buradaki
trunk-basedgeliştirme tercihi her zaman çalışmaları ana branch'e yakın tutacak şekilde ufak, yönetilebilir ve merge-conflict'lerden daha uzak sağlıklı bir sürüm geçmişini sağlayacak bir mental-model'in oluşmasında da bize yardımcı oluyor. Geliştiriciler codebase'de küçük değişiklikler yapılmasına teşvik edildiği için büyük ölçekli refactor işlemlerinin ihtiyacı giderek azalıyor.- 1.2.
Feature BranchyerineFeature Flagleri kullanıyoruz. Özellikle
trunk-basedgeliştirme yaparken geliştirilmesi tamamlanan, ancak henüz kullanıcıların tümüne veya bir kısmına sunulmayacak geliştirmelerin kodun içinde yaşaması ve bir konfigurasyon aracılığı ile açılıp kapanmasını sağladığı içinFeature Flagler oldukça yararlı.Feature Flagler bir özelliğin hızlıca geri çekilebilmesi, kontrollü özellik yayılımları, A/B testleri, sürekli entegrasyon ve sürekli ileri doğru veritabanı "migration" stratejileri için oldukça önem taşırlar.- 1.3. Elimizdeki her iş maddesi için ana branch'e
pull requestaçarak geliştirmelerimizi tamamlıyoruz. feature-basedyaklaşımda olduğu gibi her feature için bir branch oluşturup geliştirmeleri o branch altında tutmak yerine,Repo'ya yazmaya yetkimiz varsa, için bir branch oluşturup,
Repo'ya yazma yetkimiz yoksa, oluşturduğumuz fork üzerinde,
geliştirmeleri tamamlamalı ve
pull requestaçarak ilerlemeliyiz.- 1.4. Commit mesajlarını "Conventional Commits 1.0.0" standartına göre yazıyoruz.
Conventional Commits, commit mesajlarının daha iyi taranabilmesi ve geliştirme maddelerinin birbirinden ayrılabilmesi için yardımcı bir standart sunar. Detaylar: conventionalcommits.org
Kullandığımız tipler:
build,chore,ci,docs,feat,fix,perf,refactor,revert,style,test.- 1.5. Branch isimleri içerdiği geliştirmenin türü ve iş maddelerinin id'lerini taşır.
Branch'lerin hangi amaçla açıldığının takibini sağlamak için branch isimleri belirli bir biçimde olmalıdır. Buradaki biçim yine Conventional Commits'in tarif ettiği tip kategorizasyonu ile aynıdır. Feature geliştirmeleri için açılan branch'ler
feat/JIRA-4, bugfix'ler içinfix/JIRA-12ve benzerleri şekilde isimlendirilebilirler.- 1.6.
cherry-pickişlemlerinden kaçınıyoruz. Doğrusal sürüm kontrol sistemlerinden Git ve benzeri dağıtık sürüm kontrol sistemlerine geçiş nedenlerimizden biri de
cherry-pickgibi operasyonlardan kaçınmak ve bunun için branch yapılarını kullanmaktı.cherry-pickişlemi bir commit'i mevcut dalın tarihine ekler, sürüm geçmişinde kopukluklar oluşturur ve orijinal commit'in bağlamını veya bağımlılıklarını taşıdığı için sürüm geçmişinin tekrar yazılmasına neden olur. Bu nedenle bu işlemden sonrafast-forwarddışında seçeneğimiz kalmaz ve ana branch'den kopya almış branch'leri rebase ederek alt branchleri güncel tutma imkanımız kalmaz.Feature Flaglerinin de desteği ile ana branch'de birleşen kod zatencherry-pickedilmişçesine uygulamanın son sürümünü yansıtmalı ve olası "conflict"lerin çözülmüş bir kopyası olmalı. Eğer halen "birleşmiş sürüm"de sorunlar varsa, bunlar eski sürümleri değiştirerek değil, yeni bir commit ile yamalanmalıdır.- 1.7. Sürüm numaraları için
semantic versioningkullanıyoruz. semantic versioningyani anlamsal sürümleme, sürüm numaralarının standartize edilebilmesi ve doğru kategorilendirilmesi için bir dizi yönlendirme sunar. Detaylar: semver.org- 1.8. Sürümleri belirlemek için
tagkullanıyoruz. Kodun ana branch'de bulunan bir noktasından sürüm çıkabilmek için, ilgili commit id'ye bir tag ekleyerek ilerliyoruz.
Bu sayede yayınlama aşamasında çalışan ve
continuous deliverysağlayan pipeline'lar verilen tag'isemantic versioningaraçları ile tanımlayarak nasıl bir paket çıkması gerektiğine karar verebilir hale geliyorlar.
Sınama ve Yayınlama
- 2.1.
Continuous Integration,Continuous DeliveryveContinuous Deployment'ı ayrı süreçler olarak ele alıyoruz. Continuous Integrationiletilen geliştirmenin projenin bütünü ile adaptasyonunu,Continuous Deliverysürümlerin paketlenip taşınabilir hale getirilmesini,Continuous Deploymentise ilgili sürümlerin ilgili ortamlara yüklenmesini hedeflediği için bu kavramları birbirinden izole halde tutmak iyi bir pratiktir.- 2.2.
GitHub Actionskullanıyoruz. GitHub Actions
Continuous IntegrationveContinuous Deliveryaşamalarında kullanılan pipeline'ların kod üzerinden tanımlanması, GitHub'ın sağladığı araçlarla takip edilebilmesi, bağımlılıkların güvenlik taramalarından geçirilmesi ve kolayca tekrar kullanılabilmesini sağlamaktadır.- 2.3.
GitOpskullanıyoruz. GitOps bir
Continuous Deploymentçözümü olarak operasyonların da Git üzerinden kontrol edilebilmesi ve böylece mevcut uygulama altyapısının proje codebase'indeki yapı ile "senkron" kalmasını sağlar. GitOps, yükleme yapılan ortamlardaki gerçek durum ile geliştiricinin "planladığı durum"u senkronize etmesi açısından iyi bir pratiktir.
İletişim ve Kültür
- 3.1. Mümkün olduğunca
asenkron iletişimkullanıyoruz. Bilgilendirme, soru ve benzeri iletişim ihtiyaçlarımızı mümkün olan en "ortak" alanda, yazılı, okunması kolay ve detay-bilgi içermeyen bir biçimde sağlamalıyız. Böylelikle karşımızdaki insanlar takvim meşguliyetleri, saat-farklılıkları veya odaklanma ihtiyaçları gibi dezavantajları hissetmeksizin "uygun olduklarında" geri dönüş sağlayabilecekler.
- 3.2. Atıfta bulunalım.
Başka birinden aldığımız, gördüğümüz, işittiğimiz ve öğrendiğimiz kavramları kullanır veya paylaşırken bizim için konunun orijini olan kimselere atıfta bulunmamız oldukça önem arz ediyor.