İçeriğe geç

Pipeline’lar ve otomasyon

Pipeline’lar Control Center’ın deterministik yarısıdır. Neyin söyleneceğine bir ajan karar verir; sırada ne olacağına ise bir pipeline karar verir, hem de her seferinde aynı şekilde. Bir pipeline, ajan gönderebilen, betik çalıştırabilen, bir koşula göre dallanabilen, bir koleksiyon üzerinde dağılabilen ve adımlar arasında veri aktarabilen adımlardan oluşan bir DAG’dır — kalıcıdır, kaldığı yerden devam edebilir ve maliyeti hesaplanır.

Üç nedenle var olurlar: yinelenen çok adımlı bir süreci zincirlemek, birkaç ajanı sırayla ya da paralel olarak eşgüdümlemek ve bir insan orada yokken olan bir şeye tepki vermek.

Bir şablon (PipelineDefinition) bildirimsel DAG’dır: adımlar, bildirilen girdiler ve yapılandırma. Çalışma alanının kendi veritabanında yaşar. Bir çalıştırma (PipelineRun) o şablonun tek bir yürütülmesidir; değiştirilebilir bir durum torbası, maliyet ve token toplamları ile adım başına durum taşır.

Bir şablonun birçok çalıştırması olur. Çalıştırmalar yeniden başlatmaya dayanır: motor, uçuştaki çalıştırmaları yeniden yükler ve kaldıkları yerden devam ettirir.

İki koruma mekanizması, bir adımı sürdürmek yerine bilinçli olarak tüm çalıştırmayı başarısız kılar; çünkü sürdürmek durdurmaktan daha kötü olurdu:

  • suspendedStepTimeout süresinden (varsayılan olarak 24 saat) daha uzun süredir suspended olan bir adım, hiçbir zaman terminal duruma ulaşmayacak biletleri bekliyor demektir; bu yüzden çalıştırmayı serbest bırakmak için başarısız kılınır. Muafiyet extras['awaitApproval'] == true’dur — bu, orchestration.awaitApproval kısmi onay kapısıdır. human.gate muaf değildir.
  • extras: {'idempotent': false} olarak bildirilmiş ve sunucu durduğunda uçuşta olan bir adım, yan etkisini (bir squash merge, bir çalışma ağacı temizliği) çoktan uygulamış olabilir. Yeniden çalıştırmak iki kez uygulamaya yol açabilir; bu yüzden motor onu başarısız kılar ve yeniden denemeyi size bırakır.

Bir adımın birbirinden bağımsız iki parçası vardır ve bunları ayrı tutmak, motorun küçük kalmasını sağlayan şeydir.

Tür (StepKind), motora bir adımın üst adımlarına göre ne zaman çalıştırılabilir hale geldiğini söyler — zamanlayıcının bilmesi gereken tek şey budur. Altı tür vardır: trigger, listen, join, router, forEach ve terminal. Gövde (bodyKey) ise adımın zamanlandıktan sonra yaptığı iştir. Gövdeler, sunucu başlangıcında anahtarla kaydedilen closure’lardır; böylece farklı türlerdeki birçok adım tek bir gövdeyi paylaşabilir: örneğin, hepsi conversation.promptAgent çalıştıran birkaç listen adımı.

Zamanlama semantiği altı türde yaşadığı için, davranış kataloğu kimse zamanlayıcıya dokunmadan büyüyebilir. Türlerin, gövdelerin ve bunların yapılandırmasının tam kataloğu için Pipeline adımları sayfasına bakın.

Kayıt defteri tasarımının iki sonucu, bir şablonu elle yazmadan önce bilmeye değer:

  • bodyKey’i kayıtlı olmayan bir adım, şablon yüklenirken uyarı üretir ve ardından hiç çalışmaz. Çalışma zamanında yüksek sesle başarısız olan bir şey yoktur. trigger ve terminal adımları bu uyarıdan muaftır: tetikleyici yine de hiçbir şey yapmayan pipeline.trigger gövdesini çalıştırır, böylece alt dinleyiciler tetiklenir; bir terminal adımının gövdesi yoktur ve zamanlayıcı için bir nöbetçidir.
  • Bir düğümün extras haritasındaki anahtarlar tam eşleşmelidir, aksi halde sessizce yok sayılır. Bir ajan adımının işini mevcut bir konuşmaya yalnızca extras['spaceId'] yerleştirir. extras['mode'] (chat / plan / review), odayı açan düğümde okunur (messaging.createSpace, varsayılan review) — sonraki bir ajan adımı, katıldığı bir konuşmanın izinlerini yeniden veremez. İki anahtarın başka herhangi bir yazımı yok sayılır.

Adımlar birbirini çağırmaz. Çalıştırma üzerindeki paylaşılan bir durum torbasından okurlar ve oraya yazarlar: bir adım girdilerini anahtarla okur, yürütür ve çıktısını kendi outputKey’i altına geri yazar. Paralel dallar aynı anahtarı hedeflediğinde bir StateReducer eşzamanlı yazmaları birleştirir, bir TemplateRenderer da istemlerdeki ve betiklerdeki {{...}} yer tutucularını aynı durumdan doldurur.

Bir pipeline’ın sonradan incelenebilir olmasının nedeni budur — durum torbası, çalıştırmanın tüm hikâyesidir.

