יום שלישי, 18 בינואר 2022

431 Multirepo at outbrain


פודקאסט מספר 431 של רברס עם פלטפורמה. הוקלט ב-11 בינואר 2022 באולפנינו שבכרכור - שנה חדשה וטובה ועברנו את רברסים 2021 בהצלחה - היה מאוד מוצלח.
היום אנחנו מארחים את אבי מחברת Outbrain - ואנחנו הולכים לדבר על Multi-Repo vs. Mono-Repo וכל מה שביניהם.


(רן) אז אבי - ספר לנו קצת עליך?
  • (אבי) אני אבי ואני מהנדס תוכנה בצוות התשתיות ב-Outbrain, כבר קרוב ל-5.5 שנים ב-Outbrain
    • הצוות שלנו נקרא DevX, או Development Experience - כל מה שמשתמע מהדבר הזה.
  • באתי לספר על איך התחלנו ב-Outbrain, לפני קרוב ל-5.5 שנים - לתת איזושהי היסטוריה על ה-Transition, מאיפה התחלנו ואיפה אנחנו היום.
(אורי) Multi-Repo ו-Mono-Repo זה ויכוח עתיק יומין - בכל חברה שגדלה . . . 
  • (אבי) נכון . . . 
(רן) רגע, אני אעצור אותך לשנייה - הייתה פה איזו Easter Egg שהחבאת לנו . . . .מה זה DevX? מאיפה המצאתם את השם הזה? מה זה עושה?
  • (אבי) אז Development Experience זה שם שהגיע ממשהו שאורי הטמיע לנו . . . 
  • (רן) אתה, אורי?
  • (אבי) ויונתן . . . האמת שרצינו לעשות משהו, היה איזשהו Transition - הצוות הקודם היה Infra ורצינו לתת איזושהי חווייה הרבה יותר טובה לכל ה-Development שלנו.
    • זאת אומרת - אנחנו נותנים את התשתיות שבהן משתמשים הצוותים השונים ב-Outbrain, וחוץ מזה גם נותנים איזושהי תמיכה ואיזשהו מענה לצוותים האלה.
    • וגם חווייה טובה יותר לצוותי הפיתוח ביום-יום.
(רן) אז מה זה כולל - כלים שהמפתחים משתמשים בהם? . . . 
  • (אבי) דבר ראשון זה באמת התשתיות שבהן אנחנו משתמשים ב-Outbrain
    • זה הכלים והואטומציות שמסביבם
  • וגם כל תקלה שאנחנו יכולים, ברמת העיקרון, לטפל בה ולסייע לצוותים השונים.
  • (אורי) אפילו - כצוות - באחריותכם ה-Container שלנו - ה-Application Server שלנו - שהוא . . .
  • (אבי) כל דבר שאנחנו יכולים לתרום - לא משנה אם זה . . . כל בקשה - לא משנה אם זה “במסגרת האחריות” או לא, אם זה חלק מה-Scope - אנחנו ניתן מענה אם אנחנו נוכל.
(אורי) אני רק רוצה להגיד שהאמת שההקמה של הצוות הזה הייתה כחלק ממהלך יותר גדול - של מעבר לגילדות [367 Guilds at Outbrain]
  • במהלך המעבר הזה לגילדות, הבנו שהגילדה כנראה צריכה להחזיק - בין השאר - גם את “החווייה”: חוויית ה-Development של כל אחד מהמהנדסים.
  • אז אמרנו - אוקיי, בואו גם נקים איזשהו צוות שיחזיק את זה, לצד הגילדה.
  • אבל אתם עושים גם דברים שהם מעבר ל . . . “פיתוחים”, אני אגיד - ויותר קשורים לגילדה
    • למשל ה-Bootcamp זה משהו שאתם . . .
    • כל ה-Bootcamp, שזה משהו שאנשים עוברים דרכו ב-Onboarding שלהם, כמהנדסים - הצוות הזה גם דואג שה-Bootcamp הזה יתפתח . . .
  • (אבי) אז הרבה לא יודעים מה זה “Boot-camp” . . . 
  • (רן) שכיבות סמיכה ב-VI . . .
  • (אבי) כשאומרים “Bootcamp”, זה באמת משהו שהוא . . אנשים יכולים להבין משמעויות אחרות.
    • ברמת העקרון, כל מהנדס שמגיע לחברה עובר איזשהו תהליך הכשרה - שהוא יכיר את כל הסטנדרטיזציה של החברה, יכיר את כל הכלים שאנחנו משתמשים בהם
      • כדי שכשהוא יגיע לצוות עצמו, השאלות יהיו מאוד Straight-forward בשבילו.
  • (אורי) זה מאוד מקצר את הזמן של New Employee או New Engineer להיות פרודוקטיבי.
  • (אבי) בהחלט - אני רואה את זה ביום-יום . . .
