בפוסט הזה אני רוצה לחזור ולדבר על הציפיות הסבירות מ CD, על המשמעות, המעבר, וכו׳…
הפשט
בדומיין שאנו מדברים עליו יש 3 פרקטיקות דומיננטיות, שנהוג לפרש אותן בערך כך:
- Continuous Integration (בקיצור CI) – יש לנו שרת Build עם בדיקות אוטומטיות. כל כמה זמן (לילה?) – כל הבדיקות רצות ואנו מגלים אם יש בעיות בקוד – ואז מתקנים.
- Continuous Delivery (בקיצור CD) – יש לנו שרת Build אוטומטי, שגם אורז את הקוד ל Delivery. למשל: בונה את ה ISO (אם אנו מפיצים את המערכת על DVD – פחחח) או Docker Image – שניתן להטמיע בפרודקשיין (SaaS או On-Premises).
- Continuous Deployment (בקיצור גם CD, לצורך הפוסט אשתמש בקיצור CDD) – כמו Continuous Delivery, אבל ההחלטה לשלוח ל Production היא אוטומטית. כל קוד שנכנס למערכת – מגיע ל Production. לכאורה, תוספת קטנה לתהליך.
![]() |
נכון, אך פשטני משהו… מקור: notafactoryanymore.com |
מוטיבציה – אז למה לנו CD עכשיו…?
CD אמור לשפר כמה מדדים במערכת, הנה העיקריים:
- צמצום אי-ודאות – היכולת לשחרר קוד מהר יותר, מספקת לנו פידבק מהיר ותדיר יותר מהשטח. ״לפגוע בקרקע בתדירות גבוהה יותר״. (רלוונטי בעיקר ל Continuous Deployment)
- פישוט תהליכי ה Integration / Deploy – ארגונים רבים נאבקים לסיים גרסאות בזמן, ובאיכות טובה. CD היא דרך לשפר את התהליכים, בכמה צורות.
- יציבות, או Uptime של המערכת בפרודקשיין.
- חוסר ודאות מה הלקוחות צריכים –לפעמים הם בעצמם לא יודעים, ופשוט יש לראות כיצד הם משתמשים במוצר.
- חוסר ודאות לגבי התוצאות של פעולות שנעשות – האם המעבר ל NoSQL DB יספק את ה Scalability הצפוי. האם ה Design החדש של מודול Y יעמוד יפה בשטף הדרישות העתידיות?
- חוסר ודאות לגבי הבנת תוכנית הפעולה והתיאום בין אנשינו – כאשר האנשים שעובדים איתנו לא מבינים את אותה התוכנית – הם עלולים למשוך לכיוונים מנוגדים.
הפיצ’ר של אמזון של “אנשים שקנו את X קנו גם את Y”, נדחה ע”י אנשי המוצר כ”מטופש” – ובארגון אחר היה נקבר לעד.
בתחקור של גרסאות שהתעכבו או יצאו באיכות לא-מספקת?
במינוי ״אחראים״ ושינוי מנגנונים – על מנת ש ״זאת תהיה הפעם האחרונה שזה קורה״?
– אם אתם ראשי צוותים או מנהלים בכירים יותר, אתם בוודאי חשופים למאמצים הללו יותר.
ככל שהמערכת גדולה יותר וסבוכה יותר – כך קשה יותר להגיע לתהליך מוצלח ו”חלק”.
תהליכי CD עוזרים לשקף את קצב הפיתוח והבעיות בצורה טובה יותר: במהלך כל יום בספרינט יודעים מה הבעיות שצצו – וניתן לפתור אותן מייד, ולהתאים את התכנון בהתאם. כך ניתן לכוונן את סוף הגרסה עם כמות הקוד האמיתית שניתן להכניס באיכות טובה.
אין כאן קסם:
בתהליכי Integration/Deploy תקופתיים (נאמר: פעם בחודש) – משקיעים המון.
וגם בתהליכי CD – משקיעים המון.
התמורה היא שב CD הסיכויים להגיע לתהליך מוצלח – הם טובים יותר. במיוחד כאשר המערכת שלנו מחולקת למודולים נפרדים (למשל: microservices) ואז ניתן לייצר pipeline נפרד ומותאם לכל חלק במערכת (sub-system).
![]() |
מקור: http://www.mindtheproduct.com |
יציבות
זה לכאורה פרדוקס: שינוי בפרודקשיין הוא סיכון – והנה אנחנו הולכים לעשות הרבה יותר כאלה. במקום שינוי בחודש, אולי כמה שינויים כל יום!
מצד שני, כשהשינויים הם מאוד קטנים – הסיכון מאוד קטן, יכולת האיתור של תקלות משתפר פלאים, וכמו שאומרים: Practice Makes Perfect. הרבה אימון בתהליך מאפשר להשתפר בצורה מהירה יותר.
בארגונים ללא CD, מדובר בד”כ על כמה ישיבות, עבודה ידנית של ביצוע רגרסיות ומעבר על התוכן, ואף כמה פעולות ידניות של איש Operations שמלווה את ה deploy. כמה שעות עבודה, וכמה דקות של פחד (במקרה הטוב).
אם אתם רוצים לעשות deploy כל יום, זה נראה כחוסר-יעילות, ולכן ה”Best Practice” שהיה מקובל במשך שנים הוא להפחית את מספר ה releases, או לפחות למתן אותו – נאמר, פעם או פעמיים בחודש, ולא יותר.
לא שעות העבודה שמושקעות ב deployment הן המחסום העיקרי – אלא הפחד מתקלות: תקלת Deploy עלולה לגרום להפסדים כספיים (“פגיעה בביזנס”), לעלות עשרות שעות עבודה של מפתחים ,ולגרום לפגיעה במוניטין החברה.
הגישה של CD נקראת: Bring the Pain forward (כמו באג’ייל).
אם זה כואב, עשו את זה בתכיפות רבה יותר – עד שתשתפרו וזה כבר לא יכאב.
בפועל, באימוץ CD אתם הולכים “לשבור דברים” כ”כ הרבה פעמים – כך שתוך כדי אתם צפויים לפתח יכולות Recovery טובות במיוחד ולשפר מאוד את ה MTTR. כמובן שחשוב מאוד לשבור דברים קטנים, ולהיות עם יכולת recovery כמעט מיידית, למשל: לסגור את ה feature flag או לחזור ל deployment הקודם תוך שניות (ע”י blue/green deployment – פרטים בהמשך).
המערכת לא תהיה יציבה יותר כי היא “תשבר פחות”.
אם תציבו לארגון ה R&D מדד פנימי של “מינימום תקלות” – קרוב לוודאי שתהרגו את תהליך ה CD.
המדד צריך להיות: תוך כמה זמן אנו מתקלים תקלה, end-to-end: זיהוי התקלה עד אימות התיקון.
באופן זה, המערכת תהיה יציבה יותר כי (כמעט) כל שבירה תאותר ותתוקן לפני שמישהו בכלל ישים לב. בדרך תדעו היכן הרגישויות של המערכת – ותחזקו את האזורים הללו. תבנו מנגנוני הגנה מתאימים, ואז – תוכלו להתקדם בקצב גבוה מבעבר.
Continuous Integration (בקיצור: CI)
זהו הרעיון שקוד המערכת יהיה כל הזמן במצב תקין (“working state”).
בניגוד למיתוס מקובל, המשמעות איננה שעליכם להתקין ולהגדיר מערכת של Jenkins או Cruise Control.
זכרו: הכלי – הוא החלק השולי. התהליך – הוא העיקר.
העיקרון הוא שאינטגרציה של קוד (“merge”) הוא הכלי האולטימטיבי לזהות שבירות במערכת – ולכן עליכם לבצע אינטגרציה כל הזמן.
כפי שאמרו זאת מייסדי ה Extreme Programming (שהיו הראשונים לאמץ את הפרקטיקה בצורה רחבה):
“אם אינטגרציה של קוד היא טובה – עשו אינטגרציה של קוד כל הזמן.”
המדד המקובל ליישום CI הוא:
כל מפתח, מבצע בכל יום עבודה – לפחות פעם אחת merge של הקוד שלו ל branch המרכזי. (ועדיף: חמש פעמים)
(רמז: Jenkins לא גורם לזה לקרות.)
שימו לב: זה לא שכל מפתח מושך את ה branch המרכזי (נקרא לו לצורך הפוסט: master) ועושה merge לתוך ה feature branch. זה פחות מועיל / מלמד על שברים. העניין הוא לבצע merge לתוך ה master בכל יום.
Feature Branches? לא כ”כ מומלצים, אלא אם אתם מקפידים לבצע merge ל master.
זה מחייב את המפתחים לחשוב ביחידות קטנות, לפרק את הפיצ’ר לשלבים קטנים (שזה טוב – בפני עצמו), ולדאוג כל הזמן שהקוד הנכתב – לא שובר את המערכת.
מה קורה עם קוד שמשנה חלק גדול במערכת? איך אפשר לעשות merge כאשר הקוד לא “מוכן”? – פשוט הכניסו feature flag, ואל תדליקו אותו עד שהקוד מוכן. תחשבו איזה יופי יהיה להדליק את הפיצ’ר רק עבור המשתמש שלכם בפרודקשיין – ולבדוק איך הפיצ’ר עובד בלייב עם traffic/data אמיתי!
העיקרון החשוב השני של CI הוא:
כאשר ה Build נשבר – לתקן אותו זו עדיפות עליונה של הארגון. לפני כל דבר אחר.
יעד מקובל הוא תיקון תוך 10 דקות – לרוב ע”י rollback.
אפילו יותר טוב: בדקו את ה merge בצד, ורק לאחר שהצליח – בצעו את ה merge בפועל. השיטה הזו עובדת יותר טוב כאשר יש code bases קטנים (למשל: microservices) ואין race condition על merges.
הרעיון העיקרי לעקרון הזה הוא לדאוג לשיפור מתמיד. כל עוד הארגון מוכל לסבול כמה שעות של build שבור – לא יהיה ניתן יהיה לעמוד ביעד הראשון, ויש סיכוי טוב שהארגון לא יצליח להתמיד בתהליך ה CI.
כל הרעיונות של פרסום ברבים של שם האדם ששבר את ה build, או לבקש ממנו לחבוש כובע מצחיק – הם שגויים מהיסוד בעיני, ופשוט לא אפקטיביים. זו פשוט דרך להרוג את הרצון של אנשים לבצע merge תכוף.
![]() |
עם CI אולי תכניסו קצת פחות פיצ’רים – אבל תוכלו לסיים את הספרינט בזמן, ובאיכות שהחלטתם. |
בדיקות יחידה (Unit-Tests) או אינטגרציה (Integration-Tests) הגיעו לתהליך ה CI מאוחר יותר – והפכו לחזות עיקר התהליך. אין ספק: הן חשובות מאוד, ומועילות מאוד. מה היה קודם לכן? קומפליציה + בדיקת המערכת end-to-end (שאורכת זמן רב, ותופסת רק חלק מסוים מהבעיות).
האם בדיקות אוטומטיות טובות מספיקות, ויכולות לייתר את הצורך ב merges תכופים?
אם אתם רואים שאצלכם זה עובד – אדרבא.
בד”כ השבירות בקוד (גם אם הן נתפסות ע”י Unit tests) מגיעות אחרי merges של קוד – ואתם לא רוצים “לחטוף אותן” בסוף הספרינט – חשוב לבצע אינטגרציה כל הזמן.
בדיקות אוטומטיות שמגלות בעיות ביום האחרון של הספרינט, בלחץ – שקולות לרופא שנקרא לטפל בחולה, לאחר שזה כבר גוסס: הסיכוי להציל אותו הוא כבר קטן.
כל מיני פשרות של “רק את הפיצ’ר הזה נפתח בצד” – הן דרכים מצוינות לא להגיע ל CI עובד, שמצדיק את עצמו.
האם שווה לעשות CI ע”י merges תכופים, אך ללא בדיקות יחידה מקיפות?
– גם על זה לא הייתי ממליץ. זה כנראה עדיף במעט על בדיקות ללא merges תכופים – אך זה לא ייתן את האפקט המלא.
CI הוא האב הרוחני של CD, ולרוב מגיע איתו ביחד.
האם חובה ליישם CI לפני שמתחילים לעבוד על CD? – נדבר על זה בהמשך…
סיכום
בפוסט זה ניסיתי להסביר מה הציפיות הסבירות מ CI/CD/CDD – תהליך חשוב שלאט הולך ומוטמע באמת בעוד ועוד חברות. אימוץ תהליכים אלו הם לרוב מאמץ ארגוני אינטנסיבי של חודשים – אבל גם השיפור עשוי להיות משמעותי למדי.
בפוסט זה פירטתי קצת על CI. הפוסט הבא ארצה להמשיך ולפרט על CD ו CDD – בהתאמה, ולעלות כמה נקודות לגבי תהליך ההטעמה של תהליכים כאלו.
שיהיה בהצלחה!
מאמר מצויין, תודה רבה!
נהניתי לקרוא,תודה
מתי בתהליך הזה מתרחש ה-Code Review?
לפני push ל trunk / master branch.ב Github פשוט עושים Pull Request, ומי שעושה review ומאשר את הקוד פשוט עושה merge.
הזכרת הרבה merge ים תכופים ל branch הראשי. במקרה זה האם יש בכלל יתרון לפתח ב branch נפרד?
כעיקרון – לא, אך זה עניין של סגנון ויש כאלו שיעדיפו לפתוח branch אפילו לכמה שעות.כמו כן, ברור שיש הבדל בין תיאוריה למציאות. לא כולם קנאים לשיטה (יש כאלו שכן, אני יכול להעיד) – אבל יש כאלו שיחליטו ש CI עבורם זה נניח אינטגרציה פעם בשבוע לכל הפחות, ולא פעם ביום. במקרים כאלו יש יותר שימוש ב Branches.הייתי אפרופו בסדנא של Jez Humble בה הוא אמר שגיט הוא אכן רע ל CI, עם הקלות והעידוד שלו לייצר Brachnes.
בא לי להיות פרקליט השטן : וש פראדיגמה בבסיס ה CI שאין לה שום ביסוס והצדקה : אם שינוי(קטן) שהוכנס למערכת גורם לבעיה , פשוט תוציא אותו מהר כי השינוי האחרון הוא תמיד מקור הבעיה. ומה אם הוא מתנגש עם שינוי קטן אחר שהוכנס לפני N מחזורי CI כי השינוי הישן לא בוצע בצורה נכונה ? אם אין Branches נבטל כול מה שעבר CI עד עכשיו ? או שנעשה את השינוי האחרון בצורה \”עקומה\” כדי שיתאים לשגיאה שכבר השתרשה במערכת ? זה יוצר תחרות קטלנית בין מפתחים מי יצליח לדחוף את השינויים שלו הכי מהר ולקבוע עובדות בשטח. זה מגביר פרודוקטיביות ?
היי דני,ביקורת זה דבר טוב, והייתי שמח ליותר ממנה – במיוחד בנושא זה שאיננו פשוט :)להוציא את השינוי בד\”כ הכוונה לעשות rollback לגרסה מעט יותר ישנה – בשאיפה כמה שעות אחורה. גרסה שבה כל השינויים עבדו זה עם זה. יכול להיות ששינוי x ישן יותר מתנגש עם שינוי y שלנו. נחזור לגרסה ללא y – נתקן את הקוד ואז נוסיף את y' : קוד שעובד עם x – ואולי כלל שינויים ב x.ברגע השינויים קטנים, קל למצוא את מקור הבעיה – וזה מגביר פרודקטיביות.דווקא כאשר עושים merge לעבודה של שבוע+ – התנגשויות הרבה יותר קשות לחקירה. אני זוכר את עצמי כמפתח צעיר במירוץ (קולני, מודע, ומתובל בהומור) להכניס שינויים גדולים לפני חברים – כדי שהם יתמודדו עם ה merge.
איך בדיוק? חמישה code reviews לכל מפתח ביום?
שני, יש עוד סיבה שאפשר למנות. כשרוצים לבצע Pull Request לקוד. לא מכיר שיטה אחרת פרט לפתיחת branch צדדי ודחיפת הקוד שלו ל-master.
ניתן לעבוד ישירות על ה master. pull, ביצוע שינויים, commit, ופוש.לא חייבים לעבוד עם Pull Requests…
צודק, התכוונתי ל-Code Reviews.
איך יוצרים איתך קשר? Mig.workteam@gmail.com
נהנתי מאוד ולמדתי! תודה!
נהנתי מאד מהמאמרפשוט מעולה!תודה!!