פיתוח תבניות GitLab CI מותאמות אישית לשימוש חוזר

צוותים גדלים, ותבניות בנייה מתפשטות בהעתק-הדבק לעשרות מאגרים. אנו מפתחים תבניות GitLab CI מותאמות אישית כפתרון מלא: שכבה אחת של תבניות משותפות מקצרת את זמן הכנת הבניות פי כמה ומסלקת פערים בין פרויקטים.

היכולות שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1359
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    776
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח לוגו חברת AIDER
    פיתוח לוגו חברת AIDER
    1022
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113

מדוע תבניות GitLab CI מועתקות בהעתקה-הדבקה בין מאגרים

העתקה-הדבקה מתחילה באופן לא מזיק: סכמת בנייה מפרויקט אחד מועברת לתצורה של מאגר שכן. בפרויקט אחד מוסיפים מטמון תלויות, באחר משנים שלב פרסום, ובשלישי מתקנים תנאי הפעלה של בדיקות. אחרי כמה חודשים זה כבר לא תבנית אחת, אלא עשרה קבצים דומים עם פרטים לא תואמים.

המחיר מתגלה לא מיד. כל עוד התיקונים ממוקדים, הכפילות של הגדרות בנייה אינה מורגשת, אבל השינוי הראשון — בדיקת אבטחה חדשה, החלפת registry של images, כללי הפעלה אחרים — הופך לסיור ידני בכל המאגרים.

משהו נשכח, במקום אחר הוחל חלקית, ופער בין הסביבות הופך לנורמה: אותו קוד נבנה בפרויקט אחד ונכשל באחר.

מנגנוני שימוש חוזר ב-GitLab — include, extends, !reference — כשלעצמם אינם פותרים את הבעיה. כל עוד לא הוגדרו בעל התבנית, סכמת גרסאות וכלל עדכון הפרויקטים, קובץ הדוגמה שוב יוצא כהעתק. אז התמיכה במספר רב של מאגרים נשענת על אנשים, ולא על תצורה.

בהמשך נסביר כיצד זה נסגר: מקור אחיד לסכמות בנייה, גרסאות במקום עותקים ונתיב עדכון צפוי לכל מאגר.

שכבה אחידה של תבניות בנייה: האפקט במספרים

המעבר לשכבה אחידה של תבניות נמדד לא בתחושה ש«נהיה נקי יותר», אלא במספרים מהיסטוריית סכמות הבנייה. להלן מה שאנחנו מתעדים לפני ואחרי הטמעת ספריית תבניות משותפת ב-GitLab: צילומי מדדים נלקחים על אותם פרויקטים, כדי שההשוואה תהיה הוגנת.

  • זמן בנייה. שירות טיפוסי נבנה תוך 4–6 דקות במקום 20–30: התבנית מושכת מטמון תלויות משותף ואינה מתקינה את הסביבה מחדש בכל שלב.
  • שיעור תיקונים ידניים. תיקונים בקבצי בנייה יורדים מעשרות בחודש ליחידות — שינוי מוכנס פעם אחת בתבנית, והוא מתפשט לכל הפרויקטים.
  • סוג כשל שנסתר. פער בגרסאות כלים ובפרמטרים בין מאגרים נעלם: הבנייה מפסיקה «לעבוד אצל מהנדס אחד וליפול אצל אחר».
  • זמן שחזור. החזרת התבנית לגרסה קודמת מחזירה בנייה עובדת תוך דקות, בלי תיקון ידני של עשרה קבצים ובלי לחפש מה בדיוק נשבר.
  • תחזוקת סכמות בנייה. מאגר חדש מתחבר לתבנית בשינוי אחד בקובץ ההגדרות — במקום להעתיק סכמה של אחר ולהתאים אותה לעצמו.
  • שיעור הבדיקות המכוסות. שלבים חובה — ניתוח סטטי, בדיקות, בדיקת תלויות — מגיעים מהתבנית ואינם יכולים להיות מושמטים בטעות בפרויקט נפרד.

סיכום: שכבת הבנייה מפסיקה להיות אוסף של פתרונות פרטיים והופכת לניתנת לניהול — משנים אותה במקום אחד, והאפקט נראה בכל הפרויקטים בבת אחת.

GitLab CI Templates: השוואת גישות לשימוש חוזר

