İçeriğe geç
academia.sh

Ders 09 / 14

Mobil Sürekli Teslimat

Mobil sürekli teslimat, kod değişikliğini imzalı bir yapıya çevirip test kanalından ve mağaza incelemesinden geçirir. Ders, aynı imzalı yapının üretimde kapalı bir bayrakla çıktığında özelliğin ne kadar çalıştığını ölçer.

Yayın Güncelleme

Bu derste

  • İmzalama, sertifika ve sağlama profilinin bir yapıyı yayına hazır kılmadaki yerini açıklar
  • Derleme, yükleme ve test dağıtımı adımlarını bir teslimat hattında sıralar
  • Hazırlık ve üretim aşamasının koşulunu ayrı ayrı kurup özelliğin işlerliğini ölçer
  • İmzalı ve yüklenmiş bir yapıda da özellik bayrağının özelliği kapatabildiğini gösterir
İçindekiler

Önceki derslerde bir özelliğin işlerliğini aygıtın durumu belirledi: ağ vardı ya da yoktu, arka plan işi kısılmıştı ya da kısılmamıştı. Bu ders koşulun kaynağını aygıttan aşamaya taşır. Uygulama kullanıcıya ulaşmadan önce bir hattan geçer; hat yapıyı derler, imzalar, yükler ve bir kanaldan dağıtır. Aynı yapı farklı aşamalarda farklı bayrak değerleriyle çalışabilir; bayrağın değeri o aşamada hangi yeteneğin var olduğunu söyler.

Kursun sorusu değişmez: bu koşulda bu özellik ne kadar çalışıyor? Açılış dersindeki dokuz kayıt beş tam, bir kısıtlı, iki ertelenen ve bir kapalı çıkmıştı. Bu ders o sayıları değiştirmez; yalnız kendi kesitini, yapının koşulunu ölçer.

Mobilde Sürekli Teslimat

Sürekli teslimat, kod değişikliğinin her seferinde aynı adımlarla ve elle müdahale olmadan yayına hazır bir yapıya dönüşmesidir. Web uygulamasında bu hattın sonunda sunucu güncellenir ve herkes yeni sürümü görür. Mobilde hattın sonunda bir yapı vardır ve o yapı kullanıcının aygıtına kurulmayı bekler. Kullanıcı güncellemeyi kabul edene kadar eski sürüm aygıtta çalışmaya devam eder.

Bir sınır daha vardır. Hat yapıyı yayına hazır hâle getirir, ama yayının son adımı uygulama mağazasının ya da Android mağazasının mağaza incelemesinden geçer ve o aşama hattın elinde değildir. Bu yüzden mobil hatlar iki parçalıdır: mağazaya girmeden önce ekibin denetlediği aşamalar, mağazaya girdikten sonra bekleyen aşamalar. Ekip ilk parçayı otomatikleştirir, ikinci parçayı planlar.

M12/K05’te bir davranışın üretime çıkıp çıkmadığı soruldu. İşlerlik başka bir şey sorar. Üretime çıkan bir yapıda da bir özellik bayrağı kapalı olabilir; işlerlik yapının nereye çıktığını değil, çıkan yapıda özelliğin ne kadar çalıştığını sınıflar.

İmzalama, Sertifika ve Sağlama Profili

Bir yapı imzalanmadan mağazaya girmez. İmzalama, yapının kimin tarafından üretildiğini ve üretildikten sonra değişmediğini kanıtlar. iOS’ta imza bir sertifikayla atılır; yapı ayrıca hangi uygulama kimliğine, hangi yetkilere ve hangi dağıtım türüne ait olduğunu söyleyen bir sağlama profiliyle eşlenir. Sertifikanın bir geçerlilik süresi vardır ve süresi dolan sertifika yeni yapının imzalanmasını engeller. Android’de imza bir anahtara bağlıdır; imzalama kimliği uygulamanın kimliğinin parçasıdır, bu yüzden imza anahtarını ekip kendisi saklıyorsa anahtarın yitirilmesi geri alınamaz, sızması da yalnız bir yapıyı değil uygulamanın bütün sürüm geçmişini ilgilendirir. İmza anahtarını mağaza saklıyorsa ekibin elindeki yükleme anahtarı yitirildiğinde mağaza üzerinden yenilenebilir.

