Git Hooks: מדוע בדיקות קוד מפספסות פגמים
כללי הבדיקה כמעט תמיד מתוארים: יש הסכמה על סגנון, מערך בדיקות, ניתוח סטטי בצינור הבנייה הכללי. אבל למאגר עדיין נכנסות שגיאות שלא טופלו, סגנון שנוי במחלוקת ובדיקות שנופלות בשלב הבא. הסיבה אחת — הבדיקות נמצאות רחוק מדי מהרגע שבו הקוד נכתב.
תמונה אופיינית: הוק pre-commit לא מוגדר, pre-push שותק, והאות הראשון על בעיה מגיע מהבנייה הכללית עשרות דקות לאחר השליחה. עד אז המפתח עבר למשימה אחרת, ההקשר אבד, ובנייה שבורה חוסמת את כל הענף — לא רק את מחבר הקומיט האחרון.
סיבה שנייה — ההוקים חיים על המכונה של מי שהגדיר אותם פעם. שיבוט חדש לא מקבל אף סקריפט עד שמתקינים אותם ידנית, לכן «אצלי הכל עובר» ו«אצלך זה לא נבנה» מתקיימים בו-זמנית, ואיכות הקוד במאגר נשענת על משמעת, לא על אוטומציה.
Git מאפשר להחזיק git hooks ישירות במאגר ולחבר אותם דרך תצורה משותפת — אז הבדיקות לפני קומיט זהות אצל כל הצוות, כולל משתתפים חדשים. נפרט כיצד זה מוגדר ומה כדאי לבדוק אוטומטית, ומה להשאיר לסקירה.
מה תופסות הבדיקות בכל שלב בעבודה עם קוד
הקו הראשון — pre-commit: הוא פועל לפני שהעריכה הופכת לחלק מההיסטוריה, ועובד רק על קבצים שהשתנו, ולכן מסתיים בשניות. בשלב זה נפסל מה שלא דורש מחשבה: סמני קונפליקט, תוספות דיבוג, מפתחות וסיסמאות שנכנסו בטעות, סגנון לא עקבי וסדר ייבוא.
בדיקת סגנון קוד אוטומטית מסירה סוג שלם של מחלוקות: העיצוב מפסיק להיות נושא לדיון בסקירה, כי כלי מביא אותו לצורה אחידה, ולא הטעם של מהנדס מסוים.
הקו השני — pre-push, בדיקות בשלב הפיתוח לפני שליחת הענף. כאן מופעל מה שלוקח יותר זמן: בנייה, בדיקת טיפוסים, בדיקות מהירות, אימות סכמות נתונים ומיגרציות. הפגם נפסל בזמן שהמחבר עוד מחזיק בראש את הלוגיקה של השינויים שלו — התיקון לוקח דקות במקום ניתוח למחרת, כשההקשר כבר אבד.
דווקא הזזת הגילוי לתוך תהליך העבודה מאפשרת גילוי מוקדם של פגמים בלי עלויות נלוות של העברת משימה בין אנשים.
בדיקת השרת נשארת הקו האחרון ותופסת את מה שעקף את ההוקים המקומיים: עקיפה באמצעות דגלים, ענף מיושן, מיזוג בלי הרצות. כללי צוות אחידים עובדים כשהם מתוארים בתצורת המאגר ומיושמים באופן זהה אצל כולם, כולל משתתפים חדשים — אז הסקירה מתחילה בלוגיקה ובארכיטקטורה, לא בהזחות ובשגיאות כתיב. שיעור ההערות על זוטות בדיונים יורד באופן מורגש, ואותו זמן של הסוקר מופנה למה שבאמת דורש אדם.
עלות תיקון שגיאה גדלה באופן לא ליניארי ככל שמתרחקים מרגע התיקון: שניות בהרצה מקומית, כמה סבבי סקירה כשמגלים בענף המשותף, שחזור וניתוח השלכות — אם הפגם הגיע לפריסה. לכן כדאי לסדר את הבדיקות לפי חומרה עולה: מיידי — לפני קומיט, כבד — לפני שליחה, סט מלא — בשרת. לא מספר ההוקים עובד, אלא הכיסוי שלהם של הנתיבים שבהם פגמים באמת מופיעים.
אפשרויות הטמעת בדיקות: בצד הלקוח, בצד השרת, היברידיות
בדיקות קוד ממוקמות בשלוש נקודות: במכונת המפתח, בצד השרת של המאגר ובצינור הבנייה. כל אחת תופסת סוג שגיאות משלה ונתקלת בתקרה משלה — הבחירה תלויה במה שחשוב יותר: תגובה בשניות או כלל שאי אפשר לעקוף.
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| הוקים בצד הלקוח (pre-commit, pre-push) | נדרשת תגובה מהירה לעיצוב ולשגיאות גסות לפני שליחה | נעקפים בדגל דילוג על הוקים, תלויים בסביבה המקומית ובגרסאות של מנתחים |
| בדיקות בצד השרת (pre-receive, update) | נדרשים כללים שאי אפשר לכבות: פורמט הודעות קומיט, איסור עריכת ענפים מוגנים | פועלים כבר אחרי השליחה — המחבר רואה דחייה מאוחר, התיקון דורש קומיטים חדשים |
| בדיקות בצינור הבנייה | הרצה מלאה של בדיקות, מנתחי קוד ובנייה בסביבה נקייה | משוב מגיע אחרי דקות ומתחלק בתור המשימות עם שאר הבניות |
| סכמה היברידית של בדיקות | נדרשים בו-זמנית תגובה מהירה ומחסום שאי אפשר לעקוף | דורשת סנכרון תצורות וגרסאות של מנתחים בין השכבות |
בדיקות בצד השרת ב-GitLab מתחברות כסקריפטים בצד המאגר ופועלות לפני יישום השינויים, ולכן אינן תלויות בהגדרות המכונה ובגרסאות הכלים של המחבר.
בפועל, הסכמה העובדת היא היברידית. הוקים בצד הלקוח לוקחים את מה שצריך ליפול בשניות: עיצוב, מנתחי קוד מהירים, בדיקת הודעת קומיט. בצד השרת — את מה שאי אפשר לעקוף: ענפים מוגנים וכללי שמות. צינור הבנייה שומר לעצמו הרצה מלאה של בדיקות במקום שבו אין ארטיפקטים מקומיים ומטמון של המפתח.
תנאי לכך שההיבריד יעבוד — קובץ תצורה אחיד של מנתחים לכל שלוש השכבות. אחרת ההרצה המקומית עוברת, והשרתית נופלת על אותן שורות, והאמון בבדיקות נעלם מהר יותר משהן מחזירות את ההשקעה.
כיצד אנחנו מטמיעים Git Hooks: שלבי עבודה הנדסית
הוקים משתלבים בתהליך שכבר עובד, ולא מחליפים בדיקות בשרת. את המחסום שמים במקום שבו הכי זול לתקן שגיאה — במכונת המפתח, לפני שליחה לענף המשותף. לכן העבודה מתנהלת מביקורת של הכללים הקיימים ועד לתקנון שהצוות יתחזק בהמשך בעצמו.
- ביקורת כללי בדיקה. מנתחים מה כבר תופס קו הבנייה ואילו שגיאות מגיעות לבדיקה ידנית. לפי הרשימה הזו בוחרים בדיקות למחסום המקומי — אין טעם לשכפל הכל.
- בחירת נקודת בקרה. עיצוב, לינטר וחיפוש מפתחות בשינויים — ב-pre-commit; טיפוסים ובדיקות של מודולים שנגעו בהם — ב-pre-push, כדי שהקומיט לא יחכה.
- הגדרת הוקים. התצורה חיה במאגר ומותקנת בפקודה אחת: הכללים מגיעים יחד עם הקוד וזהים אצל כולם, כולל משתתפים חדשים.
- בדיקת הבדיקות. מריצים תרחישים אמיתיים: פורמט שבור, מפתח בקובץ שהשתנה, ענף עם כמה קומיטים, שינוי שם. בודקים גם מהירות — הוק איטי מתחילים לעקוף.
- סדר ההטמעה. קודם מצב אזהרות, אחר כך חסימה: מעבר חד נותן גל של עקיפות ומבטל את ערך הבדיקה.
- מסירת תקנונים. מוסרים תיעוד: איך להוסיף או לשנות כלל, מתי עקיפה מוצדקת, מה לעשות כשההוק נכשל במכונה של אחר.
תצורות הוקים, סכמות בדיקה ותקנונים לצוות
אנחנו מוסרים לא תיאור, אלא סט קבצים עובד במאגר. כל כלל בדיקה חי לצד הקוד, מנוהל בגרסאות יחד איתו ופועל באופן זהה במכונת המפתח ובסביבת הבנייה — הכללים לא מתפצלים בין מכונות ולא הולכים לאיבוד בעדכון.
- תצורות הוקים — כללים מוכנים ל-pre-commit ול-pre-push: עיצוב, ניתוח סטטי, בדיקת שם ענף והודעת קומיט, סט בדיקות מהיר.
- מתקין אחיד — פקודה אחת אחרי שיבוט מחברת את הבדיקות לכל אחד. אחרת חלק מהצוות עובד בלעדיהן ולומד על הכללים רק בזמן מיזוג.
- סכמת בדיקות — איזה הוק מפעיל מה, מה חוסם קומיט, מה נותן אזהרה, כמה זמן נמשך השלב. בדיקות ארוכות מעבירים לשרת, כדי שהקומיט יישאר מהיר.
- מדיניות גישה למאגר — מי יכול לשנות את תצורת ההוקים ואת רשימת החריגים, הגנה על הענף הראשי, שכפול בדיקות מפתח בצד השרת.
- הוראות לחריגים — איך לנסח דילוג לקובץ או לכלל: היכן נמצאת הרשימה, איזה נימוק נדרש, מי מאשר ומתי בודקים מחדש.
- תיעוד לצוות — מה לעשות כשבדיקה מופעלת, איך לתקן שגיאות אופייניות, איך לעדכן את סט הכללים.
- תקנון תחזוקה — תדירות עדכון הסט, האחראי, סדר הוספת בדיקות חדשות.
הקבלה מתבצעת על הענף שלכם: מציגים הפעלה של בדיקה, עקיפה לפי ההוראות ומעבר אחרי תיקון.
מקרה בוחן: כיצד בדיקות אוטומטיות צמצמו פגמים לפני שחרור
צוות מפוזר של ארבעה עשר מהנדסים בארבעה אזורי זמן ניהל מונוליט וכמה שירותים במאגר אחד על Git. ענפים חיו שניים-שלושה ימים, ותיקונים שנגעו במודול משותף הגיעו לסקירה אצל אדם שישן באותו רגע.
בדיקות תפסו פערים בסגנון ופליטות דיבוג שנשכחו כבר אחרי המיזוג — כלומר כשהבודק נגע בהם, ולא מחבר הקוד.
מה הגדרנו
הוק על קומיט הביא את העיצוב לצורה אחידה, הריץ לינטר על קבצים שהשתנו ועצר את הקומיט אם בדיף נמצאו מפתחות, טוקנים לגישה או קובצי סביבה. הוק על שליחה הריץ בדיקות של מודולים שנגעו בהם, בדק שהודעת הקומיט קשורה למשימה בטראקר ואסר דחיפה ישירה לענפים מוגנים. כל בדיקה עובדת רק על נתיבים שהשתנו — ההרצה מסתיימת בעשרות שניות ולא מאטה את העבודה.
מה השתנה
שיעור הפגמים שאותרו לפני שחרור עלה מ-62% ל-91%: פערים בלוגיקה נעשו גלויים במכונת המחבר, ולא בסביבת הבדיקות. זמן סקירת הקוד הממוצע ירד מיממה לחמש-שש שעות — מהוויכוחים בסקירה נעלמו מחלוקות על עיצוב, ועל תיקון אחד נשארות אחת-שתיים הערות ענייניות במקום שש. החזרות למחבר פחתו פי שלושה, כי חלקן נפסלו עוד לפני יצירת הענף.
עקיפת בדיקות השארנו כאפשרית — רק דרך דגל מפורש, וקומיטים כאלה נכנסים לדוח למנהל. תמורת תיקוני חירום הצוות שילם ביכולת חיזוי: הפרות נראות, ולא מתמוססות בהיסטוריה.
במה pre-commit שונה מ-pre-push ומה לבחור
אלה לא חלופות, אלא שתי נקודות בקרה שונות עם נפח נתונים שונה. pre-commit רואה רק קבצים שהוכנו לקומיט ולוקח שניות — שמים בו עיצוב, לינטר, חיפוש מפתחות וסיסמאות, איסור על קבצים בינאריים גדולים.
pre-push מסתכל על כל הקומיטים של הענף הנשלח, ולכן שם כבר מתאימים בדיקת טיפוסים, בדיקות של מודולים שנגעו בהם ובנייה.
המגבלה העיקרית — הסבלנות של המפתח. אם pre-commit רץ יותר מכמה שניות, מתחילים לעקוף אותו עם הדגל --no-verify, ונקודת הבקרה הופכת לפורמליות. pre-push פועל לעתים רחוקות יותר ומאפשר עשרות שניות: מחיר הטעות גבוה יותר, והתמונה המלאה של הענף אינה זמינה בשלב של קומיט בודד.
| פרמטר | pre-commit | pre-push |
|---|---|---|
| נקודת בקרה | לפני יצירת קומיט | לפני שליחת הענף |
| תחום הבדיקה | קבצים שהוכנו | כל הקומיטים בענף |
| מה מפעילים | עיצוב, לינטר, חיפוש סודות | טיפוסים, בדיקות, בנייה |
| מהירות | שניות | עשרות שניות |
| עומס על המפתח | מינימלי, לעתים קרובות מתקן קוד בעצמו | מורגש, אך נדיר |
הבחירה בדרך כלל אינה בינארית: pre-commit שומר על ניקיון ההיסטוריה ולא נותן לאשפה להצטבר, pre-push תופס את מה שדורש תמונה מלאה — אי-התאמת טיפוסים בין מודולים, נפילת בדיקות במפגש בין שינויים. הכלל פשוט: חומרת הבדיקה גדלה יחד עם רגע ההפעלה. כל מה שלוקח יותר מדי מועבר לשרת, שם עקיפה כבר בלתי אפשרית.
פרקטיקת ההגדרה — סט כללים משותף במאגר, כדי שבדיקות זהות יעבדו אצל כל הצוות בלי התקנה ידנית. אם צריך, ננתח את ענף הפיתוח שלכם ונציע פריסה של בדיקות לפי נקודות.
ספקות טכניים נפוצים לגבי הטמעת בדיקות
לפני הטמעת בדיקות מהנדסים מעלים אותן שאלות: האם ההוקים יאטו את העבודה, האם קל לעקוף אותם, איך זה מסתדר עם צינור הבנייה. להלן תשובות ישירות.
הבדיקות יאטו כל קומיט?
הבדיקה עוברת רק על קבצים שהשתנו מהאינדקס, ולא על כל המאגר, והתוצאות נשמרות במטמון בין הרצות. עיצוב ולינט על עשרות קבצים לוקחים שניות, ושלבים כבדים — בדיקות, בנייה — מועברים ל-pre-push או לצינור.
בכל זאת יעקפו את ההוק עם דגל?
כן, הוק מקומי נעקף באפשרות אחת, וזה נורמלי: הוא נחוץ למשוב מהיר, לא כאמצעי kontrola. את ההבטחה נותנת שכפול של אותם כללים כשלב חובה בבנייה, בתוספת הגנה על ענפים מפני push ישיר — אז עקיפת ההוק לא משפיעה על איכות הקוד בענף.
איך לא לשכפל כללים בצינור?
הכללים יושבים בתצורה אחת בתוך המאגר ומופעלים בשני פרופילים: מהיר מקומי ומלא בבנייה. סט הבדיקות משותף, השוני הוא בעומק ובנפח, ולכן הפער «עבר מקומית, נפל בבנייה» נעלם.
במאגר שלנו יש כמה שפות
שלבים משותפים — עיצוב, חיפוש סודות, בדיקת שמות — עובדים מעל כל הספריות. בדיקות לפי שפה מחוברות לפי מסכות נתיבים, והסביבות מבודדות באמצעות קונטיינרים, כדי שתלויות של שפות שונות לא יתנגשו.
מי מתחזק את הבדיקות בהמשך?
התצורה חיה במאגר ומשתנה דרך סקירה רגילה, כמו קוד. אנחנו מוסרים תקנון עדכון כללים וניתוח של שגיאות נפוצות, כדי שהצוות ירחיב בדיקות בעצמו, בלי תמיכה חיצונית.
נדון במשימה שלכם: מה להכין לשיחה
כדי שההערכה ותוכנית העבודה יישענו על עובדות ולא על הנחות, לשיחה הראשונה מספיקים כמה נתוני פתיחה. אין צורך להכין מראש חבילת מסמכים — חלק מהנתונים נאסוף יחד, אבל ככל שהתמונה ההתחלתית מדויקת יותר, כך קצר יותר הנתיב מדיון במשימה לתחילת העבודה.
- מאגרים: כמה יש, האם זה מונורפו או סט נפרד, אילו ענפים מוגנים מקומיטים ישירים.
- סטאק לפי שפות ומה כבר נבדק בשרת האינטגרציה הרציפה — לינטרים, עיצוב, ניתוח סטטי, בדיקות.
- כללי הסתעפות: סדר מיזוג, בדיקות חובה לפני מיזוג, למי יש זכות לעקוף אותן.
- אופן אספקת ההוקים למכונות המפתחים: ספרייה משותפת בתוך המאגר, סקריפט אתחול או מנהל חבילות.
- חלוקת בדיקות בין pre-commit ל-pre-push: רגישות לזמן המתנה של המפתח מול שלמות הכללים הנבדקים.
- מגבלות גישה ומדיניות אבטחה: האם נדרש מצב בלי תלויות חיצוניות, האם יש מאגרי חבילות סגורים.
- הרכב הצוות ותחומי אחריות: מי בעל תקני הקוד ומי יתחזק את הכללים לאחר המסירה.
בהמשך נתאם תצורת יעד, נפרוס אותה על מאגר פיילוט ונמדוד את זמן הבדיקות ואת שיעור הקומיטים הנחסמים. לאחר קבלת המספרים האלה, נקבע תוכנית עבודה לשאר המאגרים ואת סדר חיבור הצוות: ההתחלה לוקחת ימים, לא שבועות. תארו את המשימה ומה שיש בהישג יד, ונחזור עם הערכה ותוכנית.