ב-GitLab CI את השכבה המשותפת של תבניות בונים בכמה דרכים, והבחירה ביניהן נקבעת לפי שני מספרים: כמה מאגרים בתחזוקה וכמה יקר נכשל בנייה. בשני-שלושה פרויקטים זול יותר להשתמש בסכמות בנייה מקומיות. אחר כך תיקון של כלל אחד הופך ל-N קומיטים זהים, וגרסאות הכללים בפרויקטים מתפצלות.

אפשרות מתי מתאימה מגבלות
סכמות מקומיות בכל מאגר 1-3 פרויקטים, צוות אחד התיקון חוזר ידנית, הכללים מתפצלים
ספריית תבניות משותפת לפי קישור שירותים רבים מאותו סוג, בדיקות אחידות בלי גרסאות התיקון משנה את הבנייה לכולם בבת אחת
תבניות עם גרסאות לפי קישור ל-tag כמה צוותים, נדרשים תאימות ו-rollback משמעת releases ותמיכה בכמה גרסאות
היברידי: ליבה משותפת ודריסות מקומיות פרויקטים מגוונים עם שלבים משותפים דיבוג מורכב יותר: צריך לראות את התוצאה כולה

ההבדל בין ספרייה לבין תבניות עם גרסאות אינו קוסמטי. ספרייה בלי גרסאות הופכת לנקודת כשל: הקומיט הכושל הראשון עוצר בניות בכל הפרויקטים בבת אחת. תבנית עם קישור ל-tag נותנת אותו שימוש חוזר, אך משאירה לפרויקט את הזכות להתעדכן לפי לוח הזמנים שלו ולחזור ל-tag הקודם.

הקריטריון פשוט: האם מחזורי ה-release זהים והאם צוות אחד עובד על התבניות. אם כן — ספרייה משותפת תספיק; אם המחזורים שונים או שיש כמה קבוצות, נדרשת שכבת גרסאות מפורשת, אחרת כל עדכון הופך לתיאום עם כולם בבת אחת.

מביקורת מאגרים ועד מסירת הספרייה: שלבי העבודה

סדר העבודה בנוי כך שהפתרון יישען על נתוני המאגרים, ולא על הנחות. תחילה מתעדים את המצב הנוכחי, אחר כך מתכננים שכבה משותפת ובודקים אותה על קבוצת פרויקטים מוגבלת — ורק לאחר מכן ספריית GitLab CI Templates עוברת לכל הצוותים.

  1. ביקורת מאגרים. עוברים על כל הפרויקטים בארגון, מורידים תצורות, מסמנים כפילויות, שלבים ידניים ופערים בין צוותים. בפלט — מפה: היכן הלוגיקה חוזרת על עצמה והיכן היא סותרת את עצמה.
  2. ספירת מלאי של סכמות בנייה. מכנסים את מה שנמצא בטבלה: triggers, שלבים, מטמון, ארטיפקטים, כללי סביבות. רואים אילו בלוקים הופכים לתבנית משותפת ואילו נשארים פרויקטיים.
  3. תכנון שכבת התבניות. מחלקים את הספרייה לרמות: בסיסית, שפתית, יישומית. בנפרד מתעדים מה חייב להיות אחיד ומה הצוות רשאי לדרוס אצלו בלי תיאום.
  4. בנייה וגרסאות. כותבים תבניות ובודקים אותן לתאימות עם בניות שכבר הוגדרו. כל שינוי מקבל גרסה, ולכן עדכון הספרייה אינו שובר פרויקטים שעוד לא מוכנים למעבר.
  5. קבוצת פיילוט של פרויקטים. מחברים כמה מאגרים עם סטאק שונה ומשווים זמן בנייה, שיעור כשלים ומספר תיקונים ידניים לפני ואחרי. פערים מנתחים לפני מסירה לשאר הצוותים.
  6. מסירת הספרייה והדרכה. מפיקים תיעוד: כיצד לחבר, כיצד להרחיב, מה לעשות בעת rollback. עוברים עם הצוותים על סדר התיקונים, כדי ששינויים יעברו דרך התבנית ולא בהעתקה בין מאגרים.

לאחר המסירה הספרייה חיה בעצמה: פרויקט חדש מתחבר לשכבה המשותפת בצעד אחד, והכללים מתעדכנים במקום אחד. זו הנקודה שבה תחזוקת סכמות הבנייה מפסיקה להיות תלויה במהנדס מסוים.

מה נשאר אצלכם: ארטיפקטים, מדיניות, תיעוד

