כשאני מספר על תהליך CI\CD בעבודה שלי, יש לא מעט אנשים שחושבים שזה מדע בדיוני וחבל. כשאני כותב קוד למוצר שאני מפתח ב-OATH, אני לא מחכה ל-QA שיבדוק אותו. אני לא מחכה ל׳שחרור גרסה׳. אני מייד דוחף אותו לפרודקשן וכמוני כל מתכנת שעובד בחברה. איך אנחנו יכולים לדעת שאנחנו לא שוברים שום דבר ולא דופקים את הפרודקשן? במיוחד במוצר שכל השבתה שלו עולה עשרות אלפי דולרים לשעה במקרה הטוב? את זה אנחנו עושים באמצעות הליך שנקרא Continuous integration. הליך שמבסגרתו הקוד החדש עובר בדיקות רבות כדי לוודא שהוא מתאים לקוד הקיים והשילוב שלו לא ישבור כלום. מדובר בבדיקות אוטומטיות, בידקות סיבוכיות, בדיקות ביצועים ואינטגרציה. אבל הבסיס של הבסיס של הבסיס הוא בדיקת static code analysis. אם המוצר שלכם עובד בג׳אווהסקריפט, אז בטח אתם מכירים את eslint, המוצר המוצלח שמוודא סטנדרטים של קוד.
בפסקאות הבאות אני מסביר מעט על תהליך ה-build, אם אתם מכירים אותו (ואתם אמורים להכיר), דלגו הלאה עד הכותרת של "השיפור״.
הסברתי על eslint במאמר קודם, היישום שלו מאוד פשוט והוא עובד בכל pull request שאני מבצע. העבודה הנכונה מול גיט היא עבודה ב׳מוד׳ של קוד פתוח. אני יוצר בראנץ׳ חדש לפיצ׳ר או תיקון באג או כל תוספת לקוד קיים. כותב את הקוד ואז מייצר פול ריקווסט. כאשר אני מייצר פול ריקווסט, רץ תהליך בילד (למשל באמצעות TraviCI( שמריץ את הבדיקות האוטומטיות וכמובן גם את בדיקת הקוד הסטטית. במידה והבדיקה נכשלת, לא יוכל להתבצע פול ריקווסט. גם על זה כתבתי מאמר הסבר ואני מאמין שרוב החברות עובדות ככה.
אבל בילד זה לא מספיק. חשוב לתת גם חיווי מיידי למתכנת על חריגה מהסטנדרטים. למה? שלא יהיה מצב שהוא יטעה במשהו איזוטרי ויצטרך לחכות לבילד שיתן חיווי. נכון, ניתן להריץ את בדיקת הקוד הסטטית באופן לוקלי. אבל בינינו? מה שלא אוטומטי לא נעשה.
השלב הראשון הוא אינטגרציה עם ה-IDE, כלי העבודה של המתכנת. את זה קל לעשות כיוון שלכל IDE שמכבד את עצמו – מ Visual studio code ועד Intellij על שלל הגרסאות שלו, יש תוסף שמציג מייד שגיאות על המסך.
אבל גם זה לא מספיק. אני רוצה לבצע בדיקה אוטומטית עוד לפני הgit push. למה? שלא יהיה מצב שהמתכנת לא עשה משהו איזוטרי כמו לשים נקודה פסיק בסוף השורה ויצטרך לחכות לבילד כדי לקבל חיווי שגיאה. אני רוצה שבכל git push או git commit תתבצע בדיקה סטטית של קוד. איך עושים את זה? עם husky, גם על זה כתבתי לא מעט.
השיפור
אז כל המבוא הזה כדי לתאר תהליך פשוט שקורה בלא מעט חברות: הליך Continuous integration שמתחיל ב-IDE, ממשיך במחשב הלוקלי של המתכנת שבמסגרתו לפני כל git commit או git push יש בדיקה לוקלית של eslint ואחר כך – אל הבילד.
מה הבעיה עם זה? שאם יש לנו לא מעט קוד, המתכנת צריך לחכות עשרות שניות ולפעמים אפילו שתי דקות לפני commit או push. הפתרון? בואו ונבדוק במחשב המקומי, לפני כל commit אך ורק את הקבצים שהוספו ל-commit ולא את כל הפרויקט. איך עושים את זה? רון אפלבאום, מתכנת שעבד איתי בימי HP העליזים ועובד איתי כבר כשנה ב-OATH, סיפר לי:
eslint `git diff --name-only --staged`
או:
eslint $(git diff --name-only --staged)
זה בודק אך ורק את הקבצים שעדיין לא עברו קומיט ורץ במהירות הבזק. נפלא.
אם אתם עובדים עם husky, אז גם קל לדאוג להריץ את זה אוטומטית לפני כל commit, פשוט להכניס את ה-githook המתאים ל-package.json:
"scripts": { "precommit": "eslint `git diff --name-only --staged`" }
מה שיקרה הוא שתוך שניה מרגע ה-commit, תעשה בדיקת קוד סטטית על הקבצים שנכנסים ל-commit ועליהם בלבד. כיוון שרק הם נבדקים, כל הסיפור אורך שניות בודדות. במידה והכל תקין, ה-commit מתבצע. במידה ולא, הוא נופל ואין commit. נפלא, נכון?
אבל יש עוד! ניתן לבצע תיקון אוטומטי של שגיאות קלות: נקודה פסיק בסוף משפט, רווחים ואינדנטציה (מישהו אמר טאב מול רווח?) וכו׳ וכו׳ באמצעות fix–. אם עושים את זה לפני קומיט, מה שקורה הוא שאם המתכנת שוכח לעשות דברים פשוטים, התיקון יתבצע מיידית וייכנס ל-commit בלי שום מעורבות של המתכנת! כלומר אם המתכנת מתעלם או לא שם לב לשגיאות בסיסיות שה-IDE צורח עליהן, הוא יקבל תיקון אוטומטי עוד בשלב ה-commit ולא יצטרך להזיע כלל. ככה זה נראה בסוף ב-package.json:
"precommit": "eslint `git diff --name-only --staged` --fix"
זו אוטומציה מלאה שחוסכת הרבה זמן ומסייעת לכל מתכנת ליצור קוד איכותי יותר.
4 תגובות
נראה טוב!
האם זה יעבוד רק כשעושים את הcommit דרך הide או גם אם עובדים עם source tree או git extension לדוגמא?
אמור לעבוד בכל סביבה. אני עושה קומיטים דרך הקונסולה וזה עובד בלי בעיה 🙂
You should already add `grep .js$` so eslint will go only over js files.
see https://ronapelbaum.github.io/2017/11/30/pre-commit-eslint/
ממליץ להשתמש ב-https://github.com/okonet/lint-staged