Ders 16 / 19
Test Kanalları
Bir derlemenin iç, kapalı ve açık test kanallarından geçip üretime çıkana kadar kaç adım attığını ölçer. Geri çevrilen derlemenin yeniden derlenip adımları baştan saydığı durumda aşımın nasıl değiştiğini gösterir.
Yayın Güncelleme
Bu derste
- İç, kapalı ve açık test kanallarının yayın yolundaki sırasını ve görevini ayırt eder
- Bir derlemenin kanallardan geçişini adım sayısı olarak modeller
- Geri çevrilen bir derlemenin yeniden denendiği ve baştan başladığı iki durumu karşılaştırır
- Terfi adımı bütçesini ekibin kararı olarak koyar ve aşımı sınıflar
İçindekiler
Önceki ders bir değişikliğin hatta kaç iş koşturduğunu ölçtü. Hattın ucunda dağıtıma hazır bir derleme bekler, ama hazır olması kullanıcılara ulaşması anlamına gelmez. Derleme önce ekibin kendi aygıtlarına, sonra seçilmiş bir test grubuna, sonra daha geniş bir test kitlesine iner; en sonda üretime çıkar. Her duraktaki kanal (track) o derlemenin farklı bir kitleyle sınanmasıdır.
Kursun sorusu burada da aynıdır: bu ölçüm bütçesini kaç örnekte aşıyor? Ölçüm bir derlemenin üretime çıkana kadar attığı terfi adımıdır, bütçe ekibin kabul ettiği adım sayısıdır, her derleme bir örnektir.
// Overrun.kt — bir olcumun butcesini kac ornekte astigini siniflandirir
class Budget(val name: String, val limit: Int)
class Overrun(val label: String, val budget: Budget, samples: List<Int>) {
val total: Int = samples.size
val over: Int = samples.count { it > budget.limit }
val verdict: String = when {
over == 0 -> "icinde"
over == total -> "hepsinde"
over * 2 < total -> "azinda"
else -> "cogunda"
}
fun line() {
println("$label: butce=${budget.name}<=${budget.limit} | asan=$over/$total -> $verdict")
}
}
fun countOverruns(overruns: List<Overrun>) {
for (name in listOf("icinde", "azinda", "cogunda", "hepsinde")) {
println("$name: ${overruns.count { it.verdict == name }}")
}
}
Overrun sınırı kesin aşan örnekleri sayar ve yaygınlığı dört adla verir: içinde, azında, çoğunda, hepsinde. Kural kaç derlemenin aştığını görür; bir derlemenin bir mi yoksa üç adım fazla mı attığı aşan her örnek için aynı sayılır.
Dört Kanal
Yayın yolu dört durağa ayrılır. İç test kanalı (internal testing) ekibin kendisine aittir: derleme yüklenir ve ekip aygıtlarında hemen denenebilir. Kapalı test kanalı (closed testing) ekibin seçtiği bir test grubuna açılır. Açık test kanalı (open testing) mağazada görünen ve herkesin katılabildiği bir teste açılır. Üretim kanalı (production) kullanıcıların kendisidir.
Dört durağın sırası yayın yolunu verir: iç, kapalı, açık, üretim. Bir derleme bir sonraki kanala terfi eder (promotion) ya da bir kanalda geri çevrilir. Geri çevrilme bir hatanın bulunmasıdır: derleme düzeltilir ve yeniden denenir.
Model yolu bir liste olarak kurar. Her kanala girmek bir adım sayılır. Bir kanalda geri çevrilen derleme, geri çevrilmeyi tüketir ve yeniden girer; bu da bir adım daha demektir.
// ReleaseTrackModel.kt — kanal yolunu ve terfi adimi sayisini modeller
class Build(val label: String, val rejectedAt: List<String>)
fun trackPath(): List<String> = listOf("ic", "kapali", "acik", "uretim")
fun promotionSteps(path: List<String>, build: Build, restartOnReject: Boolean): Int {
var steps = 0
var index = 0
val pending = build.rejectedAt.toMutableList()
while (index < path.size) {
steps++
val track = path[index]
if (track in pending) {
pending.remove(track)
index = if (restartOnReject) 0 else index
} else {
index++
}
}
return steps
}
fun sampleBuilds(): List<Build> = listOf(
Build("derleme-a", emptyList()),
Build("derleme-b", emptyList()),
Build("derleme-c", emptyList()),
Build("derleme-d", emptyList()),
Build("derleme-e", listOf("kapali")),
Build("derleme-f", listOf("acik")),
Build("derleme-g", listOf("ic")),
Build("derleme-h", emptyList()),
)
Sekiz derlemenin dördü hiç geri çevrilmedi, üçü bir kez geri çevrildi: biri iç kanalda, biri kapalı kanalda, biri açık kanalda. Son derleme de temiz geçti.
Yolun Ölçümü
Ekip bir derlemenin dört kanal artı bir yeniden denemeyi kabul ettiğini söylüyor: bütçe beş adım. Önce geri çevrilen derlemenin yalnız o kanalı yeniden denediği durumu ölçelim.
// Main.kt — geri cevrilen derleme ayni kanalda yeniden denenir, butce bes adim
fun main() {
val path = trackPath()
val builds = sampleBuilds()
val samples = builds.map { promotionSteps(path, it, false) }
for (build in builds) {
println("${build.label}: ret=${build.rejectedAt}")
}
println("adim: $samples")
Overrun("terfi-adimi", Budget("adim", 5), samples).line()
}
derleme-a: ret=[] derleme-b: ret=[] derleme-c: ret=[] derleme-d: ret=[] derleme-e: ret=[kapali] derleme-f: ret=[acik] derleme-g: ret=[ic] derleme-h: ret=[] adim: [4, 4, 4, 4, 5, 5, 5, 4] terfi-adimi: butce=adim<=5 | asan=0/8 -> icinde
Hiçbir derleme beş adımı aşmadı: geri çevrilen üç derleme tam beş adımda, geri kalanı dört adımda tamamladı. Yanıt içinde. Bu, dersin aşımıdır. Beş adım sınıra eşittir ve eşitlik aşım sayılmaz.
Bu sonuç bir şeyi saklar: bütçe, bir kez geri çevrilen derlemenin payını kapsayacak kadar geniş koyuldu. Bütçeyi dörde indirmek, tek bir geri çevirmeyi bile aşım yapar.
DA3. Model her kanalı bir adım sayar ve kanalda kalınan süreyi kurmaz. Gerçekte bir test grubunun derlemeyi kullanması bekleme ister; model beklemenin uzunluğunu da, bir kanalın diğerinden daha çok zaman almasını da görmez. Geri çevirmeler de girdidir: hangi derlemenin hangi kanalda geri çevrildiği elle yazıldı.
Bütçe Bir Karardır
Aynı sekiz derlemeyi üç bütçeyle ölçelim: beş adım, dört adım, üç adım.
// Main.kt — ayni sekiz derleme uc ayri butceyle uc ayri asim verir
fun main() {
val path = trackPath()
val samples = sampleBuilds().map { promotionSteps(path, it, false) }
val roomy = Overrun("bes-adim", Budget("adim", 5), samples)
val normal = Overrun("dort-adim", Budget("adim", 4), samples)
val tight = Overrun("uc-adim", Budget("adim", 3), samples)
listOf(roomy, normal, tight).forEach { it.line() }
countOverruns(listOf(roomy, normal, tight))
}
bes-adim: butce=adim<=5 | asan=0/8 -> icinde dort-adim: butce=adim<=4 | asan=3/8 -> azinda uc-adim: butce=adim<=3 | asan=8/8 -> hepsinde icinde: 1 azinda: 1 cogunda: 0 hepsinde: 1
Dört adımlık bütçede yalnız geri çevrilen üç derleme aştı, yanıt azında. Üç adımlık bütçede dört kanalın kendisi bütçeyi aştığı için sekiz derlemenin sekizi de aştı: temiz geçen derleme bile dört adım atar. Burada tabana dikkat edin: yol dört kanaldan oluştuğu sürece hiçbir derleme dört adımın altına inemez. Üç adımlık bütçe bir ekip kararı olarak yazılsa, kanallardan birini atlamayı gerektirir.
Yeniden Derleme
Geri çevrilen derleme düzeltilir ve yeniden derlenir. Yeniden derleme yeni bir pakettir ve sürüm kodu, bir önceki derste gördüğümüz gibi, bir öncekinden büyük olmak zorundadır.
// Platform kodu: yeniden derleme
android {
defaultConfig {
versionCode = 13
}
}
Bu parça platform kodudur; çıktı iddia etmiyoruz. Model, bu ölçümün kuralını kurar; model aracın kendisi değildir. Önemli olan sonuçtur: yeniden derlenen paket, önceki derlemeyle aynı olmadığı için önceki kanallarda alınan sonuç yeni pakete otomatik geçmeyebilir. Ekip bu durumda ya yalnız geri çevrildiği kanalı yeniden dener, ya da yolu baştan yürür. Bu seçim bir politikadır; model ikisini de bir bayrakla kurar.
Betikteki versionCode = 13 satırı iki şeyi birden anlatır. Birincisi, yeniden derlemenin yeni bir sürüm kodu taşımasıdır; kod önceki dersin kuralıyla yalnız artabilir. İkincisi, kanallarda alınan sonucun paketin kendisine değil o paketin kodu taşıdığı kimliğe bağlı olmasıdır. Kimlik değişince önceki kanalın onayı, ekibin politikası aksini söylemedikçe yeni pakete taşınmaz. Modelde restartOnReject bayrağı bu politikayı kurar: yanlışsa yalnız geri çevrilen kanal yinelenir, doğruysa yol başa döner.
Sınırlayıcı Ölçüm
Dersin aşımı içindedir; sınırlayıcı ölçüm bu rahat sonucun neyin üzerinde durduğunu sorar. Yeniden derleme baştan başlıyorsa, her geri çevirme önceki kanalları da yeniden sayar. Aynı sekiz derlemeyi iki ayrı kuralla ölçelim ve dokuzuncu olarak aynı kanalda iki kez geri çevrilen bir derleme ekleyelim.
// Main.kt — yeniden derleme yolu bastan yurutur, adimlar yeniden sayilir
fun main() {
val path = trackPath()
val builds = sampleBuilds()
val budget = Budget("adim", 5)
val retry = builds.map { promotionSteps(path, it, false) }
val restart = builds.map { promotionSteps(path, it, true) }
println("ayni kanalda yeniden: $retry")
println("bastan yeniden: $restart")
Overrun("ayni-kanal", budget, retry).line()
Overrun("bastan", budget, restart).line()
val twice = Build("derleme-i", listOf("kapali", "kapali"))
val withTwice = builds + twice
Overrun("ayni-kanal-iki-ret", budget, withTwice.map { promotionSteps(path, it, false) }).line()
Overrun("bastan-iki-ret", budget, withTwice.map { promotionSteps(path, it, true) }).line()
}
ayni kanalda yeniden: [4, 4, 4, 4, 5, 5, 5, 4] bastan yeniden: [4, 4, 4, 4, 6, 7, 5, 4] ayni-kanal: butce=adim<=5 | asan=0/8 -> icinde bastan: butce=adim<=5 | asan=2/8 -> azinda ayni-kanal-iki-ret: butce=adim<=5 | asan=1/9 -> azinda bastan-iki-ret: butce=adim<=5 | asan=3/9 -> azinda
Aynı kanalda yeniden denenen yolda aşım içinde, yolun baştan yürüdüğü kuralda azında çıktı. Baştan yürüyen yolda kapalı kanalda geri çevrilen derleme altı, açık kanalda geri çevrilen yedi adım attı; iç kanalda geri çevrilen derleme beşte kaldı, çünkü geri çevrildiği anda yolun başındaydı. Geri çevrilme ne kadar ileride olursa baştan sayılan adım o kadar çok olur.
Dokuzuncu derleme tabloyu da değiştirir. Aynı kanalda iki kez geri çevrilen derleme yeniden denemeyle altı adım, baştan yürüyen kuralda sekiz adım tutar. Kategori iki durumda da azında kaldı, ama aşan örnek sayısı birden üçe çıktı. Kural sayıyı sayar, büyüklüğü görmez: bir derlemenin bir adım, bir başkasının üç adım aşması aynı kategoriyi verir.
DA4. Model geri çevrilmeyi bir girdi olarak alır ve düzeltmenin başarılı olacağını varsayar. Gerçekte bir düzeltme yeni bir hata getirebilir; model bunu kurmaz. Geri çevirme sayısı da bir kural değil, elle yazılmış bir listedir.
Kanal Atlamak
Adım sayısını azaltmanın en kısa yolu bir kanalı yoldan çıkarmaktır. Kapalı kanalı atlayan yol üç duraktan oluşur ve temiz bir derleme üç adımda biter. Ama kanalın işi adım saymak değildir; o kanalda yakalanacak bir hatayı yakalamaktır. Aşağıdaki ölçüm yolu iç, açık ve üretim olarak kurar ve bütçeyi üç adıma indirir. Ayrıca kapalı kanalda geri çevrilecek olan derlemelerin, yani kanal yolda olsaydı yakalanacak olanların hangileri olduğunu listeler.
// Main.kt — kapali kanali atlayan yol adimi azaltir ama o kanalda yakalanacak reti gozden kacirir
fun main() {
val builds = sampleBuilds()
val skipped = listOf("ic", "acik", "uretim")
val samples = builds.map { promotionSteps(skipped, it, false) }
println("adim: $samples")
val missed = builds.filter { build -> build.rejectedAt.any { it !in skipped } }
println("gozden kacan ret: ${missed.map { it.label }}")
Overrun("kapali-atlandi", Budget("adim", 3), samples).line()
}
adim: [3, 3, 3, 3, 3, 4, 4, 3] gozden kacan ret: [derleme-e] kapali-atlandi: butce=adim<=3 | asan=2/8 -> azinda
Dört kanallı yol üç adımlık bütçede hepsinde çıkmıştı; üç kanallı yol aynı bütçede azında çıktı. Ama kazanç bir bedelle geldi: derleme-e kapalı kanalda geri çevrilecekti, yol o kanalı içermediği için geri çevirme hiç görülmedi ve derleme düzeltilmeden açık kanala ilerledi. Adım sayısı düştü; hatanın yakalandığı durak yok oldu.
DA5. Model atlanan kanalda geri çevirmenin başka bir kanalda yakalanacağını varsaymaz ve bunu gozden kacan ret listesiyle gösterir. Ama hatanın daha sonra açık kanalda ya da üretimde ortaya çıkıp çıkmayacağını, ortaya çıkarsa maliyetinin ne olacağını kurmaz.
Yaygın Yanılgılar
“Kanal sayısı kalite ölçüsüdür.” Kanal sayısı bir derlemenin geçtiği durak sayısıdır. Bir derlemenin çok kanaldan geçmesi iyi sınandığını göstermez; sınamanın kalitesi kanaldaki kitleye ve geri bildirime bağlıdır.
“Geri çevrilen derleme kötü bir derlemedir.” Geri çevirme bir kanalın işini yapmasıdır. Kanallar hatayı üretime ulaşmadan bulmak için vardır.
“Bütçeyi tutturmak için kanal çıkarmak yeterlidir.” Kanal çıkarmak adım sayısını düşürür ve ölçümü bütçenin içine ya da yakınına getirebilir. Ama kanalın yakalayacağı hata yakalanmaz. Yukarıdaki ölçüm bunu bir derleme üzerinde gösterdi: aşım azaldı, gözden kaçan geri çevirme birdi.
“Yeniden derleme önceki kanalların sonucunu taşır.” Taşımaz, çünkü yeni bir pakettir ve yeni bir sürüm kodu taşır. Taşınıp taşınmayacağı ekibin politikasıdır; bu derste iki politika da ayrı ayrı ölçüldü.
“Adım sayısı süreyi verir.” Verilmez. Bir adım bir gün de sürebilir, birkaç saat de; model süreyi ölçmez. “İç kanalda geçen derleme açık kanalda da geçer.” Geçmeyebilir. Kitle büyüdükçe aygıt ve kullanım çeşitliliği artar; iç kanalda hiç görünmeyen bir hata ancak daha geniş bir kitlede ortaya çıkar. Kanalların sırası bu yüzden büyüyen bir kitleye göredir.
“Kanalları atlamak yalnız süre kazandırır.” Süre kazandırdığı doğrudur, ama kanalın yakalayacağı hata da üretime geçer. Bu derste kapalı kanalı atlayan yol adım bütçesini tutturdu ve gözden kaçan geri çevirme sayısı bire çıktı; kazanç ile kayıp aynı tabloda görüldü.
“Kanal sırası ekibin zevkine bağlıdır.” Sıra, bir derlemenin kime ulaşmadan önce kimin elinden geçeceğini belirler. Sırayı değiştirmek, bir derlemeyi daha az denetlenmiş bir kitleye daha erken göstermek demektir. Bu bir tasarım kararıdır ve ölçümün kendisi sırayı önermez.
“Geri bildirim sayısı kanalın başarısıdır.” Çok geri bildirim, çok hata olduğu anlamına da gelebilir, kitlenin ilgili olduğu anlamına da. Model geri bildirim sayısını ölçmez; adım sayısını ölçer.
“Aşım azaldıysa süreç iyileşmiştir.” Aşım yalnız bir bütçeye göre sayılır. Bütçe gevşetilirse ya da kanal çıkarılırsa aşım kendiliğinden azalır; sürecin iyileşip iyileşmediği, hangi hataların hâlâ üretimden önce yakalandığına bakılarak anlaşılır. Bu yüzden aşım sayısı ile gözden kaçan geri çevirme sayısı yan yana okunmalıdır. Tek bir sayıya bakıp karar vermek, öteki sayının söyleyeceğini duymamaktır.
“Her derleme dört kanaldan da geçmelidir.” Bu bir ekip politikasıdır, bir kural değildir. Küçük bir düzeltme ile büyük bir özellik aynı yolu izlemek zorunda değildir; ama yolu kısaltan her karar, yakalanamayacak hataların bir listesini de beraberinde getirir. Bu listeyi yazmak ve kimin kabul ettiğini bilmek, yolu kısaltmanın ön koşuludur.
Özet
- Bu dersin aşımı: içinde. Sekiz derlemenin hiçbiri beş adımlık bütçeyi aşmadı; bir kez geri çevrilen üç derleme tam beşte kaldı.
- Yayın yolu iç, kapalı, açık ve üretim kanallarından oluşur ve her kanala giriş bir adım sayıldı; bu yüzden hiçbir derleme dört adımın altına inemez.
- Aynı sekiz derleme beş, dört ve üç adımlık bütçelerde sırayla içinde, azında ve hepsinde çıktı.
- Geri çevrilen derleme yolu baştan yürürse adımlar altı ve yediye çıktı, aşım içinden azına geçti.
- Kapalı kanalı yoldan çıkarmak üç adımlık bütçede hepsinden azına indirdi, ama kapalı kanalda yakalanacak bir geri çevirme gözden kaçtı.
- İki kez geri çevrilen dokuzuncu derleme aşan örnek sayısını birden üçe çıkardı; kategori azında kaldı, çünkü kural büyüklüğü görmez.
Sonraki Adım
Derleme kanallardan geçti ve üretime çıkmaya hazır, ama üretime çıkış hemen tüm kullanıcılara olmak zorunda değildir. Sıradaki ders, Aşamalı Yayın, yayını aşama aşama genişletir ve her aşamada çökme sayısını bir eşikle karşılaştırır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.