(רן) וזה קורה אינטראקטיבית? ממש הדרכה, או שזה כזה “Online”?
  • (אבי) אז זה  . . . בוא ניגע בזה בדיוק, באיך שאני - בחווייה שלי בתור מפתח, כשאני הגעתי לפני 5.5 שנים - וגם ניגע באיך שבעצם התחלנו - 
    • אז כשאתה מגיע לOutbrain היום - כמו שהיה לפני 5.5 שנים, זה היה בעצם אותו התהליך רק שהיום הוא משודרג והוסיפו עוד כמה אלמנטים - אז אתה מגיע ל-Outbrain ואתה מתחיל את התהליך הזה, שהוא תהליך של שבועיים-שלושה, של הכשרה.
    • אתה עושה git-clone - באותה תקופה הייתי צריך לעשות git-clone ל-Repository שהוא Mono-repo - זה נקרא Trunk, אורי מכיר אותו . . . 
      • אז זה בעצם Repository שהכיל את כל ה-Code base של Outbrain
        • היום זה כבר microServices אבל אז זה היה Monolith אחד גדול.
        • וזה היה לוקח הרבה מאוד זמן . . . 
    • אז בשביל מישהו שמתחיל בתהליך הזה, כשאתה עושה git-clone והולך לשתות קפה - ובאותו יום שתיתי המון קפה . . .
      • (רן) בוא, תחתום על הטפסים של HR, תעשה git-clone ותחזור מחר . . .
      • (אבי) בדיוק, על הדברים האלה אני מדבר.
    • אז כן - יש את ההיכרות הזאת, מול הכלים השונים . . .
    • (רן) שאני לא אגיד מה היה המצב כשאני הייתי שם . . . אני חושב שעוד היינו ב-Subversion . . . 
    • (אורי) כן - אבל ה-Repo היה הרבה יותר קטן  . . .
    • (רן) ה-Repo היה (1) הרבה יותר קטן ו . . . . כן . . .אבל לעשות commit היה לוקח הרבה זמן, כי השרתים היו קצת רחוקים.
      • אבל מאז עברם ל-git, ועדיין - Repo אחד ב-git.
    • (אבי) נכון, ברמת כעיקרון כן - כמו שאמרתי, היה Mono-Repo אחד, לקח הרבה מאוד זמן למשוך את הקבצים, לקח המון זמן . . . 
      • זמן האינדוקס (Indexing) ב-IDE זה עוד קפה . . . היית יכול לפתוח את הפרויקט שלך ב-IDE, וזמן האינדוקס, שמכיל כל כך הרבה קבצים, היה לוקח המון זמן.
    • (רן) קבצי Java? או Scala? מה . . .
    • (אבי) אז אנחנו בשפות ה-JVM - אז כמובן שהזכרת פה Scala . . . 
    • זמן ה-CI היה גם ככה מאוד ארוך - ו-Scala תרם לזה שהוא יהיה עוד יותר ארוך . . . 
      • זה עוד קושי שנתקלנו בו בזמנו.
      • (רן) נסה Rust, זה יהיה אפילו יותר ארוך . . . 
      • (אבי) איך?
      • (רן) נסה Rust אם אתה מחפש דברים ארוכים . . . [דותן חש הפרעה בכוח].
      • (אבי) אז אנחנו מנסים לקצר, דווקא . . . 
      • (רן) לא, זו שפה טובה - רק הקומפילציה (Compiling) ארוכה.
    • (אבי) אז אנחנו היום ניגע בזה, אבל ברמת העיקרון - זמן של Scala מגדיל אולי פי 2 את זמן הקומפילציה ב-CI שלנו.
    • וחוץ מזה - Flaky tests ב-Mono-repo - ההשפעה שלהם יכולה להיות מאוד משמעותית על צוות Engineering
      • כי Flaky test יכול לגרום למהנדס, שרק הגיע, למעיין בהלה - “מה עשיתי? . . מה עשיתי לא בסדר?”
      • ולא עשית שום דבר - ה-Flaky tests, יש לו השפעה והשלכה
        • גם על זה שאתה צריך לחכות הרבה מאוד זמן 
        • וגם שאם ה-Build שלך נופל אחרי 15 דקות אז אתה צריך להריץ עוד פעם . . .
    • (רן) בוא נסביר - נגיד שעשית איזשהו שינוי ואז הרצת טסטים
      • עכשיו, אתה מריץ לא רק את הטסטים של של השינוי שאתה עשית אלא את של כל ה-Repo, או לפחות של חלק נכבד ממנו.
      • וטסטים - שלפעמים עוברים ולפעמים לא עוברים . . . .
      • (אבי) מסיבות מסויימות . . . יש הרה סיבות לדברים האלה-  גם אם זה תקשורת, גם אם זה פתאום איזשהו משהו אחר, איזשהו Res Condition בטסט או טסט שכתוב לא טוב . . .
    • (רן) עכשיו - נכון שזה Bad practice - לא  . . . Flaky test זה Bad Practice, אנחנו לא רוצים כאלה - אבל המציאות היא שלפעמים יש . . .
      • השאלה היא איזה נזק הם גורמים . . .
    • (אבי) בדיוק . . .  אז מה שזה גורם זו האטה - וזה משפיע ישירות על כל ה-Engineering, לא משנה איפה.
    • כשאתה יושב ב-Mono-Repo [אחלה שם לבית קפה] וצוות אחד מתוך 20 גורם לאיזשהו CI ליפול, זה אומר שהוא לא משפיע רק על הצוות שלו
      • הוא משפיע על כל ה-Engineering ועל ה-Velocity שלהם - וכולם מחכים עד שהבעיה תתוקן.
      • וזה יכול לקחת הרבה מאוד זמן . . . .
      • זה אומר שכל ה-Engineering מחכים עד שזה יתוקן, ואי אפשר לרלס (Release), גם אם יש Bug ב-Production כרגע.
      • (אורי) וככל שהארגון יותר גדול אז יש יותר צוותים . . . 
      • (אבי) בהחלט
  • (רן) אבל בוא, שנייה - ברמה הטכנית, עדיין אפשר שיהיה Repo אחד בודד, אבל להריץ איזשהו Subset של הטסטים שרלוונטיים אליך
    • זאת אומרת, אתה יכול לייצר עץ תלויות
    • אני זוכר שזה מה שהיינו עושים ב-Repos גדולים, כמו של Google, שבהם אם אתה משנה איזשהו רכיב אז אתה מריץ את הטסטים שאתה תלוי בהם ואת הטסטים שתלויים בך - אבל לא את כל העץ.
    • (אבי) אז נגעת דווקא בנקודה מאוד מאוד טובה, שאנחנו גם . . . Mono-Repo של Google ו-Facebook . . . היינו בנקודת זמן של להחליט האם אנחנו נשארים באותו Mono-Repo, והולכים לכיוון הזה.
    • אז באותה תקופה, כשדווקא חקרנו הרבה מאוד זמן, הלכתי - הלכנו, כצוות - לאיזשהו כנס שנקרא Scale@ 
      • ובדיוק היה שם בחור מ-Facebook שהציג את ה-Mono-Repo של Facebook
      • לבחור קוראים Durham - ותפסתי אותו לשיחה
      • תפסתי אותו לשיחה כי זה עניין אותי מאוד איך אנחנו פותרים את בעיית ה-Mono-Repo.
      • וכששאלתי אותו כמה זמן . . .כמה אנשים הם בצוות, Dedicated רק לפתור את בעיית ה-Mono-Repo, הוא אמר שהם צוות של 20 אנשים, שנתיים וחצי על Mono-Repo אחד - fsh להיכנס ל-Beta . . . 
      • אז זו איזושהי החלטה . . . .
    • (רן) זו באמת השקעה מאוד מאוד משמעותית - ונשאלת השאלה למה הם עושים את זה
      • יש פה כמה Benefits, אני בטוח שהם לא  עושים את זה סתם . . . 
    • אני רק רציתי להעיר, אני אומר שיש פה שני דברים
      • אחד זה איפה הקוד? האם הוא נמצא באותו ה-Repo?
      • ושתיים זה האם הכל תלוי בהכל? האם כשאתה עושה איזשהו שינוי, האם אתה צריך להריץ את כל הטסטים בעולם, או רק איזשהו Subset שלהם.
    • (אבי) אז נכון, זה באמת משהו שיכול להקל על המצב. 
      • אנחנו החלטנו ללכת על כיוונים אחרים - ועל זה נדבר היום.

