- CI/CD workflow מלא ועובד — lint, test, build, deploy — שרץ אוטומטית על כל PR ו-push
- Reusable workflow שניתן לשתף בין ריפוזיטורים בארגון
- ידע לנהל secrets ו-environments — staging ו-production עם protection rules
- טבלת החלטה: איזה runner לבחור, מתי reusable workflow ומתי composite action
- Matrix build עובד שבודק את הקוד על כמה מערכות הפעלה וגרסאות
- Caching מוגדר שחוסך 60-80% מזמן התקנה
- יכולת לחשב עלויות — כמה Actions minutes עולים ואיך לחסוך
- מילון מונחים — 15 מונחי מפתח שתשתמשו בהם כל יום
- תוכלו לבנות workflow שמריץ tests, build ו-deploy אוטומטית על כל PR
- תוכלו ליצור reusable workflow שניתן לשתף בין ריפוזיטורים
- תוכלו להגדיר secrets, environments ו-deployment protection rules
- תוכלו לחשב עלות Actions minutes ולייעל עם caching ו-matrix
- תוכלו לזהות טעויות נפוצות — secrets בקוד, חוסר caching, workflow כפול — ולתקן אותן
- פרקים קודמים: אין — זה הפרק הראשון בקורס
- כלים: חשבון GitHub (חינמי), ריפוזיטורי (אפילו ריק), טרמינל עובד (Terminal / Git Bash / WSL)
- תוכנה מותקנת: Node.js (גרסה 20 ומעלה) ו-npm — נשתמש בהם בתרגילים
- ידע: Git בסיסי (clone, commit, push, pull), מה זה PR ו-branch
לאורך הקורס כולו אנחנו בונים שליטה מלאה ב-GitHub. בפרק הזה אתם בונים את מערכת ה-CI/CD — השכבה שמריצה בדיקות ופריסה אוטומטית. בפרק הבא (GitHub CLI) תלמדו לנטר ולנהל את ה-workflows האלה מהטרמינל, בלי לפתוח את הדפדפן.
הפרויקט שנבנה: pipeline אוטומטי שבודק קוד, בונה אותו ופורס — כל זה קורה בענן של GitHub, בלי שום שרת שלכם.
- Workflow
- תהליך אוטומטי שמוגדר בקובץ YAML בתיקיית
.github/workflows/ - Job
- יחידת עבודה בתוך workflow שרצה על runner נפרד
- Step
- פעולה בודדת בתוך job — או action או פקודת shell
- Action
- יחידת קוד ניתנת לשימוש חוזר מה-marketplace או שבניתם בעצמכם
- Runner
- מכונה (וירטואלית או פיזית) שמריצה את ה-jobs
- Trigger / Event
- אירוע שגורם ל-workflow לרוץ — push, PR, schedule וכו'
- YAML
- פורמט טקסט מובנה לקבצי הגדרות — השפה של GitHub Actions
- CI/CD
- Continuous Integration / Continuous Deployment — בדיקות ופריסה אוטומטיים
- Matrix Build
- אסטרטגיה שמריצה job על מספר שילובים במקביל — OS, versions
- Cache
- שמירת תלויות בין הרצות כדי לחסוך זמן ודקות
- Artifact
- קובץ שנוצר ב-job אחד ואפשר להוריד אותו או להעביר ל-job אחר
- Secret
- ערך רגיש (מפתח API, סיסמה) שמאוחסן מוצפן ונגיש ב-workflow
- Environment
- הקשר פריסה עם כללי הגנה, secrets ייחודיים, ומגבלות branch
- Concurrency Group
- מנגנון שמבטיח שרק הרצה אחת של workflow פעילה בו-זמנית
- Reusable Workflow
- workflow שאפשר לקרוא לו מ-workflows אחרים עם
workflow_call
לפני שנצלול לתוכן, בואו נוודא שיש לכם פרויקט עובד. אם כבר יש לכם ריפוזיטורי עם קוד Node.js — מצוין, השתמשו בו. אם לא, צרו אחד עכשיו:
# צרו תיקייה חדשה ואתחלו פרויקט
mkdir my-actions-lab && cd my-actions-lab
git init
npm init -y
# הוסיפו script פשוט של test ו-lint
npm install --save-dev eslint
# צרו קובץ index.js בסיסי
echo 'console.log("Hello Actions!");' > index.js
# עדכנו package.json — הוסיפו scripts:
# "test": "node --test",
# "lint": "eslint .",
# "build": "echo 'build complete' && mkdir -p dist && cp index.js dist/"
# דחפו ל-GitHub
git add -A
git commit -m "Initial setup"
gh repo create my-actions-lab --public --source=. --push
חשוב: בדקו שיש לכם package.json עם scripts של test, lint ו-build. כל התרגילים בפרק מתבססים על זה. אם אתם עובדים עם Python או שפה אחרת, תוכלו להתאים — אבל הדוגמאות כתובות ל-Node.js.
1.1 מה זה GitHub Actions ולמה זה חשוב
GitHub Actions הוא מערכת אוטומציה מובנית ישירות ב-GitHub. כל פעולה שאתם עושים בריפוזיטורי — push, פתיחת PR, יצירת release, ואפילו תגובה על issue — יכולה להפעיל תהליך אוטומטי: בדיקות, build, פריסה, שליחת הודעות, ועוד. זו לא עוד מערכת CI/CD חיצונית שצריך לחבר — זה חלק אינטגרלי מ-GitHub עצמו.
נחשוב על דוגמה קונקרטית: אתם עובדים על פרויקט עם צוות. מישהו פותח Pull Request עם שינוי בקוד. מה קורה?
- GitHub Actions מריץ את הבדיקות אוטומטית — unit tests, linting, type checking
- אם הכל עובר — ה-PR מסומן בירוק ומוכן ל-review
- אחרי merge ל-main — Actions בונה את הפרויקט ופורס אותו לפרודקשן
- אם משהו נכשל — מייל או הודעת Slack נשלחים לצוות
כל זה קורה בלי שמישהו נוגע בכפתור. זו המהות של CI/CD — Continuous Integration ו-Continuous Deployment.
למה Actions ולא Jenkins, CircleCI או Travis CI?
שלוש סיבות עיקריות:
- מובנה. אין צורך להקים שרת חיצוני, לנהל Jenkins, או לחבר שירות צד שלישי. Actions חי בתוך GitHub, באותו מקום שבו הקוד, ה-PRs וה-issues. אפס תצורה חיצונית. הכל מתחיל מקובץ YAML אחד בריפוזיטורי שלכם.
- חינמי (לרוב הפרויקטים). 2,000 דקות בחודש בתוכנית החינמית. לרוב הפרויקטים הקטנים והבינוניים — זה מספיק בהחלט. ריפוזיטורים ציבוריים מקבלים דקות ללא הגבלה.
- אקוסיסטם ענק. מעל 25,000 actions מוכנים ב-marketplace. רוצים לפרוס ל-Vercel? יש action. לשלוח הודעה ב-Slack? יש action. לבדוק קוד עם CodeQL? מובנה. רוצים לסרוק dependencies חשודים? יש action גם לזה.
בפועל, GitHub Actions הפך לסטנדרט דה-פקטו עבור CI/CD בפרויקטי קוד פתוח ובחברות שעובדות עם GitHub. הפופולריות הזו יוצרת אפקט רשת — יותר משתמשים, יותר actions ב-marketplace, יותר תיעוד, יותר דוגמאות, ויותר ידע קהילתי שזמין בחיפוש פשוט.
השוואה מהירה לפלטפורמות אחרות
אם יש לכם ניסיון עם כלי CI/CD אחרים, הנה איך Actions משתווה:
- Jenkins — חזק מאוד, אבל דורש שרת ייעודי, תחזוקה מתמדת, וניהול plugins. Actions לא דורש תשתית כלל.
- CircleCI / Travis CI — שירותי SaaS טובים, אבל חיצוניים ל-GitHub. Actions מובנה — אין צורך בחיבור, בהגדרת webhooks, או בניהול חשבון נפרד.
- GitLab CI — מובנה ב-GitLab באותו אופן ש-Actions מובנה ב-GitHub. אם אתם ב-GitHub — Actions הוא הבחירה הטבעית.
- Azure DevOps Pipelines — אותה טכנולוגיה בבסיס (Microsoft), אבל ממשק שונה ואינטגרציה פחות הדוקה עם GitHub.
מתי Actions הוא לא הבחירה הנכונה?
הוגנות חשובה. Actions לא מושלם לכל מצב:
- Builds ארוכים מאוד (מעל 6 שעות) — יש timeout של 6 שעות ל-job. Jenkins עם self-hosted runner עדיף.
- דרישות חומרה מיוחדות — GPU, FPGA, חומרה ייחודית — צריך self-hosted runner.
- ריצה on-premise מלאה — אם הארגון דורש שאף נתון לא יוצא לענן, Actions hosted לא מתאים.
לכל שאר המקרים — וזה 95% מהפרויקטים — Actions הוא כנראה הבחירה הנכונה. היתרון של "הכל באותו מקום" (קוד, CI, issues, PRs, packages, security scanning) קשה להפריז בחשיבותו. פחות כלים = פחות context switching = יותר פרודוקטיביות.
בואו נסתכל על מה שזה אומר בפועל. בלי Actions, כל מפתח צריך:
- להריץ בדיקות ידנית לפני כל push
- לזכור לעשות build ידנית
- לפרוס ידנית לשרת
- לקוות שאף אחד לא שכח שלב
עם Actions, כל השלבים האלה אוטומטיים. טעות אנוש? לא רלוונטי. שכחתם להריץ tests? לא משנה — Actions מריץ בשבילכם. שכחתם לפרוס אחרי merge? Actions פורס אוטומטית. הלכתם הביתה? Actions ממשיך לעבוד.
זה לא רק נוחות — זה אמינות. מערכת אוטומטית לא שוכחת, לא מתעייפת, ולא עושה טעויות כי היא ממהרת. CI/CD טוב הוא ההבדל בין "דחפנו קוד שבור לפרודקשן" ל-"Actions תפס את הבאג לפני ש-merge קרה".
פתחו ריפוזיטורי שלכם ב-GitHub ולחצו על הטאב Actions. האם יש workflows? אם כן — לחצו על אחד ובדקו את ההיסטוריה שלו. אם לא — בדקו אם יש תיקיית .github/workflows/ בקוד. אם שניהם ריקים — מצוין, תיכף נבנה את ה-workflow הראשון.
1.2 אנטומיה של Workflow — מ-YAML לאוטומציה
כל workflow הוא קובץ YAML בתיקיית .github/workflows/. YAML הוא פורמט טקסט מובנה — פשוט, קריא, ורגיש ל-indentation (הזחה). אם עבדתם עם JSON, חשבו על YAML כ-JSON יותר קריא, בלי סוגריים מסולסלים.
בואו נפרק workflow שלם לחלקים ונבין כל שורה:
name: CI Pipeline # שם ה-workflow — מופיע בטאב Actions
on: # מה מפעיל אותו (trigger)
push:
branches: [main] # רק על push ל-main
pull_request:
branches: [main] # ועל PR לכיוון main
jobs: # רשימת ה-jobs (יחידות עבודה)
test: # שם ה-job הראשון
runs-on: ubuntu-latest # על איזה runner לרוץ
steps: # רשימת הצעדים בתוך ה-job
- uses: actions/checkout@v4 # action מוכן — מוריד את הקוד
- uses: actions/setup-node@v4 # מגדיר Node.js
with:
node-version: 22 # פרמטר ל-action
- run: npm install # פקודת shell — התקנת תלויות
- run: npm test # פקודת shell — הרצת בדיקות
ארבע שכבות, מלמעלה למטה:
שכבה 1: Trigger (on)
מה מפעיל את ה-workflow. הנפוצים ביותר:
push— כל push ל-branch מסוים. הנפוץ ביותר.pull_request— כשנפתח PR או מתעדכן. אידיאלי ל-CI.schedule— cron job, למשל כל יום בחצות. שימושי לבדיקות תקופתיות.workflow_dispatch— הרצה ידנית מהטאב Actions. כפתור "Run workflow" מופיע.repository_dispatch— הפעלה דרך API. שימושי לאינטגרציות חיצוניות.release— כשנוצר release חדש. מושלם ל-publish packages.
אפשר (ומומלץ) לשלב כמה triggers:
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch: # גם ידני, ליתר ביטחון
schedule:
- cron: '0 6 * * 1' # כל שני בשש בבוקר UTC
שכבה 2: Jobs
יחידות עבודה עצמאיות. כל job רץ על runner נפרד — מכונה וירטואלית חדשה ונקייה. jobs יכולים לרוץ במקביל כברירת מחדל, או בסדר עם needs. כל job יכול לרוץ על מערכת הפעלה שונה.
שכבה 3: Steps
הפעולות בתוך job. כל step הוא או uses (action מוכן מה-marketplace) או run (פקודת shell שכתבתם). Steps רצים תמיד בסדר, אחד אחרי השני. אם step נכשל — ה-job עוצר (אלא אם הוספתם continue-on-error: true).
שכבה 4: Actions
יחידות קוד ניתנות לשימוש חוזר. actions/checkout מוריד את הקוד מהריפוזיטורי, actions/setup-node מתקין Node.js, וכו'. נדבר על actions בהרחבה בסעיף 1.4.
שימו לב להבדל חשוב:
uses— מפעיל action קיים. מקבל פרמטרים עםwith:run— מריץ פקודת shell ישירה. כמו שהייתם כותבים בטרמינל.
expressions — הגישה לנתונים דינמיים
שמתם לב ל-${{ }} בקוד? זה syntax של expressions — הדרך לגשת לנתונים דינמיים ב-workflow:
${{ github.ref_name }}— שם ה-branch הנוכחי${{ github.actor }}— מי עשה את ה-push${{ github.event_name }}— סוג האירוע (push, pull_request...)${{ secrets.MY_SECRET }}— גישה ל-secret (נלמד בסעיף 1.6)${{ runner.os }}— מערכת ההפעלה של ה-runner
expressions עובדים גם בתנאים. למשל, job שרץ רק על main:
deploy:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
YAML — הדברים שחשוב לדעת
YAML הוא רגיש ל-indentation. טעות של רווח אחד יכולה לשבור את כל ה-workflow. כמה כללים:
- רווחים, לא tabs. YAML דורש רווחים. 2 רווחים ל-indentation הם הסטנדרט ב-GitHub Actions.
- מחרוזות עם תווים מיוחדים — עטפו בגרשיים:
'22'ולא22(כי YAML יפרש 22 כמספר). - רשימות — מתחילות ב-
-(מקף ורווח). - מפתחות —
key: value(נקודתיים ורווח). - הערות —
# הערה(סולמית).
הנה טעויות נפוצות שישברו את ה-workflow:
# ❌ שגוי — indentation לא עקבי
jobs:
test:
steps:
- run: echo "wrong" # ← צריך להיות מוזח פנימה
# ✅ נכון
jobs:
test:
steps:
- run: echo "correct"
# ❌ שגוי — חסר רווח אחרי נקודתיים
jobs:
test:
runs-on:ubuntu-latest # ← חסר רווח
# ✅ נכון
jobs:
test:
runs-on: ubuntu-latest
טיפ: השתמשו ב-extension של YAML ב-VS Code (למשל redhat.vscode-yaml) — הוא מזהה שגיאות YAML בזמן אמת ויציל לכם שעות של debug. גם GitHub עצמו מציע validation ב-web editor — אם יש שגיאת syntax, תראו קו אדום.
Multi-line commands ב-run
כשצריך להריץ כמה פקודות ב-step אחד, השתמשו ב-pipe (|) ב-YAML:
- name: Build and verify
run: |
echo "Starting build..."
npm run build
echo "Build complete, checking output..."
ls -la dist/
echo "Files in dist: $(ls dist/ | wc -l)"
כל שורה היא פקודה נפרדת. אם אחת נכשלת (exit code שונה מ-0) — ה-step נכשל. זה התנהגות ברירת מחדל טובה.
Environment Variables — משתני סביבה
אפשר להגדיר משתני סביבה בשלוש רמות:
# ברמת workflow — זמין לכל ה-jobs
env:
NODE_ENV: production
jobs:
build:
# ברמת job — זמין לכל ה-steps ב-job
env:
CI: true
steps:
# ברמת step — זמין רק ב-step הזה
- run: echo $MY_VAR
env:
MY_VAR: hello
סדר העדיפויות: step > job > workflow. אם אותו משתנה מוגדר בכמה רמות, הרמה הספציפית ביותר מנצחת.
Workflow Status Badge
רוצים להציג את סטטוס ה-CI ב-README? GitHub מייצר badge אוטומטית לכל workflow. הוסיפו ל-README.md:

