לינטינג אוטומטי של קוד ב-CI/CD: ESLint, Pylint, golangci-lint

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

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

שאלות נפוצות

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

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

לינטינג אוטומטי בצינור: היכן האיכות נשברת

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

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

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

הסיבה אינה במשמעת, אלא בהגדרות. הלינטר (ESLint, Pylint או golangci-lint — לפי סטאק הפרויקט) רץ על כל העץ, על קוד מורשת תלויות כמה אלפי אזהרות, רמת ההקפדה מוגדרת כאזהרה במקום כשגיאה — ואת העשירית מתוך מאה אף אחד לא שם לב. נפרט כיצד זה נסגר: העברת הבדיקה לתחילת המעבר, רמה מחמירה לשינויים חדשים ומצב נפרד לקוד היסטורי.

מה נותן לינטינג אוטומטי: האפקט על הבנייה

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

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

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

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

פורמטים של בדיקת קוד: מקומית, בבנייה, בשרת

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

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

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

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

כיצד אנו בונים את הבדיקות: סדר העבודות

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

  1. ביקורת בסיס הקוד. סופרים נפח לפי שפות והפעלות לפי כל כלל של ESLint, Pylint ו-golangci-lint על הענף העדכני. בפלט — רשימת הפרות המוניות וקבצים שאנו מתקנים לפני הפעלת המצב המחמיר.

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

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

  4. הרצה ב-CI/CD. הלינטר בודק שורות שהשתנו, ולא את כל הריפוזיטורי: הבנייה לא מתארכת, אבל אי-התאמה חדשה לא עוברת. הרצה מקומית לפני שליחה נותנת אותה בדיקה בשניות.

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

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

מה הצוות מקבל לידיים לאחר הטמעת הבדיקות

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

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

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

מקרה בוחן: שער איכות אחיד במונורפוזיטורי

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

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

כיצד ארגנו שער אחיד

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

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

במה בדיקה בבנייה שונה מבדיקה בעורך

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

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

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

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

ספקות טכניים: שאלות על כללים ותמיכה

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

בפרויקט יש הרבה קוד מורשת — האם באמת נצטרך לתקן הכול בבת אחת?

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

האם לינטינג אוטומטי יאט את הבנייה?

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

מי יתחזק את סט הכללים לאחר מסירת הפרויקט?

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

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

נדבר על המשימה: מה צריך לדעת לפני ההתחלה

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

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

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