PipelineTrigger satırları, bir şablonun ne zaman kendiliğinden başlayacağını bildirir. Dört tür vardır:

Tetikleyici Şu durumda bir çalıştırma başlatır
Alan olayı Eşleşen bir alan olayı tetiklenir — örneğin PullRequestPublished ya da TicketAssigned
Zamanlama Bir cron/aralık ifadesinin zamanı gelir
Manuel Elle çalıştırırsınız; şablonu çalıştırma seçicisine koyan şey, etkin bir manuel tetikleyicinin varlığıdır
Webhook Harici bir sistem, sunucunun HTTP portundaki /webhooks/<token> adresine POST gönderir

Olay tetikleyicileri kapalı bir kümedir: dağıtıcı 16 olay türü bilir ve bunlar seçicide sunulur (EventPayloadMapper.knownEventTypes); bunların dışında hiçbir şey bir pipeline başlatamaz. Bu 16 türden on dördünün bir yük eşlemesi vardır. İkisinin — TicketCreated ve TicketStatusChanged — hiç yoktur; dolayısıyla bu ikisinden birine kurulan bir tetikleyici etkin bekler ve hiç tetiklenmez. Tam liste için Alan olayları sayfasına bakın.

Webhook token’ı aynı zamanda HMAC gizli anahtarıdır: isteğin X-Hub-Signature-256: sha256=<hex> başlığı HMAC-SHA256(body, token) ile doğrulanır, doğrulanmayan teslimatlar reddedilir ve yeniden oynatılamaz, yinelenenler dedupe_key ile elenir. Tetikleyici satırları (çalışma alanı, olay türü, şablon) üzerinde benzersiz olduğundan, bir şablon en fazla bir webhook tetikleyicisi ve her alan olayı türü için bir tetikleyici tutabilir.

Yerleşik şablonlar manuel ve olay tetikleyicilerini etkin olarak tohumlar; zamanlanmış tetikleyiciler ise devre dışı tohumlanır, böylece düzenli bir tarama her zaman isteğe bağlıdır.

Her çalışma alanına on üç pipeline şablonu tohumlanır ve bunlardan sekizi devre dışı gelir: external_pr_welcome, cross_review, ticket_to_pr, pr_triage, pre_merge_gate, release_notes, dep_audit ve pr_digest.

İnsanları şaşırtan kısım burasıdır. Bunların tetikleyicileri etkin olarak tohumlanır, ama PipelineEngine.start devre dışı bir şablonu reddeder ve null döndürür — böylece tetikleyici boşluğa ateş eder ve hiçbir çalıştırma görünmez. Anahtar, tetikleyici değil şablondur. Bu sekizinden herhangi birinin bir şey yapmasını beklemeden önce Ayarlar → Çalışma alanı → Pipeline şablonları’ndan etkinleştirin.

Bir çalışma alanını yeniden tohumlamak, seçtiğiniz her şeyi korur: isEnabled ayarınız ve mevcut tetikleyici satırlarınız varlığını sürdürür. Tam olarak bir bilinçli istisna vardır — pr_merged_cleanup’ın günlük zamanlaması, daha önce kapalı olsa bile zorla etkinleştirilir; çünkü bu bir çöp toplamadır. O olmadan çalışma ağacı satırları, kod grafiği bölümleri ve yazarken kopyalama kopyaları birikir ve bu hiçbir zaman kullanıcı tercihi olarak düşünülmemişti.

Bilmeye değer bir asimetri daha: pr_review yerleşiği artık bilinçli olarak GitHub’a gönderi yapmaz. Bir incelemeyi yayımlamak ayrı ve kullanıcı onayına bağlı bir adımdır; doğrudan gönderi yapan bir pipeline iki kez yayımlardı. cross_review, ticket_to_pr ve pr_triage ise çalıştıklarında hâlâ doğrudan GitHub’a yorum gönderir.

PipelineEngine çalıştırma kaydını oluşturur, çalıştırmanın olay türüyle eşleşen başlangıç düğümünü zamanlar ve ardından DAG’da ilerler: adımlar tamamlandıkça alt tetikleyicileri değerlendirir, router dallarını çözer, join’leri bekler, yeniden deneme politikalarını ve başarısızlıkta devamı uygular; her adımda durumu, maliyeti ve hataları kalıcı hale getirir. Başka bir başlangıçtan çıkan kenarlar o çalıştırma için yok sayılır; böylece bir zamanlama ateşlemesi, yalnızca manuel başlatmaya özgü bir koşulu beklemez.

Bilmediği şey ise biletleme, gönderim, GitHub veya mesajlaşmaya dair herhangi bir şeydir. Tek genişleme dikişi PipelineBodyRegistry’dir. Oraya kayıtlı gövdeler, AgentDispatchPort, MessagingPort ve kardeşlerini tutan şeylerdir — pipeline’lara bir yetenek eklemenin neden hiçbir zaman zamanlayıcıyı değiştirmek anlamına gelmediğinin nedeni de budur.

Başarısız olan bir adım, hata mesajını kaydeder ve failed durumuna geçer. Adım continueOnFail bildiriyorsa alt adımlar ilerler ve hata çalıştırma durumunda saklanır; aksi halde çalıştırma başarısız olur. Bir StepRetryPolicy’ye sahip adım, bu ikisinden biri uygulanmadan önce doğrusal veya üstel artan beklemeyle yeniden denenir.