(רן) אז זה היה המצב כשהגעת?
  • (אבי) נכון, ואני רוצה גם לגעת דווקא ביתרונות של Mono-Repo, כי יש לא רק חסרונות בדברים האלה . . .
    • אז דבר אחד זה שב-Mono-Repo הקוד זמין לכולם - אתה לא צריך לחפש בהרבה מאוד [מקומות] כמו ב-Multi, הכל זמין
    • כל התלויות - שזה נושא מאוד קרוב וכואב ב-Maven וב-Java - כל התלויות שלך גם יושבות במקום מרכזי אחד, שהוא מאוד מאוד חשוב
      • אז שדרוגים ודברים כאלה הם מאוד קלים - הכל נמצא במקום אחד, אז השדרוגים הם די פשוטים
    • (רן) אני חושב שיש כאן גם עניין תרבותי, זאת אומרת - זה “מסיר חסמים”
      • אם אתה משתמש בספרייה שצוות אחר כותב, אבל יש לך כבר את ה-Source Code - אז מאוד קל לתקן את זה ובאותו ה-Commit אולי גם לתקן כבר שני דברים בשתי ספריות שונות
      • אבל זה הכל אטומי וזה נגיש לך - זה לא שאתה צריך לפתוח Bug למישהו אחר שיתקן ולחכות בזמן שהוא יעשה את זה.
    • (אבי) כן, זה באמת . ..  כמו שאמרת - לבצע שינויים ו-Visibility של מה שקורה
      • לא צריך לחפש את הדברים ואת הכל במקומות שונים - הכל זמין לך במקום מרכזי אחד.
    • (רן) מצד שני - זה גדול . . .  
      • זה גדול על ה-IDE
      • זה גדול על git
      • כמו שאמרת - Flaky Tests וכו’. . . 
    • אז יש פה גם אתגרים טכנולוגיים וגם, כנראה, אתגרים תרבותיים של איך לייצר סביבה שהיא עדיין פרודוקטיבית למפתחים, עם כל האתגרים האלה.

(רן) אוקיי, אז מה הצעד הבא?
  • (אבי) אז הצעד הבא, הכי טריוויאלי, זה פשוט ללכת ל-Multi-Repo - לא?
  • אז זה בדיוק מה שעשינו - אמרנו “פשוט נלך ל-Multi-Repo ונפרק את ה-Monolith שלנו” - באותו תקופה זה היה Monolith - ל-microServices
    • וכל צוות שהוא יקבל Ownership על Repository מסוים - וה-Repository הזה יתחלק, בעצם, לשני מודולים - 
      • שזה בעצם ה-Service-ים שיש באותו הצוות
      • וכל ה-Libraries
    • כשאני אומר “Libraries” - יש שני סוגים של Libraries:
      • [אחד זה] Library שאתה לא מחצין לצוותים אחרים 
      • ו[שני] - Library שאתה כן מחצין, Library שאתה בעצם עושה לה Publishing ל-Artifactory ואתה רוצה ש . . .
        • קודם כל זה בשביל לחצין איזשהו API, איזשהו Client או דברים כאלו
        • או איזשהו משהו שהוא שהוא מאוד Common, כדי שאנשים אחרים יוכלו להשתמש בו גם.
