פייפליינים ואוטומציה
פייפליינים הם החצי הדטרמיניסטי של Control Center. סוכן מחליט מה לומר; פייפליין מחליט מה יקרה בהמשך, באותו אופן בכל פעם. פייפליין הוא DAG של שלבים שיכולים לשלוח סוכנים, להריץ סקריפטים, להסתעף לפי תנאי, להתפצל על פני אוסף ולהעביר נתונים בין שלבים — נשמר, ניתן לחידוש ומתומחר.
הם קיימים משלוש סיבות: לשרשר תהליך רב-שלבי חוזר, לתאם כמה סוכנים ברצף או במקביל, ולהגיב למשהו שקרה בלי שאדם היה שם.
תבניות והרצות
קטע בשם “תבניות והרצות”תבנית (PipelineDefinition) היא ה-DAG הדקלרטיבי: שלבים, קלטים
מוצהרים ותצורה. היא מתגוררת במסד הנתונים של סביבת העבודה עצמה. הרצה
(PipelineRun) היא ביצוע אחד של אותה תבנית, והיא נושאת מאגר מצב
ניתן לשינוי, סכומי עלות וטוקנים וסטטוס לכל שלב.
לתבנית אחת יש הרצות רבות. הרצות שורדות הפעלה מחדש: המנוע טוען מחדש הרצות פעילות וממשיך אותן מהמקום שבו נעצרו.
שני מנגנוני רשת ביטחון מכשילים בכוונה את ההרצה כולה במקום לחדש שלב, מפני שחידוש יהיה גרוע מעצירה:
- שלב שנמצא במצב
suspendedיותר מ-suspendedStepTimeout(24 שעות כברירת מחדל) ממתין לכרטיסים שלעולם לא יגיעו למצב סופי, ולכן הוא מוכשל כדי לשחרר את ההרצה. הפטור הואextras['awaitApproval'] == true— זהו שער האישור החלקיorchestration.awaitApproval.human.gateאינו פטור. - שלב שהוצהר עם
extras: {'idempotent': false}והיה באמצע ריצה כשהשרת נעצר עשוי כבר להחיל את תוצאת הלוואי שלו (מיזוג squash, ניקוי עץ עבודה). הרצה חוזרת שלו עלולה להחיל אותה פעמיים, ולכן המנוע מכשיל אותו ומשאיר את הניסיון החוזר לכם.
הסוג מתזמן, הגוף עובד
קטע בשם “הסוג מתזמן, הגוף עובד”לשלב יש שני חלקים אורתוגונליים, וההפרדה ביניהם היא מה שמאפשר למנוע להישאר קטן.
הסוג (StepKind) אומר למנוע מתי שלב נעשה בר-הרצה ביחס לשלבים
שבמעלה הזרם — זה הדבר היחיד שהמתזמן צריך לדעת. ישנם שישה: trigger, listen,
join, router, forEach ו-terminal. הגוף (bodyKey) הוא ה_עבודה_
שהשלב מבצע לאחר שתוזמן. גופים הם סגירות הרשומות לפי מפתח עם עליית השרת, כך
ששלבים רבים מסוגים שונים יכולים לחלוק גוף אחד: כמה שלבי listen שמריצים
כולם conversation.promptAgent, למשל.
מכיוון שסמנטיקת התזמון חיה בשישה סוגים, קטלוג ההתנהגויות יכול לגדול בלי שאף אחד ייגע במתזמן. ראו שלבי פייפליין לקטלוג המלא של סוגים, גופים והתצורה שלהם.
שתי השלכות של עיצוב המרשם כדאי להכיר לפני שאתם כותבים תבנית ביד:
- שלב שה-
bodyKeyשלו אינו רשום מפיק אזהרה בעת טעינת התבנית ואז לעולם אינו מבוצע. שום דבר לא נכשל בקול רם בזמן ריצה. שלביtriggerו-terminalפטורים מהאזהרה הזו: הטריגר עדיין מריץ את גוף ה-pipeline.triggerשאינו עושה דבר, כדי שמאזינים במורד הזרם יופעלו; שלבterminalאינו בעל גוף והוא זקיף של המתזמן. - מפתחות במפת ה-
extrasשל צומת הם בהתאמה מדויקת, ואחרת מתעלמים מהם בשקט. רקextras['spaceId']מציב את עבודתו של שלב סוכן בשיחה קיימת.extras['mode'](chat/plan/review) נקרא בצומת שפותח את החדר (messaging.createSpace, ברירת מחדלreview) — שלב סוכן מאוחר יותר אינו יכול להעניק מחדש הרשאה לשיחה שהוא הצטרף אליה. כל איות אחר של מי מהמפתחות מתעלמים ממנו.
מצב וזרימת נתונים
קטע בשם “מצב וזרימת נתונים”שלבים לא קוראים זה לזה. הם קוראים ממאגר מצב משותף של ההרצה וכותבים אליו:
שלב קורא את הקלטים שלו לפי מפתח, מבצע, וכותב את הפלט שלו חזרה תחת
ה-outputKey שלו. StateReducer ממזג כתיבות מקבילות כשענפים מקבילים
מכוונים לאותו מפתח, ו-TemplateRenderer מחליף מחזיקי מקום {{...}}
בהנחיות ובסקריפטים מאותו מצב.
זו הסיבה שפייפליין ניתן לבדיקה בדיעבד — מאגר המצב הוא כל סיפור ההרצה.
מה מפעיל הרצה
קטע בשם “מה מפעיל הרצה”רשומות PipelineTrigger מצהירות מתי תבנית מופעלת אוטומטית. ישנם ארבעה
סוגים:
| טריגר | מפעיל הרצה כאשר |
|---|---|
| אירוע תחום | אירוע תחום תואם נורה — למשל PullRequestPublished או TicketAssigned |
| לוח זמנים | מגיע מועד של ביטוי cron/מרווח |
| ידני | אתם מריצים אותו ביד; נוכחותו של טריגר ידני מופעל היא מה שמציג את התבנית בבורר ההרצה |
| Webhook | מערכת חיצונית שולחת POST אל /webhooks/<token> בפורט ה-HTTP של השרת |
טריגרי אירוע הם קבוצה סגורה: 16 סוגי אירועים מוכרים למפעיל ומוצעים בבורר
(EventPayloadMapper.knownEventTypes), ושום דבר אחר אינו יכול להתחיל
פייפליין. לארבעה-עשר מתוך 16 האלה יש מיפוי מטען. לשניים —
TicketCreated ו-TicketStatusChanged — אין כזה, ולכן טריגר על מי מהם
נשאר מופעל ולעולם אינו נורה. ראו
אירועי תחום לרשימה המלאה.
אסימון ה-webhook משמש גם כסוד ה-HMAC: הכותרת
X-Hub-Signature-256: sha256=<hex> של הבקשה מאומתת מול
HMAC-SHA256(body, token), משלוחים שאינם מאומתים נדחים ואינם ניתנים
לשליחה חוזרת, וכפילויות נזרקות על ידי dedupe_key. מכיוון שרשומות טריגר
ייחודיות לפי (סביבת עבודה, סוג אירוע, תבנית), תבנית יכולה להחזיק לכל
היותר טריגר webhook אחד וטריגר אחד לכל סוג אירוע תחום.
התבניות המובנות זורעות את הטריגרים הידניים וטריגרי האירועים שלהן מופעלים; טריגרים מתוזמנים נזרעים מושבתים, כך שסבב חוזר הוא תמיד בחירה מפורשת.
התבניות שמגיעות מושבתות
קטע בשם “התבניות שמגיעות מושבתות”שלוש-עשרה תבניות פייפליין נזרעות לכל סביבת עבודה, ושמונה מהן מגיעות
מושבתות: external_pr_welcome, cross_review, ticket_to_pr,
pr_triage, pre_merge_gate, release_notes, dep_audit ו-pr_digest.
זה החלק שמפתיע אנשים. הטריגרים שלהן נזרעים מופעלים, אבל
PipelineEngine.start מסרב לתבנית מושבתת ומחזיר null — כך שהטריגר נורה
אל תוך כלום ולא מופיעה שום הרצה. התבנית, ולא הטריגר, היא המתג. הפעילו
אותה במסך הגדרות ← סביבת עבודה ← תבניות פייפליין לפני שתצפו שמי מהשמונה האלה
יעשה משהו.
זריעה מחדש של סביבת עבודה משמרת את מה שבחרתם: הגדרת ה-isEnabled שלכם
ורשומות הטריגר הקיימות שורדות. יש חריג מכוון אחד בדיוק — לוח הזמנים היומי
של pr_merged_cleanup מופעל בכוח גם אם היה כבוי קודם, מפני שזהו איסוף
אשפה. רשומות עצי עבודה, מחיצות של גרף הקוד ועותקים copy-on-write
מצטברים בלעדיו, וזה מעולם לא נועד להיות בחירה של המשתמש.
עוד א-סימטריה אחת שכדאי להכיר: הפייפליין המובנה pr_review כבר לא
מפרסם ל-GitHub, במכוון. פרסום סקירה הוא שלב נפרד שעובר בשער של משתמש,
ופייפליין שמפרסם ישירות יפרסם פעמיים. cross_review,
ticket_to_pr ו-pr_triage עדיין מפרסמים הערה ישירות ל-GitHub כשהם
רצים.
מה המנוע יודע
קטע בשם “מה המנוע יודע”PipelineEngine יוצר את רשומת ההרצה, מתזמן את צומת ההתחלה שמתאים
לסוג האירוע של ההרצה, ואז צועד ב-DAG: כששלבים מסתיימים הוא מעריך
טריגרים במורד הזרם, מכריע ענפי router, ממתין ל-join, מיישם מדיניות ניסיון
חוזר ו-continue-on-fail, ושומר מצב, עלות ושגיאות בכל שלב. קשתות שיוצאות
מ-start אחר מתעלמים מהן בהרצה הזו, כך שהפעלה מתוזמנת אינה ממתינה לתנאי
המיועד להרצה ידנית בלבד.
מה שהוא לא יודע הוא שום דבר הקשור לכרטוס, שליחה, GitHub או הודעות. נקודת
ההרחבה היחידה שלו היא ה-PipelineBodyRegistry. הגופים הרשומים שם הם
שמחזיקים את AgentDispatchPort, MessagingPort ואחיהם — ולכן הוספת
יכולת לפייפליינים לעולם אינה מחייבת שינוי של המתזמן.
טיפול בשגיאות
קטע בשם “טיפול בשגיאות”שלב שנכשל רושם את הודעת השגיאה שלו ועובר ל-failed. אם השלב מצהיר
continueOnFail, שלבי ההמשך ממשיכים והשגיאה נשמרת במצב ההרצה; אחרת
ההרצה נכשלת. שלב עם StepRetryPolicy מנוסה שוב קודם, עם השהיה לינארית
או מעריכית, לפני שאחד משני אלה חל.
ראו גם
קטע בשם “ראו גם”- אירועי תחום: למה מאזין טריגר אירוע
- תזמור: תוכנית שאתם מאשרים, שנאספת לאחד מהפייפליינים האלה
- כרטיסים והאצלה: מה ששלבי פייפליין יוצרים ומשלימים
- שלבי פייפליין: הקטלוג המלא של סוגים, גופים ותצורה
- בנו את הפייפליין הראשון
- יצירת תבנית פייפליין
- הפעלת פייפליין ידנית
- מעקב אחר הרצות פייפליין
- הגדרת טריגרים לפייפליין