ה-badge מתעדכן אוטומטית — ירוק כשהכל עובר, אדום כשיש כשלון.
צרו קובץ .github/workflows/hello.yml בריפוזיטורי שלכם עם ה-workflow הבא:
name: Hello World
on:
push:
branches: [main]
workflow_dispatch:
jobs:
greet:
runs-on: ubuntu-latest
steps:
- run: echo "Hello from GitHub Actions!"
- run: echo "Branch: ${{ github.ref_name }}"
- run: echo "Actor: ${{ github.actor }}"
- run: echo "Event: ${{ github.event_name }}"
- run: echo "Runner OS: ${{ runner.os }}"
עשו push, ואז לכו לטאב Actions — תראו את ה-workflow רץ. לחצו עליו לראות את הפלט של כל step. שימו לב ש-workflow_dispatch מאפשר גם הרצה ידנית.
עכשיו הריצו את ה-workflow ידנית: לכו לטאב Actions, בחרו את "Hello World" בצד שמאל, לחצו על "Run workflow". בדקו — מה ההבדל בפלט בין event_name כשהרצתם ידנית לעומת push? (תשובה: workflow_dispatch לעומת push).
1.3 Runners — איפה הקוד שלך באמת רץ
כל job רץ על runner — מכונה וירטואלית שמספקת את סביבת ההרצה. ה-runner הוא מכונה חד-פעמית: נוצרת בתחילת ה-job, נמחקת בסופו. שום דבר לא נשמר בין הרצות (חוץ מ-cache, שנלמד בסעיף 1.8).
יש שלושה סוגים:
GitHub-hosted runners
מכונות שגיטהאב מנהל בשבילכם. אפס תחזוקה:
- Ubuntu 24.04 —
ubuntu-latest. הנפוץ ביותר, הזול ביותר. מומלץ כברירת מחדל. - Windows Server 2025 —
windows-latest. מכפיל x2 בצריכת דקות. - macOS 15 —
macos-latest. מכפיל x10 בצריכת דקות (!). - ARM64 runners — חדש ב-2026, חסכוני יותר ממכונות x64, מתאים ל-workloads ARM-native.
מפרט ריפוזיטורים ציבוריים: 4 vCPUs, 16GB RAM, 14GB SSD. מספיק לרוב ה-builds בנוחות.
שימו לב: ריפוזיטורים פרטיים מקבלים runners עם מפרט מופחת — 2 vCPU ו-8GB RAM. אם ה-build שלכם כבד ואתם על ריפו פרטי, ייתכן שתרגישו את ההבדל.
Self-hosted runners
מכונות שלכם — פיזיות או וירטואליות — שאתם מחברים ל-GitHub. יתרונות: שליטה מלאה בחומרה, תוכנה מותאמת, אפשרות ל-GPU. חסרונות: אתם אחראים על תחזוקה, אבטחה, ועדכונים. מתאים לבניות כבדות, תוכנה מיוחדת, או דרישות אבטחה מחמירות.
Larger runners
מכונות GitHub-hosted חזקות יותר — מ-2 עד 64 cores. זמינים ב-Team ו-Enterprise. מאפשרים builds מהירים יותר בלי לנהל מכונות בעצמכם. מחירים גבוהים יותר מ-standard runners, אבל עדיין אפס תחזוקה.
מה מגיע מותקן על GitHub-hosted runner?
השאלה הנפוצה: "האם אצטרך להתקין X?". התשובה: כנראה שלא. GitHub-hosted runners מגיעים עם עשרות כלים מותקנים מראש:
- שפות: Node.js, Python, Ruby, Go, Java, .NET, PHP, Rust
- כלים: Git, Docker, Docker Compose, kubectl, Terraform, Helm
- דפדפנים: Chrome, Firefox (מושלם ל-E2E tests)
- DBs: PostgreSQL, MySQL, MongoDB (כ-services)
הרשימה המלאה זמינה ב-github.com/actions/runner-images. אם כלי חסר — התקינו אותו ב-step, או השתמשו ב-Docker container.
Services — מסדי נתונים ב-workflow
צריכים PostgreSQL לבדיקות? אפשר להרים service container ישירות ב-workflow:
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_PASSWORD: testpass
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
steps:
- uses: actions/checkout@v4
- run: npm test
env:
DATABASE_URL: postgres://postgres:testpass@localhost:5432/postgres
ה-service עולה לפני ה-steps ומוריד אחריהם. אפס תצורה, אפס ניקיון. Services זמינים רק ב-Linux runners.
Runner labels וגמישות
כל runner מזוהה על ידי labels. ב-GitHub-hosted, ה-labels הם שמות כמו ubuntu-latest, ubuntu-24.04, windows-latest. ב-self-hosted, אתם מגדירים labels משלכם:
jobs:
build:
runs-on: [self-hosted, linux, gpu] # runner עם 3 labels
Labels מאפשרים לכוון jobs ל-runners ספציפיים. למשל, runner עם GPU לבניית models, או runner עם גישה ל-VPN פנימי. שימו לב שכל ה-labels חייבים להתקיים — זה AND, לא OR.
ubuntu-latest vs ubuntu-24.04: ubuntu-latest מצביע תמיד לגרסה האחרונה. כרגע זה Ubuntu 24.04. כשגרסה חדשה יצאה (26.04 בהמשך), ubuntu-latest ישתנה. אם אתם צריכים יציבות, הצמדו לגרסה ספציפית: ubuntu-24.04.
| קריטריון | GitHub-hosted | Self-hosted | Larger runners |
|---|---|---|---|
| עלות | לפי דקות (free tier כלול) | עלות חומרה שלכם + $0.002/דקה platform fee | לפי דקות, יקר יותר |
| תחזוקה | אפס — GitHub מנהל | אתם אחראים לכל עדכון ותחזוקה | אפס — GitHub מנהל |
| ביצועים | סטנדרטי (4 core public / 2 core private) | לפי החומרה שלכם — ללא הגבלה | 2-64 cores לבחירתכם |
| אבטחה | sandbox חד-פעמי — מושלם | אתם אחראים — סיכון אם repo ציבורי | sandbox חד-פעמי |
| מתאים ל- | 95% מהפרויקטים | builds כבדים, GPU, תוכנה ייחודית | builds כבדים בארגון Team/Enterprise |
הכלל: התחילו תמיד עם ubuntu-latest. עברו ל-self-hosted או larger רק כשיש צורך מוכח — build שנמשך מעל 10 דקות, תוכנה שאי אפשר להתקין, או דרישות GPU.
בדקו ב-workflow שלכם — על איזה runner הוא רץ? אם כתוב runs-on: ubuntu-latest, מצוין — זו הבחירה הכלכלית ביותר. אם יש macos-latest בלי סיבה טובה (כמו build ל-iOS), שנו ל-Ubuntu — תחסכו פי 10 בדקות. גם windows-latest הוא פי 2 מ-Linux — השתמשו בו רק אם באמת צריך.
1.4 Actions Marketplace — אל תמציאו את הגלגל
ב-marketplace יש מעל 25,000 actions מוכנים. לפני שאתם כותבים step עם run ו-10 שורות bash, בדקו אם יש action שעושה את זה — בדרך כלל יש, וכנראה שהוא טוב יותר ממה שתכתבו מאפס.
Actions רשמיים שחובה להכיר
GitHub מתחזקת סט actions רשמיים תחת הארגון actions/. אלה נבדקים, מתוחזקים, ובטוחים לשימוש:
actions/checkout@v4— מוריד את קוד הריפוזיטורי. כמעט כל workflow מתחיל בזה.actions/setup-node@v4— מגדיר Node.js (גםsetup-python,setup-java,setup-goוכו')actions/cache@v4— שומר תלויות בין הרצות (נלמד לעומק בסעיף 1.8)actions/upload-artifact@v4— שומר קבצי build output (נלמד בסעיף 1.8)actions/download-artifact@v4— מוריד artifacts מ-job אחרgithub/codeql-action— סריקת אבטחה של קוד (SAST)
Actions פופולריים של צד שלישי
codecov/codecov-action— כיסוי קוד עם דוח ויזואליdocker/build-push-action— בניית Docker images ודחיפה ל-registrypeaceiris/actions-gh-pages— פרסום ל-GitHub Pagesslackapi/slack-github-action— שליחת הודעות Slack
איך מעריכים action לפני שימוש
לא כל action במרקטפלייס שווה שימוש. לפני שאתם מוסיפים action, בדקו:
- מספר כוכבים — מעל 100 כוכבים זה סימן טוב
- עדכון אחרון — אם לא עודכן חצי שנה, זהירות
- Verified creator — תג כחול אומר שגיטהאב אימתה את היוצר
- README ברור — תיעוד טוב = action מתוחזק
- Issues פתוחים — יותר מדי issues ללא מענה = action נטוש
לעולם אל תצמידו action ל-tag כמו v4 בפרודקשן. Tag יכול להשתנות — מישהו יכול לדחוף קוד זדוני ל-tag קיים (supply-chain attack). במקום זה, השתמשו ב-commit SHA מלא:
# ❌ לא בטוח — tag יכול להשתנות
- uses: actions/checkout@v4
# ✅ בטוח — SHA הוא immutable
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.7
ה-SHA הוא immutable — אי אפשר לשנות אותו. ההערה # v4.1.7 היא בשביל קריאות בלבד. לפרויקטי לימוד ותרגול, tag מספיק — אבל בפרודקשן, תמיד SHA.
איך מוצאים SHA? לכו לריפוזיטורי של ה-action ← Releases ← לחצו על הגרסה ← העתיקו את ה-commit SHA. או השתמשו ב-CLI: gh api repos/actions/checkout/commits/v4 --jq .sha.
Action Allowlisting — בקרה על actions מותרים
בארגונים גדולים, לא תמיד רוצים שכל מפתח ישתמש בכל action מהמרקטפלייס. GitHub מאפשר action allowlisting ברמת הארגון: אפשר להגביל שימוש רק ל-actions מ-creators מסוימים, או רק ל-actions שעברו סקירה פנימית. זה מנהל ב-Settings → Actions → General → Policies.
שלוש רמות הגבלה:
- Allow all actions — בלי הגבלה (ברירת מחדל)
- Allow actions from specific organizations — רק מארגונים שבחרתם (למשל
actions/*,docker/*) - Only local actions — רק actions מתוך הריפוזיטורי עצמו
כנסו ל-github.com/marketplace?type=actions וחפשו שלושה actions רלוונטיים לפרויקט שלכם. לכל אחד, רשמו: שם, כוכבים, ו-verified creator (כן/לא). העדיפו תמיד actions מ-creators מאומתים.
1.5 בונים CI/CD Pipeline — מאפס לפריסה
הגיע הזמן לבנות pipeline אמיתי. ניצור workflow עם 4 jobs: lint, test, build, deploy. לפני שנתחיל, כמה מושגים שנשתמש בהם בתרגיל (ומוסברים לעומק בהמשך הפרק):
- Artifacts — קבצים שנוצרים ב-job אחד ומועברים ל-job אחר. בסעיף 1.8 נלמד את הפרטים.
- Environment — הגדרת סביבת פריסה (כמו production) עם כללי הגנה. בסעיף 1.6 נלמד איך מגדירים.
needs— מילת מפתח שאומרת "תחכה ל-job אחר לפני שתרוץ".
אל תדאגו אם אתם לא מבינים את כל הפרטים עכשיו — העיקר לראות את התמונה המלאה. נחזור לכל מושג בנפרד.
מטרה: ליצור workflow מלא עם 4 jobs שרצים בסדר הנכון.
דרישות: ריפוזיטורי עם package.json שכולל scripts של lint, test, ו-build. אם אין לכם — חזרו להכנת הפרויקט למעלה.
שלב 1: צרו קובץ .github/workflows/ci.yml:
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'npm'
- run: npm ci
- run: npm run lint
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'npm'
- run: npm ci
- run: npm test
build:
needs: [lint, test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'npm'
- run: npm ci
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
environment: production
steps:
- uses: actions/download-artifact@v4
with:
name: build-output
path: dist/
- run: echo "Deploying to production..."
# Replace with your actual deploy command
- run: ls -la dist/
שלב 2: עשו commit ו-push. לכו לטאב Actions וצפו:
- lint ו-test רצים במקביל (כי אין
needsביניהם) - build ממתין לשניהם (בזכות
needs: [lint, test]) - deploy ממתין ל-build, ורק על main (בגלל ה-
if)
שלב 3: פתחו PR (לא ישירות ל-main) — תראו ש-deploy לא רץ. זה התנהגות נכונה — deploy רק ב-main.
מה למדנו:
needsיוצר תלויות בין jobs — מבטיח שהסדר נכוןifמאפשר תנאים — deploy רק ב-main, לא ב-PRupload-artifact/download-artifactמעבירים קבצים בין jobs שרצים על runners שוניםenvironmentמגדיר הקשר פריסה עם protection rulescache: 'npm'ב-setup-node חוסך זמן התקנה משמעותי
Troubleshooting: אם ה-workflow נכשל, בדקו:
- האם
package.jsonמכיל scripts שלlint,testו-build? - האם
package-lock.jsonקיים? (npm ciדורש אותו — אם חסר, השתמשו ב-npm installבמקום) - האם ה-indentation ב-YAML נכון? (2 רווחים, לא tabs)
- האם ה-build script באמת יוצר תיקיית
dist/?
דחפו את ה-workflow, פתחו PR, וצפו ב-Actions טאב. ודאו שאתם רואים את lint ו-test רצים במקביל. אם job נכשל — לחצו עליו ובדקו את הלוג. הסיבה הנפוצה: חסר script ב-package.json.
1.6 Secrets ו-Environments — אבטחה בפריסה
בכל pipeline רציני יש ערכים רגישים — מפתחות API, סיסמאות, tokens, connection strings. לעולם אל תשימו אותם בקוד — לא ב-YAML, לא בקובץ .env שנדחף ל-GitHub, ולא כ-hardcoded strings. GitHub מספק מנגנון secrets מוצפן ומאובטח.
שלוש רמות של Secrets
- Repository secrets — זמינים לכל workflow בריפוזיטורי. הכי נפוץ.
- Environment secrets — זמינים רק ל-jobs שמשתמשים ב-environment ספציפי. מאפשרים secrets שונים לכל סביבה (staging vs production).
- Organization secrets — זמינים לכל הריפוזיטורים בארגון, או רק לנבחרים. מושלם למפתחות API שמשותפים.
הגישה ל-secret ב-workflow היא דרך ${{ secrets.SECRET_NAME }}. GitHub מסתיר אוטומטית את הערך בלוגים — תראו *** במקום הערך האמיתי.
בנוסף, כל workflow מקבל אוטומטית GITHUB_TOKEN — token זמני עם הרשאות מוגבלות לריפוזיטורי הנוכחי. לא צריך להגדיר אותו — הוא קיים תמיד. לרוב מספיק לפעולות כמו יצירת comments, עדכון statuses, ויצירת releases.
Environments — שכבת אבטחה נוספת
Environment הוא הגדרה שמייצגת סביבת פריסה (staging, production, QA). מעבר ל-secrets ייחודיים לכל environment, אפשר להגדיר protection rules:
- Required reviewers — מישהו (או כמה אנשים) חייב לאשר ידנית לפני שה-deploy רץ. קריטי לפרודקשן.
- Wait timer — עיכוב (למשל 5 דקות) לפני ריצה. נותן זמן "לחשוב שוב".
- Branch restrictions — רק branches ספציפיים (למשל main) יכולים לפרוס ל-environment. מונע deploy מ-feature branch בטעות.
- Custom deployment branch policy — כללים מתקדמים יותר עם patterns.
Environment מופיע ב-job עם מילת המפתח environment::
deploy:
runs-on: ubuntu-latest
environment: production # ← כאן מוגדר ה-environment
steps:
- run: echo "Deploying with ${{ secrets.DEPLOY_KEY }}"
ב-YAML הזה, ה-job deploy ישתמש ב-secrets של ה-environment production. אם הגדרתם required reviewers — ה-job יחכה לאישור ידני לפני שהוא רץ.
GITHUB_TOKEN — מה מגיע אוטומטית
כל workflow run מקבל אוטומטית GITHUB_TOKEN — token זמני שפג תוקפו בסוף ה-run. אפשר לגשת אליו דרך ${{ secrets.GITHUB_TOKEN }} או ${{ github.token }}. מה הוא יכול לעשות?
- ליצור ולעדכן comments על PRs ו-issues
- לעדכן commit statuses
- ליצור releases
- לדחוף ל-GitHub Packages
- ליצור ולמחוק branches (עם הרשאות מתאימות)
מה הוא לא יכול? לפעול על ריפוזיטורים אחרים, להפעיל workflows בריפוזיטורים אחרים (כדי למנוע infinite loops), ולגשת ל-secrets של ריפוזיטורים אחרים.
אפשר לשלוט בהרשאות של GITHUB_TOKEN ברמת ה-workflow:
permissions:
contents: read # קריאת קוד
pull-requests: write # כתיבת comments על PRs
issues: write # כתיבת comments על issues
best practice: הגדירו permissions מינימליים. אם ה-workflow רק מריץ tests — הוא צריך רק contents: read. כלל הזהב: least privilege.
תבנית מומלצת: staging ו-production
הנה תבנית שעובדת לרוב הפרויקטים:
- Environment
staging— בלי protection rules, deploy אוטומטי על כל merge ל-main - Environment
production— עם required reviewer ו-wait timer של 5 דקות, deploy רק אחרי אישור
ב-workflow:
deploy-staging:
needs: build
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: staging
steps:
- run: echo "Deploy to staging"
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment: production # ← דורש אישור ידני
steps:
- run: echo "Deploy to production"
הרעיון: קודם מפרסים ל-staging (אוטומטי), בודקים שהכל עובד, ואז מאשרים ידנית את הפריסה לפרודקשן. פשוט, בטוח, ויעיל.
לעולם אל תשימו secrets בקובץ YAML! גם לא בקובץ .env שעולה ל-GitHub. השתמשו רק ב-Settings → Secrets and variables → Actions. גם אם זה נראה "יותר נוח" — מישהו יעשה fork ויראה הכל. GitHub סורקת באופן אוטומטי secrets שנדחפו בטעות (secret scanning), אבל עדיף לא להגיע לשם.
גם ב-PR logs: אם עשיתם echo ${{ secrets.MY_KEY }}, GitHub מסתיר את הערך. אבל אם חילקתם אותו לתווים בודדים עם bash — הוא עלול להופיע. אל תנסו לעקוף את ההסתרה.
הגדירו secret: Settings → Secrets and variables → Actions → New repository secret. שם: TEST_SECRET, ערך: כל מה שתרצו (למשל hello-from-settings). עכשיו הוסיפו step ל-workflow:
- run: echo "Secret length: ${#SECRET}"
env:
SECRET: ${{ secrets.TEST_SECRET }}
שימו לב: GitHub מסתיר אוטומטית את הערך בלוגים — תראו ***. אבל אתם כן יכולים להשתמש בערך בפקודות (למשל לפריסה).
צרו environment: Settings → Environments → New environment. שם: staging. הוסיפו wait timer של דקה אחת. עכשיו עדכנו job ב-workflow שלכם להשתמש בו: environment: staging. הריצו ותראו שה-job מחכה דקה לפני שרץ — זו ההגנה בפעולה.
1.7 Matrix Builds — בדיקה על כל שילוב
צריכים לבדוק שהקוד עובד על כמה גרסאות Node? או על Linux וגם Windows? בלי matrix, תצטרכו לכתוב job נפרד לכל שילוב. Matrix builds פותרים את זה — מגדירים את השילובים פעם אחת, ו-Actions מריץ jobs לכל שילוב במקביל:
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node-version: [20, 22]
fail-fast: false # אל תעצור הכל אם אחד נכשל
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm test
התוצאה: 4 jobs מקביליים — Ubuntu+Node20, Ubuntu+Node22, Windows+Node20, Windows+Node22. בלי matrix, הייתם צריכים לכתוב 4 jobs נפרדים עם קוד כמעט זהה. עם matrix — הגדרה אחת.
הגדרות מתקדמות
fail-fast — ברירת מחדל: true. כשהוא true, אם job אחד נכשל — כל שאר ה-matrix jobs מבוטלים. שנו ל-false כדי לראות את כל התוצאות:
strategy:
fail-fast: false # תמשיך לרוץ גם אם שילוב אחד נכשל
include — להוסיף שילובים ספציפיים שלא נוצרים מהמטריצה:
strategy:
matrix:
os: [ubuntu-latest]
node-version: [20, 22]
include:
- os: macos-latest # שילוב ספציפי נוסף
node-version: 22
exclude — להוציא שילובים שלא רלוונטיים:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [18, 20, 22]
exclude:
- os: macos-latest # אין טעם לבדוק macOS עם Node 18
node-version: 18
max-parallel — להגביל כמה jobs רצים במקביל. שימושי כשרוצים לחסוך minutes:
strategy:
max-parallel: 2 # מקסימום 2 jobs מקביליים
חישוב עלות matrix
שימו לב: matrix מכפיל את צריכת הדקות. 3 OS × 3 Node versions = 9 jobs מקביליים. אם כל job רץ 3 דקות, זה 27 דקות actions. עם macOS בתמהיל (מכפיל x10), זה יכול לעלות מהר.
דוגמה: matrix של 3 OS (Linux, Windows, macOS) × 3 Node versions (18, 20, 22):
- Linux jobs: 3 × 3 דקות = 9 דקות (מכפיל x1)
- Windows jobs: 3 × 3 דקות = 9 דקות (מכפיל x2 = 18 דקות equivalent)
- macOS jobs: 3 × 3 דקות = 9 דקות (מכפיל x10 = 90 דקות equivalent)
- סה"כ: 117 דקות equivalent מ-run אחד!
אם זה רץ 4 פעמים ביום × 22 ימי עבודה = 10,296 דקות בחודש. הרבה מעבר ל-free tier. תכננו בהתאם.
טיפ פרקטי: matrix מצומצם ב-PR, מלא ב-main
פתרון נפוץ: הריצו matrix מצומצם ב-PRs (רק Linux + Node latest), ואת ה-matrix המלא רק על push ל-main:
jobs:
test:
strategy:
matrix:
os: ${{ github.event_name == 'push' && fromJSON('["ubuntu-latest","windows-latest","macos-latest"]') || fromJSON('["ubuntu-latest"]') }}
node-version: ${{ github.event_name == 'push' && fromJSON('[18,20,22]') || fromJSON('[22]') }}
ככה PRs רצים מהר (job אחד), ו-main נבדק על הכל.
הוסיפו matrix build ל-workflow שלכם: ubuntu-latest ו-windows-latest עם Node 20 ו-22. הריצו וצפו ב-4 jobs רצים במקביל בטאב Actions. שאלו את עצמכם: האם באמת צריך את כל השילובים, או שמספיק לבדוק על Ubuntu בלבד?
1.8 Caching ו-Artifacts — חיסכון זמן וכסף
שני מנגנונים שחוסכים זמן ודקות: caching לתלויות ו-artifacts לקבצי build. חובה להכיר את שניהם.
Caching — שמירת תלויות בין הרצות
npm install לוקח 30-60 שניות? עם cache — 3-5 שניות. זה חוסך 60-80% מזמן ההתקנה בממוצע. הרעיון פשוט: שומרים את התלויות המותקנות, ומשחזרים אותן בהרצה הבאה.
- uses: actions/cache@v4
with:
path: ~/.npm # מה לשמור
key: npm-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: | # fallback keys
npm-${{ runner.os }}-
איך זה עובד:
- הרצה ראשונה: אין cache (miss) → התקנה מלאה → שמירה ל-cache
- הרצה שנייה: יש cache (hit) → שחזור מיידי → דילוג על התקנה
- שינוי ב-package-lock.json: key חדש → cache miss → התקנה מלאה → שמירה מחדש
ה-restore-keys הוא fallback: אם אין cache מדויק, GitHub מחפש cache עם prefix תואם. זה אומר שגם אחרי שינוי קטן ב-dependencies, תקבלו cache חלקי שעדיין חוסך זמן. לדוגמה: אם המפתח המדויק הוא npm-Linux-abc123 ולא נמצא, GitHub יחפש cache שמתחיל ב-npm-Linux- — ייתכן שהוא לא מדויק, אבל 95% מהתלויות כבר שם.
Cross-branch caching
Cache ב-GitHub Actions עובר בין branches — אבל בכיוון אחד. ה-default branch (בדרך כלל main) הוא המקור. כלומר:
- Feature branch יכול להשתמש ב-cache של main
- main יכול להשתמש רק ב-cache של main
- Feature branch A לא יכול להשתמש ב-cache של feature branch B
זה אומר שחשוב שה-main branch יריץ workflows באופן קבוע כדי ליצור cache עדכני שכל ה-feature branches ייהנו ממנו.
דרך קלה יותר: actions/setup-node@v4 כבר כולל cache מובנה. מספיק להוסיף שורה אחת:
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'npm' # ← זה מספיק! לא צריך actions/cache נפרד
גם setup-python ו-setup-java תומכים ב-cache מובנה באותו אופן.
מה כדאי לשמור ב-cache
- Node.js:
~/.npmאוnode_modules - Python:
~/.cache/pip - Gradle:
~/.gradle/caches - Docker layers: עם
docker/build-push-actioncache
שימו לב: Cache ו-artifacts חולקים את אותו storage quota (10GB לריפוזיטורים חינמיים). אם ה-cache שלכם גדול מדי, הישנים נמחקים אוטומטית (FIFO).
Artifacts — העברת קבצים בין jobs
Artifacts הם קבצי build (או כל קובץ אחר) שנוצרים ב-job אחד ואפשר:
- להוריד אותם ידנית מהטאב Actions (שימושי ל-debug)
- להעביר ל-job אחר — למשל build ב-job אחד ו-deploy ב-job אחר
השימוש הקלאסי: job אחד בונה (upload-artifact), job אחר פורס (download-artifact):
# ב-build job:
- uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
retention-days: 7 # כמה ימים לשמור
# ב-deploy job:
- uses: actions/download-artifact@v4
with:
name: build-output
path: dist/
retention-days — כברירת מחדל, artifacts נשמרים 90 יום. שנו ל-7 או 14 כדי לחסוך storage. אפשר גם להגדיר ברמת הריפוזיטורי ב-Settings → Actions → General.
Artifacts vs Cache — מה ההבדל?
שני מנגנונים ששומרים קבצים, אבל לשימושים שונים:
| קריטריון | Cache | Artifact |
|---|---|---|
| מטרה | שמירת תלויות (node_modules, pip) | שמירת תוצרי build (dist/, reports) |
| בין הרצות? | כן — זו המטרה | בין jobs באותו run, או הורדה ידנית |
| שמירה | נמחק אוטומטית אחרי 7 ימים ללא שימוש | נמחק לפי retention-days (ברירת מחדל 90) |
| גודל | עד 10GB לריפו (חינמי) | חולק את אותו quota |
| גישה | אוטומטית לפי key | upload/download או UI |
כלל אצבע: תלויות → cache. קבצי פלט → artifact.
דוגמה מלאה: build + test report כ-artifacts
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'npm'
- run: npm ci
- run: npm test -- --reporter=junit --output=test-results.xml
- run: npm run build
# שמירת build output
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
retention-days: 7
# שמירת test results (שימושי ל-debug)
- uses: actions/upload-artifact@v4
if: always() # ← גם אם הבדיקות נכשלו!
with:
name: test-results
path: test-results.xml
retention-days: 14
שימו לב ל-if: always() — בלי זה, אם הבדיקות נכשלות ה-step של upload לא ירוץ, ותפסידו את דוח הבדיקות שאתם הכי צריכים.
הוסיפו cache: 'npm' ל-actions/setup-node ב-workflow שלכם (אם עדיין לא הוספתם). הריצו פעמיים ובדקו את ההבדל בזמן — הרצה שנייה צריכה להיות מהירה בהרבה. בדקו בלוגים של ה-step — תראו הודעת "Cache restored successfully".
1.9 Reusable Workflows ו-Composite Actions — DRY בגדול
יש לכם 10 ריפוזיטורים עם אותו CI workflow? אל תעתיקו — שתפו. עקרון ה-DRY (Don't Repeat Yourself) חל גם על workflows. שתי דרכים עיקריות:
Reusable Workflows — pipeline שלם לשיתוף
Reusable workflow הוא workflow שלם שאפשר לקרוא לו מ-workflow אחר. המפתח: ה-trigger workflow_call שהופך workflow רגיל ל-reusable:
# .github/workflows/reusable-ci.yml (בריפו המשותף)
name: Reusable CI
on:
workflow_call: # ← זה מה שהופך אותו ל-reusable
inputs: # פרמטרים שה-caller מעביר
node-version:
description: 'Node.js version to use'
required: true
type: string
default: '22'
secrets: # secrets שה-caller מעביר
NPM_TOKEN:
required: false
jobs:
lint-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm test
ה-caller משתמש ב-uses ברמת ה-job (לא ברמת ה-step):
# .github/workflows/ci.yml (בריפו שקורא)
name: CI
on: [push, pull_request]
jobs:
call-ci:
uses: my-org/shared-workflows/.github/workflows/reusable-ci.yml@main
with:
node-version: '22'
secrets: inherit # מעביר את כל ה-secrets
שימו לב:
usesברמת job (לא step) — מצביע לקובץ workflow בריפו אחר@main— ה-branch או tag של ה-reusable workflowsecrets: inherit— מעביר את כל ה-secrets של ה-caller (נוח אבל פחות מאובטח מלהעביר בפירוש)- מקסימום 4 רמות קינון — reusable שקורא ל-reusable שקורא ל-reusable
Composite Actions — קטע steps לשיתוף
Composite action הוא action שמורכב מכמה steps. מתאים כשרוצים לשתף קטע מתוך workflow, לא workflow שלם:
# .github/actions/setup-and-test/action.yml
name: Setup and Test
description: 'Install deps and run tests'
inputs:
node-version:
description: 'Node.js version'
required: false
default: '22'
runs:
using: composite
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: 'npm'
- run: npm ci
shell: bash # ← חובה ב-composite action
- run: npm test
shell: bash
שימוש ב-composite action מתוך workflow:
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-and-test # path מקומי
with:
node-version: '22'
דוגמה מציאותית: ארגון עם 50 ריפוזיטורים
נניח שיש לכם ארגון עם 50 ריפוזיטורים של Node.js. בלי reusable workflows, כל ריפוזיטורי מכיל עותק של אותו CI workflow. כשצריך לשנות משהו (למשל לעדכן Node version) — צריך לעדכן 50 קבצים. עם reusable workflow:
- ריפוזיטורי
my-org/shared-workflowsמכיל את ה-reusable workflow - כל 50 הריפוזיטורים מצביעים אליו עם
uses: my-org/shared-workflows/... - שינוי ב-shared-workflows מתפשט אוטומטית לכולם
זה חוסך עשרות שעות תחזוקה בשנה ומבטיח consistency בכל הארגון. כל ריפוזיטורי חדש שנוצר מקבל CI שעובד מהיום הראשון — פשוט מעתיקים 5 שורות של caller workflow.
Versioning של reusable workflows
כמו actions, גם reusable workflows צריכים versioning. השיטה המומלצת:
- השתמשו ב-tags עם semantic versioning:
v1,v1.2,v1.2.3 - שמרו על backward compatibility — שינויים שוברים עולים major version
- ה-callers מצביעים ל-major tag:
uses: my-org/shared/.../ci.yml@v1 - עדכנו את ה-major tag כשיש patch:
v1→v1(tag move),v1.2.3→v1.2.4
ככה callers מקבלים bugfixes אוטומטית בלי לשנות קוד.
Outputs — להחזיר ערכים מ-reusable workflow
Reusable workflow יכול גם להחזיר ערכים ל-caller:
# ב-reusable workflow
on:
workflow_call:
outputs:
version:
description: 'The built version'
value: ${{ jobs.build.outputs.version }}
jobs:
build:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- id: version
run: echo "version=1.2.3" >> $GITHUB_OUTPUT
ב-caller:
jobs:
ci:
uses: ./.github/workflows/reusable-ci.yml
notify:
needs: ci
runs-on: ubuntu-latest
steps:
- run: echo "Built version: ${{ needs.ci.outputs.version }}"
| קריטריון | Reusable Workflow | Composite Action | Shared Script |
|---|---|---|---|
| מתאים ל- | pipeline שלם (CI/CD) | קטע steps חוזר | לוגיקה פשוטה (bash/python) |
| runner | מגדיר runner משלו | רץ על runner של ה-caller | רץ על runner של ה-caller |
| secrets | מקבל secrets כ-input | יורש secrets אוטומטית | יורש secrets אוטומטית |
| קינון | עד 4 רמות | ללא הגבלה | ללא הגבלה |
| שיתוף בין ריפוזיטורים | כן — uses: org/repo/path@ref | כן — עם ריפו נפרד | כן — עם git submodule |
| דוגמה טיפוסית | CI pipeline לכל הריפוזיטורים | setup + install + test משותף | סקריפט deploy |
הכלל: התחילו עם composite action לשיתוף steps. עברו ל-reusable workflow כשצריך pipeline שלם עם כמה jobs.
מטרה: ליצור reusable workflow שניתן לקרוא לו מ-workflow אחר.
שלב 1: צרו קובץ .github/workflows/reusable-ci.yml עם התוכן הבא:
name: Reusable CI
on:
workflow_call:
inputs:
node-version:
description: 'Node.js version'
required: true
type: string
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm test
שלב 2: צרו (או עדכנו) קובץ .github/workflows/ci.yml שקורא ל-reusable:
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
call-reusable-ci:
uses: ./.github/workflows/reusable-ci.yml
with:
node-version: '22'
שלב 3: דחפו ובדקו בטאב Actions — תראו שה-job call-reusable-ci מפעיל את ה-reusable workflow.
שימו לב לתחביר:
- ב-reusable: ה-trigger חייב להיות
workflow_call(לאpushאוpull_request) - ב-caller:
usesברמת job, לא ברמת step withמעביר את ה-inputs שהגדרתם ב-reusable
1.10 עלויות וייעול — כל שקל חשוב
GitHub Actions הוא חינמי — עד גבול מסוים. ריפוזיטורים ציבוריים מקבלים דקות ללא הגבלה. ריפוזיטורים פרטיים מקבלים free tier, ומעבר לזה — משלמים:
Free Tier — כמה דקות מגיע לכם
| תוכנית | דקות חינמיות (Linux) | מכפיל Windows | מכפיל macOS |
|---|---|---|---|
| Free | 2,000 | x2 | x10 |
| Pro / Team | 3,000 | x2 | x10 |
| Enterprise | 50,000 | x2 | x10 |
מה זה "מכפיל"? דקת Windows נספרת כ-2 דקות Linux מה-free tier. דקת macOS = 10 דקות Linux. אז 2,000 דקות Linux = רק 200 דקות macOS.
מה קורה מעבר ל-free tier
עלויות חריגה (overage) לריפוזיטורים פרטיים:
- Linux: $0.006 לדקה (כ-2 אגורות)
- Windows: $0.012 לדקה
- macOS: $0.062 לדקה
נשמע זול, אבל בואו נחשב: 10 workflows ביום x 5 דקות x 30 יום = 1,500 דקות בחודש. זה כבר 75% מה-free tier. עם צוות של 5 מפתחים שכל אחד דוחף 3-4 פעמים ביום — אתם חורגים מהר.
דוגמת חישוב: סטארטאפ קטן
נניח צוות של 5 מפתחים, 3 ריפוזיטורים פרטיים:
- כל מפתח עושה 4 pushes ביום
- כל push מפעיל CI workflow של 3 דקות (Linux)
- חודש עבודה = 22 ימים
חישוב: 5 מפתחים x 4 pushes x 3 דקות x 22 ימים = 1,320 דקות. עם תוכנית Free (2,000 דקות) — בסדר, אבל בלי הרבה מרווח. הוסיפו matrix build עם Windows ופתאום אתם ב-2,640 דקות equivalent.
בלי concurrency group, כל push מייצר הרצה חדשה. 10 pushes מהירים (למשל fixups ברצף) = 10 הרצות מקביליות שאוכלות minutes. הוסיפו תמיד:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
זה מבטל הרצות ישנות על אותו branch כשמגיע push חדש. במקום 10 הרצות, רק אחת (האחרונה) רצה. זה לבד יכול לחסוך 30-50% מצריכת הדקות.
Platform fee ל-self-hosted runners
שינוי חשוב ממרץ 2026: גם self-hosted runners נושאים עכשיו platform fee של $0.002 לדקה. זה לא הרבה, אבל שינוי מנטלי — self-hosted כבר לא "חינמי לגמרי". עדיין זול בהרבה מ-hosted runners, אבל חשוב לדעת שזה קיים.
עלויות storage
מעבר לדקות, יש גם עלות storage ל-artifacts ו-cache:
- Free tier: 500MB storage (Free), 2GB (Pro), 50GB (Enterprise)
- חריגה: $0.25 per GB per month
ניהול retention-days ו-cleanup של artifacts ישנים חוסך כאן. הגדירו retention-days: 7 על artifacts שלא צריכים לשמור.
8 טיפים לחיסכון בדקות
- Path filters — אל תריצו CI על שינויים ב-README או docs:
on: push: paths-ignore: - '**.md' - 'docs/**' - '.github/ISSUE_TEMPLATE/**' - Skip CI — הוסיפו
[skip ci]או[ci skip]בהודעת commit לדלג על Actions לגמרי. שימושי ל-commits של documentation או formatting. - Caching — כבר למדנו, חוסך 60-80% מזמן התקנה. שורה אחת (
cache: 'npm') שחוסכת מאות דקות. - Linux תמיד — אלא אם באמת חייבים Windows/macOS. Linux הוא הזול ביותר בפער ענק (x10 מ-macOS!).
- Concurrency groups — מבטלים הרצות מיותרות על אותו branch. חיסכון של 30-50%.
- Timeout — הגדירו
timeout-minutesכדי למנוע workflows תקועים שאוכלים דקות:jobs: test: runs-on: ubuntu-latest timeout-minutes: 10 # מקסימום 10 דקות - Matrix מצומצם ב-PR — כמו שהראינו בסעיף 1.7, הריצו matrix מלא רק על main, לא על כל PR.
- Conditional jobs — דלגו על deploy jobs ב-PRs עם
if: github.ref == 'refs/heads/main'. חוסך את זמן ה-setup של jobs מיותרים.
Concurrency Groups לעומק
Concurrency groups הם אחד הכלים החזקים ביותר לחיסכון. בואו נבין בדיוק איך הם עובדים:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
מה קורה כאן:
group— מחרוזת שמזהה את הקבוצה. כל הרצות עם אותו group name שייכות לאותה קבוצה.github.workflow— שם ה-workflow (למשל "CI/CD Pipeline")github.ref— ה-branch (למשל "refs/heads/feature/login")cancel-in-progress: true— אם הרצה חדשה נכנסת לקבוצה, הישנה מבוטלת
בלי cancel-in-progress, ההרצה החדשה ממתינה לישנה (queued). עם cancel-in-progress, הישנה מבוטלת והחדשה רצה מיד. לרוב CI, cancel-in-progress הוא מה שרוצים.
זהירות עם deploy: עבור deploy jobs, כנראה לא רוצים cancel-in-progress. deploy חצי-גמור יכול לשבור את הפרודקשן. במקום זה, תנו ל-deploys להמתין בתור:
concurrency:
group: deploy-production
cancel-in-progress: false # ← המתן, אל תבטל
| אסטרטגיה | חיסכון משוער | קושי יישום | מתי להשתמש |
|---|---|---|---|
| Concurrency groups | 30-50% | קל — 3 שורות | תמיד, בכל workflow |
| Caching | 60-80% מזמן install | קל — שורה אחת | תמיד כשיש npm/pip install |
| Path filters | 10-30% | קל — 3 שורות | כשיש docs/readme שמשתנים הרבה |
| Matrix מצומצם ב-PR | 50-80% מ-matrix | בינוני — expression | כש-matrix גדול (3+ שילובים) |
| Linux-only | 50-90% | אפס | כשלא חייבים Win/macOS |
| Timeout | מונע בזבוז קיצוני | קל — שורה אחת | תמיד, כרשת ביטחון |
סדר עדיפויות: התחילו מ-concurrency + caching (הכי קל, הכי משפיע), והוסיפו את השאר בהדרגה.
כל workflow שמריץ npm install או pip install בלי caching מבזבז 30-60 שניות על כל הרצה. על פני חודש, זה מאות דקות מיותרות. הוספת cache: 'npm' ל-setup-node לוקחת שורה אחת ויכולה לחסוך מאות דקות בחודש.
חשבו את העלות החודשית של Actions עבור הפרויקט שלכם. מלאו את הטבלה:
- כמה workflows יש לכם? ____
- כמה פעמים כל אחד רץ ביום (בממוצע)? ____
- כמה דקות כל הרצה (בדקו בטאב Actions)? ____
- על איזה runner (Linux/Windows/macOS)? ____
- מכפיל OS (Linux=1, Windows=2, macOS=10): ____
- סה"כ דקות בחודש: ____ workflows x ____ runs/day x ____ min x 22 days x ____ multiplier = ____
- האם חורגים מ-free tier? כן / לא
- אם כן, עלות חריגה: (סה"כ - free tier) x $0.006 = $____
טיפ: לכו ל-Settings → Billing → Actions כדי לראות את הצריכה בפועל.
קחו את ה-CI workflow שבניתם ב-תרגיל 1 והוסיפו את כל אמצעי החיסכון:
- הוסיפו
concurrencygroup עםcancel-in-progress: true - הוסיפו
paths-ignoreלקבצי documentation - ודאו ש-caching מוגדר (
cache: 'npm') - הוסיפו
timeout-minutes: 10לכל job
ה-workflow המייעל צריך להיראות ככה בראש הקובץ:
name: CI/CD Pipeline
on:
push:
branches: [main]
paths-ignore:
- '**.md'
- 'docs/**'
pull_request:
branches: [main]
paths-ignore:
- '**.md'
- 'docs/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
לכו ל-Settings → Billing → Actions ובדקו כמה דקות השתמשתם החודש. אם אין לכם גישה (ריפו אישי), בדקו בטאב Actions כמה זמן כל workflow לוקח. הריצו workflow עם concurrency ובלי — ודאו שהישן מבוטל כשדוחפים שוב.
1.11 סיכום ומבט קדימה
- GitHub Actions הוא מערכת CI/CD מובנית ב-GitHub — workflows, jobs, steps, actions. אין צורך בשרת חיצוני.
- Workflows מוגדרים בקבצי YAML בתיקיית
.github/workflows/. ארבע שכבות: trigger → jobs → steps → actions. - Triggers קובעים מתי workflow רץ — push, PR, schedule, dispatch, release.
- Runners הם המכונות שמריצות — GitHub-hosted (הכי נוח, 95% מהמקרים) או self-hosted (שליטה מלאה). ריפוזיטורים ציבוריים: 4 vCPU/16GB. פרטיים: 2 vCPU/8GB.
- Marketplace — מעל 25,000 actions מוכנים. תמיד צמדו ל-SHA בפרודקשן, tag מספיק ללימוד.
- Secrets ו-Environments — ניהול ערכים רגישים בשלוש רמות (repo/environment/org) עם protection rules.
- Matrix builds — בדיקה על כל שילוב של OS וגרסאות, במקביל, מהגדרה אחת.
- Caching — חיסכון של 60-80% בזמן התקנה.
cache: 'npm'ב-setup-node מספיק. - Artifacts — העברת קבצי build בין jobs עם upload/download-artifact.
- Reusable workflows — שיתוף pipelines שלמים בין ריפוזיטורים. Composite actions לשיתוף steps.
- עלויות — 2,000 דקות חינם (Linux, פרטי). Concurrency groups, path filters, caching ו-timeout חוסכים.
הוסיפו concurrency group לכל workflow. שלוש שורות שחוסכות עשרות אחוזים בדקות, מונעות הרצות כפולות, ומוודאות שרק הגרסה האחרונה של הקוד נבדקת. זה השינוי עם ה-ROI הגבוה ביותר.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
- מה ההבדל בין
needsל-ifב-job? (רמז:needsמגדיר סדר,ifמגדיר תנאי) - למה עדיף להצמיד action ל-SHA ולא ל-tag? (רמז: חשבו על supply-chain attacks)
- מה קורה כש-
fail-fast: true(ברירת מחדל) ב-matrix ו-job אחד נכשל? (רמז: מה קורה לשאר ה-jobs?) - מה ההבדל בין repository secret ל-environment secret? (רמז: חשבו על staging vs production)
- מתי תבחרו Reusable Workflow ומתי Composite Action? (רמז: pipeline שלם vs קטע steps)
- יומית: בדקו את טאב Actions אחרי כל push — וודאו ש-CI עובר ירוק. אם נכשל — תקנו לפני שממשיכים לעבוד על פיצ'ר חדש. Failing CI שמתעלמים ממנו הופך ל-"שגרה", ואז כשבאמת משהו נשבר — אף אחד לא שם לב.
- שבועית: בדקו usage ב-Settings → Billing → Actions — האם אתם בתחום ה-free tier? סרקו workflows שנכשלים בקביעות ותקנו את שורש הבעיה (לא רק re-run). בדקו אם יש runs שנתקעים מעבר ל-timeout.
- חודשית: סקרו את כל ה-workflows — האם יש מיותרים שאפשר למחוק? האם caching עדכני והמפתחות נכונים? האם actions צריכים עדכון גרסה (במיוחד security patches)? האם יש workflows ללא concurrency group? האם SHAs של actions עדכניים? ודאו ש-retention-days על artifacts לא גבוה מדי.
טיפ לצוותים: הגדירו branch protection rule שדורש CI ירוק לפני merge. זה מבטיח שאף אחד לא עוקף את הבדיקות. ב-Settings → Branches → Branch protection rules → Require status checks to pass.
- ☐ הבנתי את מבנה workflow: trigger → jobs → steps → actions
- ☐ מכיר/ה את הסוגים של triggers: push, PR, schedule, dispatch, release
- ☐ יצרתי workflow ראשון (Hello World) שרץ בהצלחה
- ☐ הרצתי workflow ידנית עם workflow_dispatch
- ☐ בניתי CI/CD pipeline עם lint, test, build, deploy
- ☐ הבנתי את ההבדל בין runners: GitHub-hosted vs self-hosted vs larger
- ☐ חיפשתי ומצאתי actions ב-marketplace
- ☐ הגדרתי secret ב-repository
- ☐ יצרתי environment עם protection rules
- ☐ הפעלתי matrix build על כמה OS/versions
- ☐ הוספתי caching ומדדתי את ההבדל בזמן
- ☐ יצרתי reusable workflow וקראתי לו מ-workflow אחר
- ☐ הוספתי concurrency group
- ☐ הוספתי path filters ו-timeout
- ☐ חישבתי את עלות ה-Actions שלי
טעויות נפוצות — סיכום
לפני שממשיכים, הנה ארבע הטעויות הנפוצות ביותר שראינו בפרק — וודאו שאתם לא עושים אותן:
| הטעות | למה מפתה | הפתרון |
|---|---|---|
| לא להגדיר concurrency group | ברירת מחדל — לא צריך לעשות כלום | 3 שורות concurrency בראש כל workflow |
| לשמור secrets ב-YAML / .env | יותר מהיר ונוח | Settings → Secrets. תמיד. |
| להתעלם מ-caching | "עובד בלי, אז למה להוסיף" | cache: 'npm' — שורה אחת, 60-80% חיסכון |
| להצמד ל-tag במקום SHA | v4 יותר קריא מ-SHA ארוך | SHA + הערת version: @abc123 # v4.1.7 |
Debugging workflows — כשמשהו נשבר
כמה כלים ל-debugging שכדאי להכיר:
- Re-run with debug logging: בטאב Actions, לחצו על "Re-run jobs" ← סמנו "Enable debug logging". זה מפעיל לוגים מפורטים יותר.
- act: כלי open-source שמריץ workflows מקומית על Docker. מושלם ל-debug בלי לדחוף כל פעם. התקנה:
brew install act(macOS) אוchoco install act-cli(Windows). ACTIONS_RUNNER_DEBUG: הגדירו secret בשםACTIONS_RUNNER_DEBUGעם ערךtrue— מפעיל debug logging לכל ההרצות.- Step outputs: הוסיפו
run: env | sortכ-step כדי לראות את כל משתני הסביבה הזמינים.
מבט קדימה
בפרק הבא: נלמד לנהל את כל מה שבנינו — ועוד הרבה יותר — מהטרמינל, עם GitHub CLI (gh). תגלו שהטאב Actions הוא רק חלק מהסיפור: אפשר להריץ workflows, לבדוק סטטוס, להוריד logs, ולנהל PRs — הכל מהטרמינל, בלי לפתוח דפדפן.
מה שמגיע בהמשך הקורס:
- פרק 2: GitHub CLI — שליטה מהטרמינל, כולל
gh workflow runו-gh run watch - פרק 3 ואילך: GitHub Copilot, Packages, Security, Projects, ועוד
אל תמתינו לפרק הבא: אם יש לכם פרויקט אמיתי, קחו את ה-CI/CD pipeline שבניתם וודאו שהוא רץ בהצלחה. זה הבסיס שעליו נבנה בכל שאר הקורס.