(רן) אבל רגע - למה לשבור פר-צוות? אפשר, נגיד, לשבור פר-ספרייה, אפשר . . . באיזו רזולוציה אתם שוברים את זה?
  • (אבי) אנחנו שברנו את זה פר-Owner, פר-צוות
  • ה-Owner זה  בעצם צוות, או מספר צוותים, שהם בעצם התחלקו - Repository פר-צוות . . . זאת החלוקה שעשינו.
  • (אורי) אבל זה גם . . . יש “גרביטציה ל-Conway's Law”, זו כמו “חוק ניוטון כזה” [The Force] - תמיד מושך למבנה הארגוני, כי הצוות רוצה Ownership ורוצה עצמאות . . .
  • (רן) נכון . . . אבל זה גם מקבע את המבנה הארגוני הזה - זו לכאורה החלטה טכנית של “בואו נחלק לפי צוותים”, אבל אתה גם בא ואומר “אוקיי, מעכשיו פונקציונאליות שאולי, לוגית, נכון שתיהיה שם - היא עכשיו תיהיה פה, כי זה הצוות” . . .
  • (אבי) אז אני רוצה, בדיוק על הנקודות האלה . . . קודם כל, העובדה שעבדנו וחילקנו ל-microServices וחילקנו את התלויות - אז היה גם מאוד “קל” להעביר Libraries מצוותים, מ-Repository ל-Repository
    • זאת אומרת - אין Coupling בין הקוד, בדר”כ . . .
  • כשאנחנו מעבירים איזשהו Domain, אנחנו מעבירים אותו כמקשה, מ-Repository ל-Repository - ובדרך כלל זאת משימה די קלה.
    • אז אין פה “מקובעות” לקטע קוד - ואין בעיה להעביר.
  • (אורי) אבל אולי זה גם כי אנחנו מאוד “microService-d” והדברים חתוכים לחתיכות קטנות בסלט הזה - אז קל להעביר  . . .
  • (אבי) בדיוק . . . עשינו עבודה די טובה בזמן הזה, זאת אומרת - ההפרדה הזו הייתה מאוד טובה, כי . . .
(רן) . . . אבל תרשה לי רגע להיות סקפטי ולשחק את “פרקליט השטן”: אז הגיע מפתח חדש ועבר את ה-Bootcamp והכל, ועכשיו הוא צריך להוסיף פיצ’ר . . . 
  • עכשיו, הוא לא בדיוק יודע איפה “נכון” להוסיף אותו, אז הוא יוסיף אותו במקום שקל לו, במקום שיש לו הרשאה - ב-Repo של הצוות שלו.
  • ובסופו של דבר, אם אתה לא “עם שתי עיניים על הכביש”, אתה מגלה שפתאום יש בלגן - כי כל אחד יוסיף במקום שקל, ואתה יודע - 
    • לפעמים לא הבינו את המשמעות של ההחלטה, לפעמים עשו את זה בתמימות
    • ולפעמים אולי סתם - כי זה יותר קל.
איך אתה אחר כך מנהל את זה? אז ב-Mono-Repo זה יחסית קל - אבל ב-Multi-Repo, ששבור לפי צוותים? אז אתה אומר שטכנית זה אולי קל להעביר את הספרייה, אבל בסופו של דבר הדברים מתחילים להיות “ספגטי”, מתחילים להתערבב אחד בשני, וקשה מאוד להפריד את הדברים האלה . . . 
  • (אבי) אז זו באמת שאלה מאו טובה וזה באמת היה אחד הנושאים הקשים, זאת אומרת - הניהול עבר בעצם לצוותים
    • זה אחד הדברים, זאת אומרת - קוד שנוהל ע”י הצוות עצמו
  • וגם הנושא השני שזה בעצם כל נושא התלויות - כל ה-3rd party Dependencies - גם זה הוגדר ע”י הצוות, שזה גם נושא - שני - מאוד כואב.
  • אז ה-Visibility היחיד . . . בעצם, שלא היה Visibility, לא היה . . . 
    • באמת, כשקרה המעבר ל-Multi-Repo, אנחנו היינו די “עיוורים” זאת אומרת - לא ידענו מה מוגדר איפה, אילו קטעי קוד נכנסים ואיזה לא, וזה באמת נושא שמאוד מאוד כאב לנו.
(רן) כשאתה אומר “לנו”, אתה מתכוון “לצוות ה-DevX”?
  • (אבי) אני חושב שזה גם לכולם - Visibility, כשאני אומר “Visibility” - אם פעם אנשים היו מחפשים במקום מרכזי אחד איזשהו קטע קוד שהם היו רוצים לממש
    • אז הם היו או מוצאים, לשמחתם . . . בהרבה מקרים זה מה שקורה, זאת אומרת - מישהו כבר מימש את מה שהם רוצים.
    • או לממש בשביל אחרים - שכשאחרים יחפשו, הם ימצאו אותו . . .
(רן) זאת אומרת שאם אני רוצה פונקציה שעושה, Whatever, נגיד String parsing או Authentication או משהו כזה, ואני חושב שאיפשהו פעם ראיתי אותה ועכשיו אני לא מוצא - אז או שאני אהיה ממש חרוץ ואמשיך לחפש או שאני פשוט אכתוב עוד אחת כזאת, משלי.
אז אתה אומר שכשהיינו ב-Mono-Repo, כל מה שהיית צריך לעשות זה לחפש ב-IDE - והיית מוצא את זה.
  • (אבי) בדיוק . . .
(רן) אז איך זה נפתר ב-Multi?
  • (אבי) אז ב-Multi זה לא נפתר . . . באמת שהבעיה הזאת הייתה קיימת - וזו אחת הנקודות הכואבות שהיו לנו.
    • זאת אחת מהן . . .
  • והנושא ההשני זה בעצם ה-3rd party Dependencies . . . 
(רן) זה לא נפתר עד היום, או שזה לא נפתר אז? . . . כי היום יש כלים לזה - יש Sourcegraph, יש חיפושים מסוגים אחרים . . .
  • (אבי) נכון . . . אז באותה תקופה אנחנו עדיין רק חווינו את החווייה הזאת
  • וכן - דיברנו על החסרונות, שני דברים מאוד קשים - זה גם בעצם זה שכל צוות מנהל גרסאות משלו ומפבלש (Publish) גם Libraries משלו, ו . . .