İki platformda da kural aynıdır: imzalama gizli değerle yapılır ve gizli değer depoya konmaz. Hat, sertifikayı, sağlama profilini ve anahtarı gizli değer deposundan okur ve yalnız imzalama adımı süresince kullanır. İmzalama bilgisi bir geliştiricinin bilgisayarında kalırsa hat o kişiye bağımlı olur; bu, sürekli teslimatın çözmeye çalıştığı sorunun kendisidir.

Derleme, Yükleme ve Test Dağıtımı

Hat genellikle üç aşamaya bölünür. Derleme aşaması temiz bir ortamda koddan yapıyı üretir ve her çalışmada derleme numarasını bir artırır. İmzalama aşaması yapıyı imzalar. Yükleme aşaması imzalı yapıyı mağazanın yayın konsoluna ya da bir test dağıtım kanalına gönderir. Test dağıtım kanalı, yapıyı tam mağaza incelemesinden geçirmeden belirli kullanıcılara ulaştırır. iOS’ta ekip dışından test kullanıcıları çağrıldığında ilk yapı ayrı bir test incelemesine girer; ekip, üretime çıkacak yapıyı önce kendi aygıtlarında ve test kullanıcılarında dener.

Aşağıdaki parça bu aşamaların bir yapılandırmadaki biçimini gösterir. Parça ölçülmez; alan adları örnektir.

# Platform kodu: teslimat hatti asamalari
pipeline:
  - stage: build
    steps: [compile, sign]
    signing:
      certificate: from-secret-store
      profile: store-distribution
  - stage: upload
    steps: [upload-to-test-channel]
  - stage: release
    needs-approval: true
    steps: [upload-to-store, submit-for-review]

Son aşamadaki needs-approval satırı hattın bilerek durduğu yeri gösterir. Yapı test kanalında dolaşırken sorun çıkmadıysa bir insan onay verir ve yapı mağaza incelemesine gönderilir. Otomasyon yükü alır, karar insanda kalır.

Hattı Güvenilir Kılan Alışkanlıklar

Hattın değeri hızından çok tekrarlanabilirliğinden gelir. Birkaç alışkanlık bunu korur.

Birincisi, test kanalında denenen yapı ile mağazaya giden yapı aynı olmalıdır. Hazırlık için bir yapı, üretim için ikinci bir yapı derlenirse, denenen şey ile yayımlanan şey arasında bir fark doğabilir. Bu yüzden hat yapıyı bir kez üretir ve aynı dosyayı bir aşamadan ötekine taşır. Aşamalar arasındaki fark yapının içeriğinde değil, aşamanın yapılandırmasında olur.

İkincisi, derleme numarası hiçbir zaman geri gitmez ve iki yapıda aynı olmaz. Mağazalar aynı derleme numarasıyla ikinci bir yüklemeyi kabul etmez; numarayı elle yönetmek, hattın en sık takıldığı yerlerden biridir. Numarayı hat artırır, ve insan yalnız sürüm numarasına karar verir. İkisinin farkı sonraki dersin konusudur.

Üçüncüsü, bir aşama başarısız olursa hat durur ve yarım bir yapı yüklenmez. İmzalama adımı hata verdiyse yükleme adımı çalışmaz; test kanalına yalnız imzalı ve bütün bir yapı çıkar. Başarısız bir çalışmanın günlüğü ekibin ilk baktığı yerdir, ve o günlükte gizli değer görünmemelidir.

Dördüncüsü, mağaza incelemesinin reddi planın içindedir. Reddedilen bir yapı için düzeltme yeni bir derleme numarası alır ve hat baştan koşar. Hattın otomatik olması bu döngüyü kısaltır, ama mağazanın kararını beklemek ekibin yönetebileceği bir şey değildir.

Yapının Koşulunu Ölçmek