ההטמעה מסתיימת לא כשצינור הבנייה עבד בלי שגיאות, אלא כשהצוות משנה אותו בעצמו, בלעדינו. לכן בפלט — לא אוסף סקריפטים בהתכתבות, אלא מאגר תבניות GitLab CI עם גרסאות, תיאור, מדיניות ותקנון תיקונים. הכול נמצא בקונטור שלכם ובחשבונות שלכם, וההרשאות ניתנות לתפקידים רגילים. להלן מה בדיוק נמסר לידיים.

  • מאגר תבניות עם מספור גרסאות major: שירותים מתחברים לענף הרצוי, ועדכון אינו שובר בניות של אחרים.
  • תצורות שלבים: הכנת סביבה, בנייה, בדיקות סטטיות, בדיקות, פרסום ארטיפקטים ותמונות.
  • כללי ירושה: אילו פרמטרים הפרויקט דורס בעצמו, ואילו חייב לרשת מהתבנית המשותפת.
  • מדיניות גישה: תפקידים נפרדים לתיקון תבניות, לחיבור ולצפייה; הגנה על הענף הראשי ותיאום חובה לשינויים.
  • מפת תלויות: איזה שירות נשען על איזו גרסת תבנית ומה יישבר בעת תיקון הקובץ המשותף.
  • תיעוד לבנייה: משתנים חובה, דוגמאות חיבור, ניתוח שגיאות טיפוסיות והסיבות שלהן.
  • תקנון שינויים: כיצד להציע תיקון, מי מתאם, כיצד מוציאים גרסה חדשה וכיצד חוזרים לקודמת.
  • הוראות לניתוח בנייה שנכשלה ותיעוד של ניתוח סופי עם הצוות שלכם — ההקשר נשאר אצלכם, לא אצלנו.

מקרה בוחן: 40 מאגרים ושכבה אחת של תבניות בנייה

פרויקט — 40 מאגרים של צוות מוצר אחד, ובכל אחד היה קובץ בנייה משלו. סכמות הועתקו מהמאגר השכן: עד לשלב הניתוח נותרו בין העותקים פחות שורות משותפות מאשר פערים, ותיקון של שלב אחד חייב 40 שינויים נפרדים.

מה היה

אף אחד לא יכול היה לומר בוודאות במה בנייה של שירות אחד שונה מאחר. עדכון image או כללי caching הפך לפשיטה על כל המאגרים: חלק מהתיקונים נשכחו, חלק הוכנסו בדרכים שונות, והבנייה התנהגה באופן בלתי צפוי. שחזור בנייה שנכשלה ארך כארבע שעות — המהנדס קודם חיפש איזה מהעותקים נשבר.

מה שינו

הוצאנו שכבה משותפת של תבניות אל GitLab CI Templates: שלבים, כללי cache, פרסום ארטיפקטים ובדיקות חיים בסט תבניות אחד, ובמאגר נשאר קובץ קצר שמתחבר לסט הרצוי ודורס פרמטרים. כל שירות מתאר רק את מה שבאמת ייחודי לו.

מדד לפני אחרי
עותקים של סכמות בנייה 40 4
תיקון שלב משותף 40 מאגרים תבנית אחת
זמן בנייה ~18 דק׳ ~7 דק׳
שחזור בנייה ~4 שעות ~20 דק׳

כפילויות הסכמות הצטמצמו פי עשרה, וזה לא ניקוי חד-פעמי: תבנית חדשה מתחברת בשורה אחת, ולכן העותקים לא יתפשטו שוב. שירות חדש מקבל בנייה עובדת ביום הראשון במקום שבוע של העתקת קובץ של אחר.

במה נבדלות תבניות משותפות מסכמות לכל פרויקט?

ב-GitLab CI תבנית משותפת מתארת אינווריאנט — מה שזהה ברוב המאגרים: התקנת תלויות, הרצת בדיקות, בניית ארטיפקט, פרסום ל-registry. סכמת פרויקט מוסיפה את מה שתלוי במאגר: סט סביבות, ענפי הפעלה, מטריצת בנייה וכללי rollback. הגבול ביניהן עובר במקום שבו הכלל מפסיק לחזור על עצמו.

הקריטריון המעשי פשוט: אם כלל שונה בשני פרויקטים מתוך שלושה, מקומו בסכמת הפרויקט; אם הוא זהה בכל מקום, הוא עולה לתבנית משותפת. התבנית עצמה מקבלת פרמטרים — image, שלב, שם ארטיפקט מועברים מבחוץ — אחרת היא מהר הופכת לאוסף תנאים לכל מאגר.