(רן) יש לי עוד חסרון בשבילך, דרך אגב - אם אתה מחפש . . . . לדוגמא, דיברת בעיקר על תלויות של JVM וכו’, אבל יש טכנולוגיות שבהן ניהול התלויות לא כל כך טריוויאלי,
  • לדוגמא Protocol Buffers ו-gRPC - אין שם מנגנון טוב לניהול תלויות
  • ואם אתה, לצורך העניין, מייצר את הסכמה ב-Server של ה-Service ב-Repo אחד, אתה צריך שה-Client יהיה תלוי ב-Repo של ה-Server - וזה מייצר תלות מאוד לא בריאה.
  • זה מייצר מה שנקרא “Monolith מבוזר” - ואין בעצם דרך טובה לנהל תלויות ב-Protocol Buffers.
  • ואז, אני לא יודע אם אתם משתמשים, אבל כן . . . . 
אז אני יכול לספר על גישה אחרת לאיך לעשות את זה, אבל בוא תמשיך את הסיפור שלך - רק רציתי להוסיף אתגר קטן . . . 
(אורי) אני רק רוצה להוסיף שאני זוכר את השיקולים, באותה תקופה, ובגדול - הבנו של-Mono-Repo או ל-Multi-Repo, לכל אחד מהם יש חסרונות - ובטוח שנצטרך כלים כדי להתגבר על החסרונות האלה.
לכן ההחלטה היא פשוט ללכת למה שנוח - ולייצר את הכלים.

(רן) אוקיי - אז איך ממשיכים?
  • (אבי) ברמת העיקרון . . . דיברנו דווקא על חסרונות, אבל ברמת העיקרון זה גם הביא הרבה מאוד יתרונות
(רן) Not של כל מה שהיה קודם, לא? . . . כל Repo יותר קטן . . .
  • (אבי) כן . . . כמו שהזכרתי לפני כן, הדבר העיקרי זה בעצם הניהול של התלויות.
  • הייתה “הצפה” של תלויות בכל Repository, וכמו שהזכרתי - הניהול של ה-Libraries וה-Publishments זה על חשבון הצוות עצמו
  • זאת אומרת שמה שקורה זה ש-Service מסויים יכול היה להיות תלוי ב-Lib-A וב-Lib-B, ושתי התלויות, שתי ה-Libraries מביאות את אותו ה-Dependency, רק בגרסאות שונות.
    • מה יטען? יטען משהו אחד, ואנחנו מכירים את אותה הבעיה משפות ה-JVM - ה-ClassNotFound או MethodNotFound
    • אלו קשיים שחווינו ברמה היום-יומית - וזה קושי מאוד עיקרי
  • ומה שעשינו בנושא הזה זה שבעצם פיתחנו כלי שנקרא bumper
    • ומה שהוא נתן לנו לפחות זה איזשהו Visibility על כל נושא התלויות - בכל ה-Repositories שלנו.
    • בעצם הוא היה סורק את כל ה-Repositories, היה מאנדקס (Indexing) את כל התלויות שלנו - והיינו יודעים איפה כל דבר נמצא.
    • כמו כן, אם היינו רוצים לשדרג - אז ה-bumper היה נותן לנו מענה - והיינו עושים את זה Cross-Repositories, עם Pull-requests
    • האם זה עבד? בצורה חלקית . . .
(רן) אם הייתי מעדכן ספרייה - נגיד שמצאתי Bug ותיקנתי Bug ועכשיו אני רוצה שכל הלקוחות של אותה הספרייה יעדכנו את הגרסא שלהם - 
  • אז אתה אומר שיש, נגיד, 100 לקוחות - אז היה את הכלי הזה, bumper, שהיה הולך ומייצר 100 Pull-Requests ושולח אותם, שולח את זה ל-Owner-ים  . . . .
  • (אבי) כן, אז יש פה את העניין של הפקטור האנושי . . . .
  • למה אמרתי “חלקי”? - כי יש את הצוותים שפשוט היו מקבלים את השינוי, ויש את אלה [כן, אתה שקורא] שלא . . .
  • אז הפקטור האנושי שיחק כאן הרבה מאוד - ואנחנו, בתור צוות התשתיות שרוצים להפיץ איזושהי גירסא, גם היינו צריכים לעבור צוות-צוות.
    • היינו מצליחים לעשות את זה - אבל זה היה לוקח יותר זמן מהרגיל.

(רן) דרך אגב, בוא רגע נשחק ב”נדמה לי” - ואם זה היה Mono-Repo, אז מה? אז פשוט זה היה עושה Commit והם היו מקבלים את זה בעל-כורחם, נכון? גם אם הם היו מתנגדים לשינוי, לא הייתה להם דרך להתנגד לו באמת . . . .
דרך אגב - הסיבה לכך שהם לא קיבלו זה כי הם התנגדו, או סתם כי לא התפנו לזה? . . . .
  • (אבי) תשמע, הפצת גרסא זה לא תמיד דבר שעובר בצורה חלקה . . . 
    • זה יכול להיות “אוקיי, ה-CI שלך עבר - אבל ב-Run-Time זה לא”
    • וזה יכול להיות ש”ה-CI שלך נפל ואין לי עכשיו את הזמן הזה” - ופשוט ה-PR שלך עומד ושוכב שם לזמן בלתי . . . לתקופה ארוכה
      • עד שיבואו אליך ויגידו באמת “תעשה את זה” אתה לא תעשה.
  • אז  . . . .
(רן) ופיתחתם גם Deprecation Policy, או שזה פשוט ככה “התפייד” עד שה-Artifactory עבר איזשהו . . . .
  • (אבי) תראה, היינו יכולים למשוך את ה-PR-ים האלה . . . 
    • אם אנחנו רואים שה-PR-ים האלה כבר לא רצויים אז היינו פשוט מושכים
    • ובדרך כלל זה מה שהיה קורה.