Hattın ürettiği yapı işlerlik açısından tek bir bilgiyi aşamanın yapılandırmasından alır: hangi özellik bayraklarının hangi değerle bulunduğu. Hazırlık aşamasının yapılandırmasında yeni ödeme akışının bayrağı açıktır, çünkü ekip onu denemek ister. Üretim aşamasının yapılandırmasında kapalıdır, çünkü akış henüz kullanıcıya verilmeyecektir. Aşağıdaki çekirdek ilk dersten tanıdıktır ve her derste aynı biçimde yeniden verilir; ders ona dokunmaz.

// operability.mjs — bir ozelligin bir kosulda ne kadar calistigini siniflandirir
export const LEVELS = ["tam", "kisitli", "ertelenen", "kapali"];
const FALLBACKS = ["kisitli", "ertelenen"];

export function feature(name, needs, fallback = {}) {
  return { name, needs, fallback };
}

export function condition(name, has) {
  return { name, has };
}

function judge(item, cond) {
  const missing = item.needs.filter((need) => !cond.has.includes(need)).sort();
  let level = "tam";
  for (const need of missing) {
    const given = FALLBACKS.includes(item.fallback[need]) ? item.fallback[need] : "kapali";
    if (LEVELS.indexOf(given) > LEVELS.indexOf(level)) level = given;
  }
  return { level, feature: item.name, condition: cond.name, missing };
}

export function assess(features, conditions) {
  const records = [];
  for (const cond of conditions) {
    for (const item of features) records.push(judge(item, cond));
  }
  return records;
}

export function printLevels(records) {
  for (const r of records) {
    const missing = r.missing.length === 0 ? "-" : r.missing.join(",");
    console.log(`${r.level}: ${r.feature} @ ${r.condition} eksik=${missing}`);
  }
}

export function countLevels(records) {
  for (const name of LEVELS) {
    console.log(`${name}: ${records.filter((r) => r.level === name).length}`);
  }
  console.log(`etkilenen: ${records.filter((r) => r.level !== "tam").length}`);
}

Çekirdeğin ardından dersin yardımcı dosyası gelir. configFor(stage) bir hat aşamasından koşul üretir: ağ her aşamada vardır, bayrak yeteneği ise yalnız aşamanın açık bayrakları için eklenir. Yetenek dizgisi flag: önekiyle yazılır. Özellikler üçtür. NewCheckout yeni ödeme akışıdır ve ağı ve flag:new-checkout yeteneğini ister; bayrağın yedeği yoktur. LegacyCheckout eski ödeme akışıdır ve yalnız ağı ister. Catalog ürün listesidir ve o da yalnız ağı ister.

// delivery.mjs — hat asamasindan kosul uretir
import { feature, condition } from "./operability.mjs";

export function configFor(stage) {
  const flags = stage.flags.map((name) => `flag:${name}`);
  return condition(stage.name, ["network", ...flags]);
}

export const checkoutFeatures = [
  feature("NewCheckout", ["network", "flag:new-checkout"]),
  feature("LegacyCheckout", ["network"]),
  feature("Catalog", ["network"]),
];

YI1. Model, bayrağı bir yetenek olarak kurar: bayrak aşamanın yapılandırmasında ya vardır ya yoktur. Gerçek bir uygulamada bayrağın değeri yapıya gömülü olabilir ya da uzaktan yapılandırmadan gelebilir; kural bu ayrımı görmez, yalnız has listesine bakar. Model, bu işlerliğin kuralını kurar; model çerçevenin kendisi değildir.

İlk ölçüm aynı derleme numarasıyla iki aşamayı yan yana koyar. Yapı bir kez derlenmiş ve imzalanmıştır; hazırlık ile üretim arasındaki fark yalnız açık bayrak listesidir. Derleme satırları dersin yerel çıktısıdır; kayıt satırları assess çıktısıdır.

// main.mjs
import { assess, printLevels } from "./operability.mjs";
import { configFor, checkoutFeatures } from "./delivery.mjs";