סכמת הפרויקט נשארת שכבה דקה של כמה עשרות שורות ורק מתחברת לתבניות המשותפות. אז תיקון מדיניות בנייה נעשה במקום אחד, ולא בארבעים קבצים, ופרויקט לא סטנדרטי לא גורר אחריו את האחרים.

שאלות טכניות נפוצות על תבניות בנייה משותפות

רוב הספקות של מנהלים טכניים מצטמצמים לארבע שאלות: האם התבנית המשותפת תשבור בניות קיימות, כיצד להעביר תצורות קיימות, מי רשאי לשנות קוד משותף וכיצד לבצע rollback לשינוי שכבר התפשט לעשרות פרויקטים. עונים לגוף העניין.

תבנית היא קובץ תצורה רגיל של שרשרת בנייה, שמתחבר דרך קישור; היא מגדירה בסיס, והגדרות הפרויקט נשארות בעדיפות.

האם התבנית המשותפת תשבור את הבניות הנוכחיות שלנו?

התבנית מתחברת בקישור ל-tag מסוים ואינה כותבת מחדש את משימות הפרויקט: הירושה לוקחת את הבסיס, ותנאי ההפעלה, התלויות והמשתנים המקומיים נשארים בעדיפות. תאימות נבדקת בענף נפרד — תחילה הרצה על שניים-שלושה פרויקטי פיילוט, אחר כך פריסה על השאר.

כיצד להעביר תצורה קיימת לתבנית?

באופן אינקרמנטלי: תחילה מוציאים סקריפטי בנייה משותפים, אחר כך שלבים, cache וארטיפקטים — כל צעד בשינוי נפרד. התצורה הישנה ממשיכה לעבוד עד שהגרסה החדשה תאושר בסדרת הרצות, והמעבר נשאר הפיך בכל שלב.

מי יכול לשנות את התבנית המשותפת?

מאגר התבניות סגור: הזכות לשינוי שמורה למעגל מוגבל של מהנדסים, הענף מוגן, וקיימות חובות בדיקות ותיאום עם בעלי הקוד. פרויקטים מתחברים לתבנית לקריאה בלבד, ולכן תיקון באחד מהם אינו פוגע באחרים.

כיצד לבצע rollback לשינוי כושל?

הקישור מוצמד ל-tag, ולא לענף צף, ולכן rollback הוא החזרת ה-tag בפרויקט או הוצאת גרסה מתוקנת. אין צורך לתקן עשרות תצורות בו-זמנית ולכתוב מחדש את ההיסטוריה.

נדבר על המשימה: מה נדרש מכם ומה אנחנו עושים

כדי שההערכה תהיה מציאותית, ולא «פחות או יותר סדר גודל», אנחנו צריכים לראות את מצב המאגרים הנוכחי ולהבין כיצד בנויים תהליכי הבנייה והפריסה שלכם. תארו את המשימה — נחזור עם הרכב התבניות, תוכנית עבודה והערכת היקף.

מה עוזר בקלט:

  • רשימת פרויקטים וסוגי בנייה: אילו סטאקים בשימוש, כמה מאגרים, היכן הבנייה שונה באופן מהותי והיכן היא שונה רק בסט הפקודות.
  • קבצי תצורה נוכחיים ו-include מחוברים — מהם רואים כפילות של שלבים ובלוקים שאפשר לקפל לתבניות GitLab CI משותפות.
  • מריצי בנייה וסביבות: משותפים או עצמאיים, האם יש מגבלות רשת, cache, גישה למשאבים חיצוניים.
  • שלבים קריטיים לפני פריסה: בדיקות, ניתוח סטטי, בניית images, פרסום ל-registry — מה חייב לעבור ומה אופציונלי.
  • שיטת עבודה עם סודות: היכן מאוחסנים נתוני גישה, מי רשאי לשנות משתנים ברמת קבוצה ופרויקט נפרד.
  • דרישות תאימות: אילו ענפים וכללי merge נתמכים, האם נדרש סט תבניות נפרד לסוגי מוצרים שונים.

לאחר הדיון נחזור עם מפת תבניות לשימוש חוזר ואזורי אחריות בכל אחת, תוכנית להעברת פרויקטים בלי לעצור פריסות, סדר שלבים והערכת היקף. בהמשך — תיאום עדיפויות והטמעה, החל מהמאגרים שבהם הכפילות עולה הכי ביוקר.