מימוש CI עם GitHub actions\ Flow

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

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

מדובר במאמר מאוד בסיסי בפיתוח תוכנה שעלול לשעמם מתכנתים מנוסים (מצטער חברים 😔) – אך כזה שעלול להכניס להלם מתכנתים חדשים שלא מכירים את המושגים. כדאי מאוד לעבור ולהכיר את:
– מערכת גיט וגיטהאב (ואם אתם לא מכירים – תתחילו כאן!)
– בדיקת קוד סטטית (כאן יש הסבר על eslint בשפת ג'אווהסקריפט והסבר על phpcs בשפת PHP)
– להכיר, ולו הכרות ברמת שלום-שלום את ג'נקינס או את TravisCI.

הדוגמאות פה הם על מוצר Node.js אבל הן רלוונטיות לכל השפות ולכל הפלטפורמות.

מה זה CI

בגדול מדובר בראשי תבות של continuous integration. מה זה אומר בפועל? התהליך שהקוד שלי עובר מרגע הכתיבה ועד שהוא משולב במוצר. בפיתוח קלאסי (שלא לומר חאפרי) התהליך הזה מאוד קצר – אני כותב קוד -> מבצע את הריליס – כלומר מעלה אותו לגיט (או ישירות לשרת 😱) -> הכל עולה לאוויר. אבל מדובר כמובן בהליך מאוד מסוכן. עבודה בשיטה כזו תגרום לבאגים, בעיות אבטחה, תקלות רגרסיה (שבירה ותקלות במקום אחר במוצר) וחוסר יציבות כללי. מה שיגרום לדחיית מועד שחרור הגרסה ולהפוך לכל התהליך לכואב מאוד.

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

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

זה תהליך CI בסיסי שרץ גם במחשב של המפתח אבל גם בשרת אחר כדי לראות שהקוד עובר. לראות פה שהכנסנו הליכים שבודקים את הקוד שרצים בשרת אחר. אבל איפה הם רצים? השרת האחר יכול להיות ג'נקינס, או TravisCI או, ועל זה אנחנו הולכים לכתוב – ב-GitHub flow. גיטהאב הכניסו יכולת לבצע הליך CI לפרויקטים שלהם. היכולת הזו נקראת GitHub actions ובמסגרת ה-actions אפשר ליצור flow שבעצם הוא קובץ שמגדיר את התהליך.

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

npx eslint ./src

אם אני כותב ב-Node.js. או

phpcs ./src

אם אני כותב ב-PHP או כל פקודה אחרת בהתאם לשפה.

ברגע שיש לי פקודה אחת כזו שמצליחה כאשר הקוד תקין ונכשלת כאשר הוא לא תקין, אני יכול להטמיע הליך CI וב-GitHub flow זה ממש פשוט.

GitHub flow

אני אדגים עם הפרויקט הקטן שלי branch-name-lint שהוא מוצר שמאפשר בדיקה סטטית של שם branch בגיט. אפשר להכנס אל לשונית Actions בגיטהאב בפרויקט שלנו ולהתחיל משם.

בגדול אנו יוצרים תיקיה שנקראת github. (שימו לב לנקודה) בתיקיה הראשית של הפרויקט ושם ליצור עוד תיקיה בשם workflows ולשים בתוכה main.yaml. למי שלא יודע, yaml זה פורמט טקסטואלי קל לקריאה.

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

name: Branch Lint Name CI

on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - master

jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os:
          - ubuntu-latest
          - macos-latest
          - windows-latest
        node_version:
          - 10
          - 12
          - 14
        architecture:
          - x64
    name: Branch Lint Name ${{ matrix.node_version }} - ${{ matrix.architecture }} on ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v2
      - name: Setup node
        uses: actions/setup-node@v2
        with:
          node-version: ${{ matrix.node_version }}
          architecture: ${{ matrix.architecture }}
      - run: npm install
      - run: npm test

ראשית יש לנו את ה-name שזה השם של ה-gitflow כפי שהוא יופיע בלוגים ובממשק. שנית יש לנו את ה-on. מתי הוא יופעל? בחרתי שההליך יופעל בכל פעם שיש פול ריקווסט ובכל פעם שיש push. וזה בדיוק מה שיקרה. אי אפשר יהיה לבצע פול ריקווסט בלי שהקוד כולו עבר את הבדיקה, הקוד יעבוד גם בכל פוש, כך המפתח שרוצה להכניס קוד ידע עוד לפני הפול ריקווסט אם הקוד שלו עובר את הבדיקה.

השלב הבא הוא איפה להריץ את הבדיקה ואם יש צורך בעבודות הכנה. אני בחרתי להריץ את הבדיקה כאן על מכונות מסוג חלונות, לינוקס ומק עם Node.js מגרסה 10,12,14 – כלומר 9 בדיקות. כיוון שהמוצר שלי נועד לרוץ ב-CLI של מחשבים שונים. אם יש לכם מוצר שרץ רק על לינוקס למשל, אפשר לבעוט את שאר מערכות ההפעלה לג'הנם. בחרתי שמערכות ההפעלה יהיו על מחשבי x64 שזו ברירת המחדל. כדאי לשים לב שאני יוצר כאן שם ייחודי לכל step לפי מערכת ההפעלה. כך אם הבדיקה שלי תכשל ב-Node מגרסה מסוימת ובמערכת הפעלה מגרסה מסוימת אני אוכל לקבל חיווי כזה. את שמות הגרסאות ומערכות ההפעלה אני מקבל באמצעות שם משתנה ${{ matrix.node_version }} הוא של גרסת ה-Node.js.

השלב האחרון הוא של ה-Step. כאן אני מכניס את ההתקנה של המוצר (npm install) ו… סוף סוף – את פקודת ה-CI שלי. אם משהו ב-step ייכשל – ובמקרה הזה או ה-npm install או ה-npm test – הבילד ייפול והמפתח לא יכול למזג את הפול ריקווסט שלו אל הסביבה ויופיע חיווי של כשלון. אם הכל עובר – יהיה חיווי של מעבר.

אם יש נפילה (או הצלחה לא צפויה 😉) אפשר להכנס באמצעות Details ללוג ולראות מה קורה. ממש כאילו מדובר במחשב שלנו – להסתכל בפלט ולהבין מה התקלה.

כמובן שמאוד חשוב שה-yaml של ה-git flow יהיה תקין. אני מציע לכם להתקין תוסף שבודק YAML כשאתם יוצרים אותו בתיקית הגיט שלכם.

כמובן ש-eslint הוא רק השלב הראשון והבסיסי בהליך CI ואפשר לכתוב בדיקות אוטומטיות (כמו שעשיתי), לבדוק בדיקות ביצועים, סיבוכיות קוד, בדיקות אבטחה יותר מחוכמות וכו'. אבל גםן בפרויקטים רזים מאוד – כדאי מאוד ליצור הליך CI בסיסי שעובד ושאפשר לתלות עליו אחר כך דברים נוספים כשיהיה זמן.

גם בפרויקט האישי שלכם כדאי מאוד שיהיה את השלבים האלו והסבר עליהם. זה מראה על איכות ומראה על רצינות. ועם git flows בכלל זה קל. אגב, אפשר לקחת את זה גם לשלב ה-deployment. יש לי GitHub Flow שמבצע גם פאבליש למוצר שלי ב-npm.

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

בונוס – פרק בפודקאסט ״מפתחים חסרי תרבות״ על CI\CD שבו השתתפתי 🙂

פוסטים נוספים שכדאי לקרוא

תמונת תצוגה של מנעול על מחשב
פתרונות ומאמרים על פיתוח אינטרנט

הגנה מפני XSS עם Trusted Types

תכונה ב-CSP שמאפשרת מניעה כמעט הרמטית להתקפות XSS שכל מפתח ווב צריך להכיר וכדאי שיכיר.

גלילה לראש העמוד