const build = { number: 42, signed: true, uploaded: true };
const stages = [
  { name: "staging", flags: ["new-checkout"] },
  { name: "production", flags: [] },
];
for (const stage of stages) {
  console.log(`derleme: ${build.number} asama=${stage.name} imzali=${build.signed ? "evet" : "hayir"}`);
}
printLevels(assess(checkoutFeatures, stages.map(configFor)));
derleme: 42 asama=staging imzali=evet
derleme: 42 asama=production imzali=evet
tam: NewCheckout @ staging eksik=-
tam: LegacyCheckout @ staging eksik=-
tam: Catalog @ staging eksik=-
kapali: NewCheckout @ production eksik=flag:new-checkout
tam: LegacyCheckout @ production eksik=-
tam: Catalog @ production eksik=-

Hazırlıkta üç özellik de tamdır. Üretimde ise NewCheckout kapalı çıkar: eksik olan flag:new-checkout yeteneğidir ve onun yedeği tanımlanmamıştır. LegacyCheckout ve Catalog aynı üretim yapısında tam kalır. Kapalı olan özelliğin işi sonraya da kalmaz; kullanıcı ödeme için eski akışı kullanır. Eski akışın tam olması yeni akışın yedeği olduğu anlamına gelmez. İkisi ayrı özelliktir ve ayrı kayıt alır.

Yapı Sabit, Bayrak Değişir

Bayrak üretimde açılabilir, ve bunun için yeni bir yapı gerekmeyebilir. Bayrağın değeri uzaktan yapılandırmadan okunuyorsa ekip değeri değiştirir, uygulama bir sonraki okumada yeni değeri alır. Bu, mobilde sürekli teslimatın en değerli ayrımlarından biridir: yapıyı mağazaya göndermek ile davranışı kullanıcıya açmak iki ayrı iştir. Birincisi mağaza incelemesine tabidir, ikincisi değildir.

İkinci ölçüm aynı üretim yapısını bayrak kapalıyken ve açıkken karşılaştırır. Koşul adları farklıdır, çünkü iki koşulun adı aynı olamaz; yapı ve derleme numarası aynıdır.

// main.mjs
import { assess, printLevels } from "./operability.mjs";
import { configFor, checkoutFeatures } from "./delivery.mjs";

const closed = { name: "production", flags: [] };
const opened = { name: "production-flag-on", flags: ["new-checkout"] };
printLevels(assess(checkoutFeatures, [closed, opened].map(configFor)));
kapali: NewCheckout @ production eksik=flag:new-checkout
tam: LegacyCheckout @ production eksik=-
tam: Catalog @ production eksik=-
tam: NewCheckout @ production-flag-on eksik=-
tam: LegacyCheckout @ production-flag-on eksik=-
tam: Catalog @ production-flag-on eksik=-

Bayrak açılınca NewCheckout kapalıdan tama geçer; öteki iki özellik hiç değişmez. Kural bayrağın açılışının nasıl yapıldığını görmez: uzaktan yapılandırma, yeni bir yapı ya da elle değiştirilen bir değer aynı yeteneği verir. Kuralın baktığı şey, açılışın sonunda yeteneğin var olup olmadığıdır.

YI2. Model bayrağın açılışının yaygınlaşmasını göstermez. Gerçek bir uygulamada uzaktan yapılandırma her aygıta aynı anda ulaşmaz; aygıtlar değeri farklı zamanlarda okur. Bu dağılım bir sonraki dersin konusudur ve bu derste tek bir uygulama örneğinin koşulu ölçülür.

Sınırlayıcı Ölçüm

Bu dersin odak kaydı NewCheckout @ production’dır. Sınırlayıcı ölçüm iki şeyi birlikte gösterir. Birincisi, odak kayıt hazırlık aşamasında tam, üretim aşamasında kapalıdır ve altı kaydın yalnız biri etkilenir. İkincisi, modelde yapının imzalanıp yüklenmesi kayda girmez: imzalı ve yüklenmiş bir yapı ile henüz imzalanmamış bir yapı aynı üretim koşulunda aynı kaydı üretir. Bu bir gözlem değil, modelin tanımıdır; koşulu kuran configFor işlevi build alanını hiç okumaz.