(רן) מה הכוונה ב”מושכים”?
  • (אבי) זה אומר שאם ה-PR, לא יודע, אחרי שבועיים הוא כבר לא ממורג’ג’ (Merged) וכבר לא רלוונטי אז פשוט עושים או Delete או Decline ל-PR הזה . . . .
(רן) אוקיי . . . .
  • (אבי) אז אלו באמת היו הבעיות שחווינו, 
  • וכמו שאנחנו עושים בכל שנה, אנחנו מתייצבים למעיין Heads-up לשנה הנוכחית ודנים, בתור צוות התשתיות, על כל מיני נושאים כואבים
    • ובאמת באותה התקופה אז זה היה הנושא הכי, או הדי-כואב
    • זה שהקוד השתכפל זה נושא אחד - והוא, ברמת העיקרון, היה נושא פחות כואב.
    • אבל נושא התלויות היה נושא מאוד קשה לנו - בגלל ש-Lib-ים ישבו לא באותו מקום והתקמפלו (Compile) מול גרסאות 3rd-Party שונות, זה היה נושא שלוקח - לנו בתור צוות תשתיות וגם לצוותים - המון זמן מזמן העבודה שלנו.
  • אז החלטנו לשנות גישה - וברמת העיקרון זה כן להישאר במעיין Multi-Repo, אבל עכשיו כל הספריות שהן מפובלשות (Published) ישבו ביחד, ב-Mono-Repo אחד . . .
    • אבל כל ה-Service-ים יושבים בב-Repositories של הצוותים.
  • מה שזה גרם זה לכך שבעצם כל ה-Libraries שמחצינים אותן ל-Artifactory מתקמפלות מול אותה הגרסא.
(רן)  . . . ב-Repo אחד?
  • (אבי) ב-Repo  אחד .  . .
(רן) אבל פה - אתה לא חוזר לאותה הבעיה? זאת אומרת, ה-Repo הזה לא יכול להיות מאוד גדול, גם פה אתה מקבל את הכאבי ראש האלה . . . .
  • (אבי) אז אנחנו נדבר על הכלים שבנינו - בדיוק בשביל זה אנחנו הגענו.
  • אז קודם - ה-Mono-Repo הזה, כשאנחנו מדברים על Libraries, לא מדובר על . . . אנחנו לא מחצינים ביום… לא עובדים בכל יום על אותו ה-Mono-Repo
    • דבר ראשון - כבר חתכנו איזושהי חתיכה מה-Libraries האלה, והגענו לאותה נקודה שבה ה-Libraries שלנו יושבות ואם אנחנו רואים שמשהו לא ממומש אז זה יכול להיות ממומש באותו Mono-Repo . . . 
(רן) כן, זה נכון - אבל אתה קצת “דוחה את הקץ” . . . זאת אומרת, נכון - כאילו הכל בסדר והצלחת להשיל קצת  . . . אם מתייחסים למצב של לפני, כשהיה Mono-Repo אחד, אז בסדר - כל ה”עלים”, את כל ה-Service-ים של הקצה הורדת, אבל עדיין יש לך איזשהו “יצור” שהולך וגדל וגדל וגדל - ואלי עכשיו זה עוד בסדר, אבל בעוד שנתיים-שלוש הוא כבר יהיה הרבה פחות בסדר, ואז שוב אתה יכול לייצר מצב שבו עכשיו כשמפתח רוצה להכניס Feature חדש, והדבר הנכון זה להכניס את ה-Feature הזה כספרייה אבל לעבוד על ה-Mono-Repo הזה של הספרייה זה סיוט כי הוא גדול מדי - אז הוא יכניס את זה ל-Service במקום להכניס את זה לספרייה . . . ויבוא המפתח הבא - ושוב יכניס ב-Service שלו . . . 
(אורי) רן, אני חושב שבגדול - רוב הפונקציונאליות שאנחנו מייצרים היא ב”עלים”, אוקיי? ב-Multi-Repos  . . . את הדברים שהם יותר תשתיתיים אנחנו תמיד נוגעים בהם אחת-ל- . . . .
עכשיו, זה נכון שכשארגון גדל אז ה”אחת ל-” הזה גם גדל - אבל היחס, פחות או יותר, נשאר.
(רן) ואם זו ספרייה שיש לה מעט מאוד משתמשים - אחד, למשל - אז היא גם תיהיה שם?
  • (אבי) שוב, ברמת העיקרון, ההחלטה האם להעביר . . . בגלל שיש . . . בגלל שעוברים את תהליך ה-boot-camp וכן יש את כל הסטנדרטיזציה הזאת, אז בדרך כלל כשרואים שיש איזשהו עניין באיזושהי ספרייה, אז אנחנו רואים שהצוותים, לבד, יודעים לקחת את הספרייה הזו ולהעביר אותה ל-Mono-Repo הזה.
  • זאת אומרת שזה משהו שנראה מאוד טבעי - וזה גם איזושהי תרבות ארגונית שיצרנו בתוך Outbrain.
  • אז כן, אתה צודק - יכול להיות מצב כזה, אבל התרבות הארגונית הזאת שאנחנו יצרנו בעצם גורמת לאנשים כן לעבוד שם.
  • דבר שני שלא היה קיים זה בעצם גם הקוד התשתיתי, שפעם לא היה יושב באותו ה-Mono-Repo, עבר לשבת ב-Mono-Repo
    • מה שרק אומר לאנשים ש”אוקיי, יש פה גם את הקוד הזה, התשתיתי - בואו תתרמו גם שם”.
    • זה נותן המון, גם לחבר’ה, להיות Contributors, בתור User-ים, ל-Mono-Repo הזה.

(רן) אוקיי - ואיך מטפלים בעניין הטכני, שככל שה-Repo הזה גדל, אז . . . .
  • (אבי) אז אחד ה-Restriction-ים שעשינו זה שקוד Scala קודם כל לא נכנס . . .
    • זו בעצם בעיית הקומפילציה (Compiling), אוקיי?
    • אין קוד Scala - אנחנו  . . . 
