CI/CD למונורפו: היכן הבנייה נשברת
מונורפו מנצח בהתחלה ומתחיל להאט את השחרור עם הגידול בנפח. צוואר הבקבוק הראשון הוא בנייה של כל עץ החבילות בכל שינוי: תיקון בשירות אחד גורר בדיקות, לינטרים ובנייה של האחרים, וזמן הבנייה גדל ממספר החבילות, לא מגודל התיקון. ההמתנה לבנייה לפני שחרור הופכת לחלק ממחזור השחרור, ולא להכנה שלו.
הסיבה בדרך כלל אינה בעוצמת הסוכנים, אלא בהיעדר גרף השפעה. כל עוד המשימות לא יודעות מאילו חבילות הן תלויות, המתכנן לא יכול לדלג על ענפים שלא נגעו בהם ולעשות שימוש חוזר בתוצאות של ריצות קודמות. מטמון לפי האש של קלטים — קבצים וגרסאות של תלויות — מחזיר תוצאה בתוך שניות, אם הקלטים לא השתנו.
הבא בתור — קונפליקטים של גרסאות תלויות. ספרייה משותפת מעלה גרסה מאג'ורית, חלק מהחבילות נשארות בגרסה הקודמת, ובעץ אחד חיות שני עותקים לא תואמים. באופן מקומי הבנייה עוברת, אבל בשלבים משותפים מתפצלים הטיפוסים וההתנהגות של כלי העזר: צריך לחפש בחבילה שהמחבר של התיקון לא נגע בה.
כאב נפרד — כשל של בדיקות על חבילות זרות. בדיקה נכשלת שאין לתיקון קשר אליה, הענף לא ממוזג, הגזע אדום — ומופיעות עקיפות בדמות שלבים מושבתים. בהמשך נפרט איך זה נסגר: גרף השפעה, מטמון מרוחק וכללים לגרסאות של מודולים משותפים.
האפקט של פייפליין אחיד: מהירות ויכולת חיזוי
האפקט המורגש הראשון — בנייה של חבילות שנגעו בהן במקום כל המאגר. הפייפליין בונה גרף תלויות ובכל שינוי מריץ רק משימות שהקלטים שלהן השתנו: תיקון בחבילה אחת כבר לא גורר בנייה מחדש של כל העץ.
מטמון של תוצאות בנייה פועל לפי האש של קלטי המשימה — קבצים, משתני סביבה, גרסת כלים — ולכן ריצה חוזרת על אותה רוויזיה לוקחת ארטיפקט מוכן במקום חישוב מחדש.
מכאן המסקנה השנייה — שחזוריות של השחרור. Bazel ומערכות בנייה מאותה משפחה דורשות קלטים מתוארים במפורש לכל יעד, ולכן התוצאה מפסיקה להיות תלויה במה שכבר נמצא על מכונת בנייה מסוימת.
אותו קומיט נותן ארטיפקט זהה אצל המפתח, בפייפליין ובסביבת הבדיקות: פערים נתפסים בבדיקה, ולא בסביבת הייצור החיה.
המדד השלישי, שבדרך כלל לא נמדד, הוא שיעור הכשלים השגויים. כל עוד הבנייה תלויה בסדר המשימות ובמטמון מחומם של בונה אחד, הפייפליין מאדים סתם, והצוות מתרגל להפעיל מחדש בעיניים עצומות. גרף נקי ושלבים מבודדים מסירים את זה: תוצאה אדומה שוב אומרת תקלה אמיתית.
זמן ההתאוששות אחרי כשל מתקצר בזכות אותו מטמון וחזרה לרוויזיה קודמת — הפייפליין חוזר רק על הענף שנפל, ולא על כל המסלול מאפס. התוצאה בשינוי טיפוסי: זמן הבנייה יורד בסדר גודל, היכולת לחזור על התוצאה מפסיקה להיות עניין של אמונה, ושחרור כושל מוחזר אחורה ומשוחזר בצורה צפויה.
סדר היישום: מביקורת ועד מסירה
סדר העבודות אינו שרירותי: כל שלב הבא נשען על הנתונים של השלב הקודם. קודם כל אוספים עובדות — זמן בנייה לפי משימות, הרכב ריצות חוזרות, התנהגות המטמון — ורק אחר כך משנים את התצורה. כך שינויים בפייפליין נשענים על מדידות, ולא על הנחות לגבי מה «מאט».
- ביקורת שלבי בנייה. מריצים את הפייפליין הקיים, מודדים את הזמן של כל משימה וסופרים כמה עבודה מבוצעת מחדש כשהקבצים לא השתנו.
- תרשים תלויות של חבילות. בונים גרף: מה תלוי במה, אילו חבילות נבנות במקביל, היכן קשרים מעגליים מפריעים לפיצול למשימות בלתי תלויות.
- תכנון כללי הפעלה. מקבעים אילו משימות עולות על חבילה שהשתנתה והחבילות התלויות בה, איך מחושב מפתח המטמון, מה קורה בענפים ובתגיות שחרור.
- הגדרת סביבות בנייה. מאחדים גרסאות כלים על הסוכנים לסט אחד, כדי שריצה מקומית והפייפליין ייתנו תוצאה זהה וכשלים ישתחזרו.
- בדיקה על שינויים אמיתיים. מריצים את הפייפליין על קומיטים אמיתיים: תיקון בחבילת עלה, עדכון ספרייה משותפת, חזרה לשחרור קודם.
- מסירת הפייפליין לצוות. מוסרים תצורות עם הערות, מנתחים כשלים טיפוסיים ואת סדר הטיפול בהם, פותחים הרשאות ומשלימים תיעוד.
מה נשאר במאגר אחרי היישום
הלקוח מקבל לא «שרת מוגדר», אלא סט ארטיפקטים שלפיו הצוות מפתח את הבנייה בלעדינו — עבור מונורפו על Turborepo, Nx או Bazel. כל סעיף נמצא במאגר לצד הקוד ועובר סקירה כמו שינוי רגיל.
- תצורת פייפליין — אילו משימות מופעלות על שינוי, מה נשמר במטמון בין הפעלות, אילו שלבים רצים במקביל ואילו רק על הענף הראשי, איך מוסיפים משימה חדשה.
- תרשים תלויות — גרף של חבילות ויישומים: מה תלוי במה, אילו משימות מושפעות מתיקון של קובץ אחד, היכן הגבול בין ספריות משותפות למוצרים.
- כללים לבדיקות חובה — מה חוסם מיזוג, מה פועל כאזהרה, באילו מסלולים זה מופעל, מי ובאילו תנאים יכול לעקוף את החסימה.
- מדיניות גישה לסודות — היכן נשמרים מפתחות, אילו משימות וענפים רואים אותם, מה סגור לבקשות מעותקים חיצוניים, איך מתבצעת רוטציה.
- נוהל שחרור — גרסאות של חבילות, סדר פרסום ארטיפקטים, רצף הפריסה וחזרה לשחרור קודם.
- תיעוד לצוות — מבנה המאגר, פעולות טיפוסיות (להוסיף חבילה, לעדכן ספרייה משותפת, להאיץ את הבנייה) וניתוח של שגיאות נפוצות.
את הסט מוסרים עם הסבר: מראים מה נמצא היכן ואיך לשנות זאת, כדי שהפייפליין לא יהפוך לקופסה שחורה שזמינה רק למחברי התצורה.
מקרה בוחן: קיצור זמן הבנייה במאגר גדול
מונורפו עם 42 חבילות וארבעה צוותי מוצר: כל תיקון במודול משותף הפעיל ריצה מלאה של CI/CD, שנמשכה 55 דקות. המפתחים הפסיקו לחכות לתוצאה ועברו למשימות אחרות, והתור של הריצות גדל מהר יותר מאשר נסגרו השינויים.
מה היה
הפייפליין בנה ובדק את כל החבילות בכל קומיט, מטמון הארטיפקטים לא עשה שימוש חוזר בין ריצות, וניתוח סטטי, בדיקת טיפוסים ובדיקות אינטגרציה רצו בשלב אחד. כשליש מהכשלים היו שגויים: בדיקות לא יציבות והבדלים בין סביבות — הפעלה מחדש «על מזל» הפכה להרגל, ושגיאות אמיתיות אבדו ברעש.
מה שינו
בנו גרף תלויות ועברנו ל-Turborepo: נבנות ונבדקות רק חבילות שנגעו בהן ומה שתלוי בהן. הוספנו מטמון מרוחק של בניות ותוצאות בדיקות, הפרדנו שלבים למהירים וכבדים, קיבענו סביבות, ובדיקות לא יציבות הועברו להסגר עם סימון אוטומטי של המשימה.
מה התוצאה
ריצה מלאה התקצרה מ-55 ל-14 דקות, ריצה טיפוסית על תיקון אחד — עד 3–4 דקות. שיעור הכשלים השגויים ירד מ-30% ל-4%: הבדיקה שוב הפכה לאות, ולא לעילה להפעלה מחדש. חזרה אחורה משחרור כושל אורכת כשלוש דקות במקום ארבעים דקות של פעולות ידניות — מחזירים את הבנייה הקודמת בפקודה אחת.
במה שונה CI/CD למונורפו מבנייה לפי חלקים?
בסט של מאגרים נפרדים יחידת השינוי היא מאגר, ולכן משימה שנוגעת בכמה חבילות מתפצלת לכמה סטים בלתי תלויים של שינויים. צריך לתאם אותם ידנית: סדר המיזוג, תאימות גרסאות, רגע השחרור. במונורפו יחידת השינוי היא כל הגרף.
ההבדל המרכזי הוא איך נבחר נפח הבנייה. פייפליינים נפרדים או בונים הכול ללא הבחנה, או לא רואים קשרים בין מאגרים ומפספסים את הנדרש. מונורפו בונה גרף תלויות של חבילות ומחשב את תת-הקבוצה שנגעו בה: המטמון נשען על התוכן של החבילה והתלויות שלה, ולכן נבנה מחדש רק מה שבאמת השתנה.
גרסה אחידה של ספריות משותפות מסירה סוג נפרד של כשלים. כשהחבילות נמצאות בנפרד, הספרייה המשותפת מתפצלת לגרסאות, ובסביבת הייצור חיות במקביל כמה גרסאות שלה — חוסר תאימות צף כבר במערכת הפעילה. במונורפו הספרייה אחת, והשינוי עובר בדיקות של כל הצרכנים לפני השחרור.
שחרור אטומי הוא תוצאה של גרף אחיד. תיקון בממשק ציבורי וכל הצרכנים שלו יוצאים בסט אחד, בלי חלון של חוסר סנכרון ביניהם. חזרה אחורה מחזירה מצב עקבי בשלמותו, ולא חצי מערכת.
המחיר הוא משמעת פייפליין: פיצול משימות לפי חבילות, בידוד מטמון, הרשאות גישה ברמת חבילות, גרסאות של שחרורים. התצורה מורכבת יותר מסט של פייפליינים נפרדים, אבל דווקא היא נותנת זמן בדיקה צפוי ושחזוריות של התוצאה.
ספקות מעשיים: חזרות אחורה, מטמון, בידוד סביבות
הספקות סביב פייפליין במונורפו הם בדרך כלל אותם ספקות: קומיט אחד נוגע בכמה חבילות בבת אחת, המטמון מאיץ את הבנייה אבל לפעמים מחזיר תוצאה מיושנת, והסביבות חולקות מאגר אחד. בהמשך — תשובות קצרות למה ששואלים הכי הרבה לפני שמתחילים.
איך מחזירים אחורה שחרור כושל?
כל שחרור הוא ארטיפקט בלתי ניתן לשינוי עם תגית גרסה. חזרה אחורה היא החלפת מצביע לארטיפקט הקודם: אין צורך בבנייה מחדש, המצב חוזר תוך דקות. מיגרציות סכימה אנחנו עושים תואמות לאחור, כדי שהקוד של הגרסה הקודמת יעבוד עם בסיס הנתונים הנוכחי.
מה לעשות אם מטמון הבנייה מחזיר תוצאה שגויה?
מפתח המטמון מחושב מתוכן קבצי הקלט, מהתצורה ומגרסאות התלויות — כשאחד מהם משתנה, הרשומה מתבטלת מעצמה. כשחושדים במטמון מורעל, מאפסים אותו לפי ענף מסוים, ולא גלובלית: שאר הבניות לא מאבדות את ההאצה שנצברה.
איך מפרידים בין סביבות?
אותו ארטיפקט מקודם בין סביבות בלי בנייה מחדש — משתנים רק הערכים של משתנים וסודות. הבנייה בסביבת הבדיקות ובסביבת הייצור זהות, ולכן פערים לא צצים ברגע השחרור.
למי יש הרשאות גישה לפייפליין?
גישה מחלקים לפי תפקידים: מפתח מריץ בדיקות בענף שלו, את השחרור מוביל רק ענף מוגן עם אישור חובה. סודות של סביבת הייצור אינם זמינים למשימות מענפים של משתמשים.
למה הבדיקות לפני מיזוג נמשכות כל כך הרבה זמן?
הסט המחייב בונה ומריץ בדיקות רק על חבילות שנגעו בהן לפי גרף התלויות — זה דקות, לא שעות. ריצה מלאה עוברת לתזמון לילי ולא חוסמת את העבודה על המשימה הבאה.
נדון במשימה ונחזור עם תוכנית יישום
כדי לחזור עם תוכנית יישום, ולא עם הרהורים כלליים, אנחנו צריכים מינימום של נתוני קלט מצדכם. אין צורך להכין דבר מראש — מספיק מה שכבר קיים במאגר ובמערכת מעקב המשימות.
- מבנה המאגר: היכן נמצאות החבילות והיישומים, איך קשורות התלויות ביניהם;
- זמן הבנייה והבדיקות הנוכחי — מתוך יומני בנייה, גם אם הם מופעלים ידנית;
- צווארי בקבוק בשחרור: אילו שלבים ממתינים הכי הרבה וכמה פעולות ידניות יש לכל שחרור;
- כללי הסתעפות ורשימת סביבות, לאן השינוי הולך אחרי מיזוג;
- גישת קריאה למאגר, למערכת הבנייה ולמאגר האימג'ים — לצורך מדידות.
לפי הנתונים האלה אנחנו משחזרים את תמונת הבנייה ובודקים אילו משימות נבנות מחדש לשווא, היכן שרשרת הבדיקות מתבצעת באופן סדרתי למרות שיכולה לרוץ במקביל, ובאיזה שלב השחרור מאבד את מירב הזמן.
- תרשים של גרף התלויות עם סימון אילו שלבים עוברים במקביל;
- תוכנית יישום: מטמון בנייה, בדיקות אינקרמנטליות, הרצת משימות מרוחקת, שחרור;
- הערכת לוחות זמנים לכל שלב והסדר של הפעלה בטוחה שלהם;
- רשימת מקומות שבהם צריך לתקן תצורות של חבילות, ואיפה — הסכמות בתוך הצוות;
- מדדי אימות של התוצאה: זמן בנייה, שיעור מטמון בשימוש חוזר, זמן עד שחרור.
תארו את המשימה — אילו יישומים יש במונורפו ומה כרגע מונע לשחרר לעתים קרובות יותר. נחזור עם הערכת לוחות זמנים ותוכנית שאפשר להפעיל בשלבים.