// main.mjs
import { assess, printLevels, countLevels } from "./operability.mjs";
import { configFor, checkoutFeatures } from "./delivery.mjs";

const stages = [
  { name: "staging", flags: ["new-checkout"] },
  { name: "production", flags: [] },
];
const records = assess(checkoutFeatures, stages.map(configFor));
printLevels(records.filter((r) => r.feature === "NewCheckout"));
countLevels(records);

const signed = { number: 42, signed: true, uploaded: true };
const unsigned = { number: 43, signed: false, uploaded: false };
const withBuild = (build) =>
  assess(checkoutFeatures, [{ name: "production", flags: [], build }].map(configFor));
const same = JSON.stringify(withBuild(signed)) === JSON.stringify(withBuild(unsigned));
console.log(`imza kayda girmez: ${same ? "evet" : "hayir"}`);
tam: NewCheckout @ staging eksik=-
kapali: NewCheckout @ production eksik=flag:new-checkout
tam: 5
kisitli: 0
ertelenen: 0
kapali: 1
etkilenen: 1
imza kayda girmez: evet

İlk iki satır dersin işlerliğini taşır: aynı özellik, aynı kod, aynı derleme numarası; yalnız bayrağın aşamanın yapılandırmasında olup olmaması değişti ve kayıt tamdan kapalıya geçti. Sayım satırları altı kayıttan beşinin tam, birinin kapalı olduğunu söyler; etkilenen birdir.

Son satır modelin sınırını açıkça gösterir. İmza, sertifika ve yükleme, bir yapının mağazaya girebilmesi için gerekli şartlardır ama özelliğin ihtiyaç duyduğu yetenekler değildir. İmzalanmamış bir yapı mağazaya hiç girmeyecektir; ama kural, mağazaya girmiş bir yapının içindeki özelliği sınıflar. Hattın başarısı ile özelliğin çalışması iki ayrı soruya cevap verir. Hat yeşil olabilir, imza geçerli olabilir, yükleme tamamlanabilir ve kullanıcı yine de yeni ödeme akışını göremez.

Bu ayrım iş akışını da değiştirir. Üretime çıkışta bir özelliğin çalışmadığı görüldüğünde ilk bakılacak yer hattın günlüğü değildir; aşamanın yapılandırmasındaki bayrak değeridir.

Özet

  • Bu dersin işlerliği: kapalı. NewCheckout @ production, üretim aşamasının yapılandırmasında flag:new-checkout yeteneği bulunmadığı ve bayrağın yedeği olmadığı için kapalı çıktı; aynı aşamada LegacyCheckout ve Catalog tam kaldı.
  • Mobil hat yapıyı derler, imzalar, yükler ve test dağıtım kanalına verir; son aşama mağaza incelemesidir ve hattın elinde değildir.
  • İmzalama sertifika, sağlama profili ve anahtar gibi gizli değerlere dayanır; bu değerler depoda değil, hattın gizli değer deposunda durur.
  • Hazırlıkta üç özellik tam, üretimde biri kapalıydı; altı kayıtta etkilenen bir çıktı. Bayrak açılınca aynı üretim yapısında kayıt tama döndü.
  • Modelde imzalı ve yüklenmiş bir yapı ile imzalanmamış bir yapı aynı kaydı verir; bu eşitlik ölçülmüş bir bulgu değildir. Yapının hazır olması işlerliği belirlemez.

Sonraki Adım

Bu derste yapı tek bir derleme numarasıyla anıldı ve ona hiçbir anlam yüklenmedi. Sıradaki ders, Sürüm Yönetimi, sürüm numarası ile derleme numarasının farkını, anlamlı sürümlemeyi ve sürüm notunu ele alır. Sonra istemci ile sunucu arasındaki sözleşmeyi sürümle ilişkilendirir ve yalnız eski sözleşmeyi sunan bir sunucuda yeni sözleşmeyi isteyen sipariş geçmişinin ne kadar çalıştığını ölçer.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ ↵ Esc gezin · aç · kapat