(רן) רק Java?
(רן) אוקיי, אז Scala הופך למעשה ל”אזרח סוג ב’” בחברה? . . . 
  • (אבי) אנחנו רואים שהמון . . . יכול להיות - אבל אנחנו רואים גם, ברמת ניהול הגרסאות ב-Scala - היא הייתה מאוד קשה.
  • גם העניין - וזו חוות דעת שלי - שקשה מאוד לתפעל את השפה . . . .
    • זאת אומרת - אפשר לכתוב את אותו קטע קוד בשלושים צורות שונות 
    • והיא מאוד קשה לשדרוג - כל העניין של הגרסאות שאלה . . .
  • וראינו שזה נכון, בזמן הנתון הזה, זה גם נכון לנו לעשות Restriction על ה-Repository הזה של ה-Libraries.
(רן) אוקיי - אז אתה אומר Kotlin ו-Java - ולפחות מבחינת זמני קומפילציה (Compiling) הן הרבה יותר סבבה.
  • (אבי) נכון
(רן) ומבחינת הגודל? אתה אומר שזה עדיין מספיק קטן כדי שאפשר יהיה ל . . . 
  • (אבי) אנחנו, כרגע, לא חווים  איתן בעיות - ואנחנו גדלנו מאז.
  • מה שכן, אנחנו, ברמת העקרון, כמו שאמרתי, מרלסים (Release) ל-Artifactory - וזה משהו שרילסנו, זה היה נקרא, איזשהו Plug-in שנקרא Maven Release Plug-in, ומ-Maven 3.5 ראינו שיש מה שנקרא קונספט של CI Friendly
  • ה-Maven Release Plug-in היה מתערב בקוד, היה עושה Prepare ו-Release, היה עושה Commit-ים לקוד, לכמות גדולה מאוד של קבצים . . . 
  • ואמרנו “אוקיי, ב-3.5 אפשר לנהל את זה ע”י Property, Revision.
  • אז כתבנו ספרייה שנקראית ci-friendly-flatten-maven-plugin, שבעצם עוזרת לנו לתפעל את ה-Repository הזה
  • וזה תהליך Deployment פשוט יותר - 
    • הוא לא מצריך שום Commit-ים לקוד
    • הוא לא מצריך שתי קומפילציות (Compile) בגלל שיש שם שתי  . . . . ב-Maven Release Plug-in היו שני Step-ים
    • הוא לא מריץ את הטסטים פעמיים, הוא לא עושה את הדברים האלה.
  • הדבר היחיד שהוא עושה זה שהוא לוקח, מקמפל (Compile) - עושה Deployment עם הגרסא הרלוונטית.
  • זה חתך לנו את זמן ה-Release בחצי, אפילו יותר . . . 

(רן) אוקיי, אז אמרנו ככה: הספריות נמצאות ב-Mono-Repo משלהן, ה-Service-ים נמצאים ב-Mono-Repo משלהם . . . דרך אגב, על כמה Repo-ים אנחנו מדברים, בגדול?
  • (אבי) 80 . . .
(רן) אוקיי, ואם אתה רוצה לעשות Re-use - אז אתה מקווה שזה נמצא בספרייה ואם לא אז אתה אולי צריך לבקש ממישהו שיעביר את זה לספרייה . . . לצורך העניין, אם מימשתי איזושהי פונקציה בתוך Service וזה משהו שגם מישהו אחר רוצה, אז אני צריך להעביר את זה לספרייה . . . 
  • (אבי) בדיוק
(רו) אוקיי, ומבחינת ה-Discoverability, מבחינת החיפוש בקוד - אז יש, אני מניח, כלי חיפוש.
עדיין צריך להשתמש ב-bumper, כי כל פעם שאתה מעלה . . . 
  • (אבי) אז עוד תחכום שעשינו, בגלל אותה בעיה של ה-Dependencies - אנחנו לא רוצים לקחת את הבעיה ולמשוך אותה.
    • ידענו שיש לנו בעיית Dependencies, אז עשינו מעיין היררכיית POM-ing, נקרא לזה - איזשוהי היררכיה שה-Service-ים יוכלו לרשת ולקבל את כל התלויות האלה, שמתקמפלות עם ה-Libraries.
    • ובעצם זה מקום מרכזי ב-Mono-Repo שגם Service-ים יקבלו אותם.
    • זאת אומרת שכל תלות שהם רוצים להשתמש - הם כרגע לא הגדירו שום Version ואין שום ניהול גרסאות - אז יש יש מקום מרכזי אחד שהם בעצם יורשים, ב-Service-ים - ומקבלים את כל התלויות.
(רן) כן, נשמע לי מוכר - אני חושב שגם עשיתי כזה פעם . . . 
(אורי) בסוף עוד יסתבר שעשית את זה ב-Outbrain . . . 
(רן) אני חושב, זה מה שנראה לי אבל אני כבר לא זוכר . . . היה לי איזשהו קובץ Versions כזה . . .

אבל מה שרציתי שנדבר . . . עד עכשיו דיברנו על JVM - אבל יש עוד דברים ב-Outbrain - יש JavaScript, יש HTML, יש עוד דברים . . . איפה כל אלה נמצאים?
  • (אבי) אז אפרופו bumper - אז אנחנו משתמשים ב-Node, ולאחרונה אנחנו עושים גם הקפצה, ואנחנו משתמשים באותו מנגנון bumper, שמוכיח את עצמו מיום ליום.
(רן) התקנתם את Colors
(רן) Colors . . . לא כדאי, אל תתקין . . . .
(רן) כן, למי שלא היה ב-Twitter בשבועיים האחרונים, אז המפתח של Colors - נכנס בו כנראה השטן והוא החליט להכניס להכניס שם Loop אינסופי, מה שהפיל לא מעט אתרים ברחבי האינטרנט שעידכנו [לגרסא החדשה עם הפיצ’ר המגניב של לולאה אינסופית…].
אז מה עושים עם כל הדברים שהם לא JVM-יים?
  • (אבי) אז ברמת העיקרון, כמו שאמרנו - ב-Node אנחנו גם מקפיצים באותה מתודולוגיה את הגירסאות.
  • על זה אחראי גם הצוות שלנו - אבל אני פחות מעורה בכל מה . . . פחות קשור לשפות ה-JVM.

(רן) אוקיי, רוצה לדבר קצת על Protobuff ו-gRPC - אתם עושים עבודה משמעותית עם זה?
  • (אבי) יש לנו Protobuff, זאת אומרת - הכנסנו את זה לאחרונה . . . 
(רן) איפה נמצאות ההגדרות שלו? זה נמצא באותו Repo של ה-Libs?
  • (אבי) כמו שאמרתי, יש גם Centralized Dependencies Management באותו ה-Repo
    • אז אתה יכול גם להכניס כל מיני Plug-In-ים, כדי לעשות איזושהי סטנדרטיזציה מסביב לדבר הזה.
    • או טם יש איזשהו Plug-In מסויים שאתה משתמש בו Across כל ה-Repositories של ה-Services.
    • אז ברמת העיקרון, הוא נמצא במקום מרכזי אחד וכולם משתמשים באותו ה-Plug-In, באותה הגרסא - ומקבלים אותו מאיתנו.

(רן) והגענו לגיבור הערב! אז לא מזמן - בטח כולם זוכרים - היה פה איזשהו סיפור קטן עם Log4j . . . . זו ספריית Log-ים שמשתמשים בה בהרבה מאוד Code-bases שמבוסיים על JVM - ואני מניח שגם ב-Outbrain.
(אורי) נכון . . .
ולא מזמן התגלתה בה איזשהו “רגישות Security” חמורה, איך נאמר . . .  ובין-לילה, כולם היו צריכים לעשות עדכון גרסא ל-Log4j.
אז אני מנחש ש-Log4j נמצא פחות או יותר בכל מקום . . . .
(אורי) האמת שזה היה בין-כל-לילה, כי כל יום התגלה Vulnerability חדש שם והיה צריך לשדרג גרסאות . . . .
  • (אבי) אז כן, ברמת העיקרון אפשר להגיד “וואו, איך אנחנו הולכים לעשות את זה?” . . . .
  • אז בגלל עצם העבודה שכמו שאמרנו - יש לנו מקום מרכזי אחד, כשכולם משתמשים באותן התלויות, אנחנו פשוט יכולנו לגשת לאותו מקום מרכזי, להקפיץ את גרסת Log4j, לרלס (Release) את הגרסא - וברמת העיקרון, עם bumper, להקפיץ את כולם.
  • עכשיו, המנגנון הזה, שדיברנו - עם bumper - אנחנו גם יכולים למרג’ג’ (To Merge) את ה-PR-ים בעצמנו - וזה היה במקרה הזה מה שעשינו.
    • אנחנו לא מחכים - לא חיכינו, בעצם - לאנשים שיעשו Approve
    • פשוט לקחנו את תהליך, עשינו את ה-Bump והיינו כבר מאחורי זה אחרי משהו כמו 10 דקות.
    • ותהליך ה-Deployment קרה גם כחלק מהתהליך של ה-bumper - קרה לאחר מכן, לכל ה-Non-Production, רילסנו (Release) את הגרסאות.
      • ובעצם אמרנו לצוותים - “בואו, עכשיו קחו את השרביט, ותדפלטו לפרודקשן (Deploy to Production) ותוודאו שהכל בסדר.
    • אני מאמין שכל השדרוג הזה, בעקבות כל העניין של ה-Centralized Dependencies Management, הציל אותנו ממש.
    • אחרי שעה-שעה וחצי כבר היינו מדופלטים (Deployed) עם ה-Log4j . . . 
  • (רן) וחוזר חלילה, בלילה הבא . . .
  • (אבי) בדיוק . . . 
  • (רן) אבל זה כבר לא באשמתכם . . . 
  • (אבי) אנחנו לפחות הבנו עד כמה שזה היה פשוט . . . 
  • (אורי) זה היה לא כואב . . . 
  • (אבי) זה היה באמת . . . אם אנחנו היינו חוזרים אחורה, שתלויות מבוזרות - אני לא יודע איך היינו עושים את זה וכמה זמן זה היה לוקח לנו.
    • פה זה הציל אותנו, זאת אומרת - המקום המרכזי זה דבר מאוד מאוד חשוב.
    • היכולת שלנו להשפיע בצורה מהירה זה משהו שהוכיח את עצמו, עד היום.
  • (אני מקווה שלא תיהיה לנו את ה- Vulnerabilities בספריות הבאות . . . 

(רן) אז יש לי תחושה, אבי, שאתם גם מגייסים?
  • (אבי) נכון מאוד - אנחנו מגייסים, וזהו:  החווייה הזו, שדיברתי בהתחלה, היא כבר לא אותה חווייה - אפשר לקחת את כל היתרונות של ה-Mono-Repo ולעבוד בצורה של Multi-Repo, זה בדיוק התחשוה שאני חווה היום.
  • אז ברמת העיקרון . . . 
(רן) “בואו אלינו!”, זה מה שאתה אומר . . . . אנחנו ב-Outbrain.

תודה אבי! להתראות.

 האזנה נעימה ותודה רבה לעופר פורר על התמלול!

אין תגובות:

הוסף רשומת תגובה