اكتشف كيف تحول GitHub Actions من مجرد أداة CI/CD إلى محرك أتمتة كامل لمشروعك، مع أمثلة واقعية من شركات مثل Netflix وShopify، وحيل لتجنب الفخاخ التي تكلف الفرق ساعات من Debugging.
في يوم من الأيام، كان فريقنا يعمل على مشروع SaaS كبير، وكل شيء يبدو على ما يرام حتى جاء يوم النشر. فجأة، اكتشفنا أن أحد المكتبات الجديدة تسبب في فشل Build على بيئة الإنتاج فقط، بينما كانت كل الاختبارات المحلية والمراحل السابقة تمر بنجاح. المشكلة؟ لم نكن نتحقق من التوافق مع Node.js 20 في بيئة الإنتاج قبل النشر. هنا دخل GitHub Actions كمنقذ، ليس فقط لتشغيل الاختبارات، بل لتنفيذ سيناريو كامل: بناء التطبيق، تشغيل اختبارات التوافق مع إصدارات متعددة من Node، وحتى إرسال تنبيه إلى Slack إذا فشل أي شيء. بعد ذلك اليوم، لم نعد نرى GitHub Actions كأداة CI/CD تقليدية، بل كطبقة أتمتة ذكية تتحكم في كل خطوة من خطوات المشروع.
الحقيقة هي أن معظم الفرق تستخدم GitHub Actions بطريقة سطحية: تشغيل `npm test` أو بناء Docker image. لكن في 2025، أصبحت الأداة قادرة على أكثر من ذلك بكثير. فكر في GitHub Actions كجهاز عصبي لمشروعك، حيث كل حدث (push، pull request، issue opened) يمكن أن يطلق سلسلة من العمليات التي تتحكم في كل شيء من التحليل الستاتيكي للكود إلى نشر التطبيق على بيئات متعددة، وحتى إدارة البنية التحتية عبر Terraform. الفرق بين الفرق الجيدة والفرق الرائعة هو كيف تستخدم هذه الأتمتة لتوفير الوقت، وتقليل الأخطاء البشرية، وجعل عملية التطوير سلسة وكأنها تعمل بنفسها.
إذا كنت تستخدم GitHub Actions منذ بضع سنوات، ستجد أن الكثير قد تغير. أولاً، أصبحت الـ Runners أسرع وأكثر مرونة. الآن يمكنك تشغيل الـ Actions على آلات افتراضية مدعومة بـ Apple Silicon (M1/M2) أو حتى على Windows Server 2022 مع دعم لـ .NET 8 وNode.js 20 بشكل افتراضي. هذا يعني أن بناء تطبيقاتك وتشغيل اختباراتك سيكون أسرع بنسبة 30-50% مقارنة بالـ Runners القديمة، خاصة إذا كنت تعمل على مشاريع كبيرة تعتمد على الـ Compilation أو الـ Transpilation مثل TypeScript أو Rust.
ثانياً، أصبحت الـ Matrix Strategies أكثر ذكاءً. في السابق، إذا أردت اختبار تطبيقك على ثلاث إصدارات من Node.js وثلاثة أنظمة تشغيل، كان عليك كتابة تسع jobs منفصلة أو استخدام matrix مع قيم ثابتة. الآن، يمكنك استخدام تعبيرات ديناميكية مثل `matrix.node_version: [18, 20, 22]` و`matrix.os: ${{ fromJSON(inputs.os_list) }}` لقراءة القيم من مدخلات الـ Workflow أو حتى من ملف JSON خارجي. هذا يجعل الـ Workflows أكثر قابلية لإعادة الاستخدام وقابلة للتخصيص دون الحاجة لتعديل الكود الأساسي.
# .github/workflows/test-matrix.yml
name: Node.js Matrix Test
on:
workflow_dispatch:
inputs:
node_versions:
description: 'JSON array of Node.js versions'
required: true
default: '[18, 20, 22]'
os_list:
description: 'JSON array of OSes'
required: true
default: '["ubuntu-latest", "macos-latest", "windows-latest"]'
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
node_version: ${{ fromJSON(inputs.node_versions) }}
os: ${{ fromJSON(inputs.os_list) }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node_version }}
- run: npm ci
- run: npm test
env:
CI: trueالفرق التي تستخدم GitHub Actions بشكل مبتكر لا تقتصر على تشغيل الاختبارات والبناء. بدلاً من ذلك، تستخدم الأداة لأتمتة مهام كانت تتطلب تدخلاً بشرياً في السابق. على سبيل المثال، في Netflix، يستخدمون GitHub Actions لمراقبة أداء الـ Pull Requests. عندما يفتح مطور PR، يقوم Workflow تلقائياً بتشغيل تحليل للأداء باستخدام أدوات مثل Lighthouse، ويقارن النتائج مع الـ Baseline، ثم يعلق على الـ PR بنتائج التحليل. إذا انخفض الأداء بنسبة معينة، يتم رفض الـ PR تلقائياً حتى يتم تحسين الكود.
مثال آخر من Shopify، حيث يستخدمون GitHub Actions لأتمتة إدارة الـ Dependencies. بدلاً من الاعتماد على أدوات مثل Dependabot التي ترسل PRs بشكل عشوائي، لديهم Workflow مخصص يتحقق من التحديثات الأمنية فقط، ثم يقوم بتحديث الـ Dependencies، ويشغل اختبارات التكامل، وإذا مرت كل الاختبارات، يقوم بإرسال PR تلقائياً. هذا يقلل من الضوضاء في الـ Repository ويضمن أن التحديثات الأمنية لا تُهمل أبداً. الفكرة هنا هي تحويل GitHub Actions من مجرد أداة تنفيذية إلى نظام ذكي يتخذ قرارات بناءً على البيانات والسياق.
# .github/workflows/auto-update-dependencies.yml
name: Auto Update Dependencies
on:
schedule:
- cron: '0 8 * * 1-5' # Run at 8 AM UTC on weekdays
workflow_dispatch:
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- name: Check for security updates
id: security-updates
run: |
UPDATES=$(npm audit --json | jq -r '.actions[].resolves[].id' | tr '\n' ' ')
echo "updates=$UPDATES" >> $GITHUB_OUTPUT
- name: Update dependencies
if: steps.security-updates.outputs.updates != ''
run: |
npm install ${{ steps.security-updates.outputs.updates }}
npm test
- name: Create Pull Request
if: success()
uses: peter-evans/create-pull-request@v5
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: 'chore: update dependencies (security)"
title: 'chore: update dependencies (security)"
body: 'This PR updates dependencies with security vulnerabilities.'
branch: 'auto/update-dependencies'أحد الاستخدامات المتقدمة لـ GitHub Actions هو إدارة البنية التحتية عبر Terraform أو Pulumi. بدلاً من تشغيل أوامر Terraform يدوياً أو الاعتماد على أدوات خارجية، يمكنك إنشاء Workflow يتحكم في كل شيء. على سبيل المثال، عندما يتم دمج PR في فرع `main`، يمكن لـ Workflow أن يقوم بتطبيق التغييرات على بيئة Staging تلقائياً. وإذا مرت كل الاختبارات، يمكن للـ Workflow نفسه أن ينتظر موافقة بشرية قبل تطبيق التغييرات على بيئة الإنتاج. هذا يقلل من الأخطاء البشرية ويضمن أن البنية التحتية دائماً في حالة متزامنة مع الكود.
# .github/workflows/deploy-infra.yml
name: Deploy Infrastructure
on:
push:
branches: [ main ]
workflow_dispatch:
jobs:
deploy-staging:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.5.0
- run: terraform init
- run: terraform plan -var="env=staging"
- run: terraform apply -auto-approve -var="env=staging"
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment:
name: production
url: https://example.com
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v2
- run: terraform init
- run: terraform plan -var="env=production"
- run: terraform apply -auto-approve -var="env=production"
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}على الرغم من قوة GitHub Actions، هناك بعض الفخاخ التي يمكن أن تسبب مشاكل كبيرة إذا لم تكن حذراً. أولاً، مشكلة الـ Secrets. الكثير من الفرق يخزنون الـ Secrets في الـ Repository Settings، وهذا جيد، لكن المشكلة تأتي عندما تستخدم هذه الـ Secrets في الـ Workflows. إذا كتبت شيئاً مثل `echo "${{ secrets.DB_PASSWORD }}"` في خطوة من الـ Workflow، سيتم طباعة الـ Secret في الـ Logs بشكل واضح، وهذا يمكن أن يسبب تسريب بيانات حساسة. الحل؟ استخدم الـ Secrets فقط في الأماكن التي تحتاجها، وتأكد من عدم طباعتها في الـ Logs بأي شكل من الأشكال.
ثانياً، مشكلة الـ Concurrency. إذا كان لديك Workflow يعمل عند كل `push`، وكان المطورون يpushون بشكل متكرر، يمكن أن ينتهي بك الأمر مع عشرات الـ Jobs تعمل في نفس الوقت، مما يستهلك الـ Runners ويزيد من فاتورة GitHub. الحل هو استخدام `concurrency` في الـ Workflow لتقييد عدد الـ Jobs التي تعمل في نفس الوقت. على سبيل المثال، يمكنك تحديد أن الـ Workflow يجب أن يعمل على فرع واحد فقط في كل مرة، وإذا كان هناك Workflow آخر يعمل بالفعل، يتم إلغاءه تلقائياً.
# .github/workflows/concurrency-example.yml
name: Test with Concurrency
on: [push]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm testثالثاً، مشكلة الـ Caching. الكثير من الفرق يستخدمون الـ Caching لتسريع الـ Workflows، لكن إذا لم يتم ضبط الـ Cache بشكل صحيح، يمكن أن ينتهي بك الأمر مع ملفات قديمة أو غير متوافقة. على سبيل المثال، إذا قمت بتخزين مجلد `node_modules` في الـ Cache، ثم قمت بتحديث الـ Dependencies، يمكن أن ينتهي بك الأمر مع نسخة قديمة من الـ Cache. الحل هو استخدام مفاتيح ديناميكية للـ Cache تعتمد على محتوى ملف `package-lock.json`، بحيث يتم إنشاء Cache جديد فقط عندما يتغير الملف.
# .github/workflows/caching-example.yml
name: Test with Caching
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Cache node_modules
uses: actions/cache@v3
id: cache
with:
path: node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- run: npm ci
if: steps.cache.outputs.cache-hit != 'true'
- run: npm testإحدى الميزات القوية في GitHub Actions هي القدرة على إنشاء Workflows قابلة لإعادة الاستخدام عبر مشاريع متعددة. بدلاً من نسخ ولصق نفس الكود في كل repository، يمكنك إنشاء Workflow مركزي واستدعاؤه من أي مكان. هذا ليس فقط يوفر الوقت، بل يضمن أيضاً أن كل المشاريع تتبع نفس المعايير. على سبيل المثال، إذا كانت شركتك لديها سياسة معينة لتشغيل الاختبارات أو بناء Docker images، يمكنك إنشاء Workflow مركزي يحتوي على هذه السياسة، ثم استدعاؤه من كل مشروع.
لإنشاء Workflow قابل لإعادة الاستخدام، تحتاج إلى تعريف Workflow في repository مركزي، ثم استخدام `workflow_call` كحدث. يمكنك أيضاً تمرير مدخلات إلى الـ Workflow، مثل اسم الفرع أو بيئة النشر، لجعله أكثر مرونة. في المثال التالي، سننشئ Workflow مركزي لبناء Docker image واستدعائه من مشروع آخر.
# .github/workflows/build-docker.yml (in central repository)
name: Build Docker Image
on:
workflow_call:
inputs:
image_name:
required: true
type: string
tag:
required: false
type: string
default: latest
secrets:
DOCKER_USERNAME:
required: true
DOCKER_PASSWORD:
required: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v4
with:
push: true
tags: ${{ inputs.image_name }}:${{ inputs.tag }}# .github/workflows/deploy.yml (in project repository)
name: Deploy
on: [push]
jobs:
build:
uses: your-org/central-repo/.github/workflows/build-docker.yml@main
with:
image_name: your-org/your-app
tag: ${{ github.sha }}
secrets:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}GitHub Actions مجاني للمشاريع العامة والمشاريع الخاصة الصغيرة، لكن عندما تبدأ في استخدامه بشكل مكثف، يمكن أن ترتفع التكلفة بسرعة. المشكلة ليست فقط في عدد الـ Minutes التي تستهلكها، بل أيضاً في كيفية استخدامك للـ Runners. على سبيل المثال، إذا كنت تستخدم الـ Runners الافتراضية لـ GitHub، فستدفع مقابل كل دقيقة تستخدمها، وإذا كنت تعمل على مشروع كبير يتطلب بناء متكرر، يمكن أن تصل التكلفة إلى مئات الدولارات شهرياً. الحل؟ استخدم الـ Self-hosted Runners لتوفير التكلفة، أو قم بتحسين الـ Workflows لتقليل الوقت المستهلك.
أحد الحلول الذكية هو استخدام الـ Caching لتقليل وقت البناء. على سبيل المثال، إذا كنت تبني تطبيق React، يمكنك تخزين مجلد `node_modules` في الـ Cache، بحيث لا تضطر إلى تحميل الـ Dependencies في كل مرة. يمكنك أيضاً استخدام الـ Matrix Strategies لتشغيل الـ Jobs بالتوازي، مما يقلل من الوقت الكلي للتنفيذ. وأخيراً، يمكنك استخدام `timeout-minutes` لتحديد الحد الأقصى للوقت الذي يمكن أن يستغرقه الـ Job، لمنع الـ Jobs من التعليق واستهلاك الـ Minutes دون داع.
# .github/workflows/optimized-build.yml
name: Optimized Build
on: [push]
env:
CI: true
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Cache node_modules
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
- run: npm ci
if: steps.cache.outputs.cache-hit != 'true'
- run: npm run build
- run: npm testإذا كنت تريد أن تستفيد من GitHub Actions بشكل كامل، ابدأ بتحويل كل مهمة متكررة في مشروعك إلى Workflow. لا تقتصر على الـ CI/CD التقليدي، بل فكر في الأتمتة الذكية: تحليل الأداء، إدارة الـ Dependencies، وحتى إدارة البنية التحتية. استخدم الـ Workflows القابلة لإعادة الاستخدام لتوحيد المعايير عبر المشاريع، وتأكد من ضبط الـ Concurrency والـ Caching لتجنب المشاكل والأخطاء. وأخيراً، راقب أداء الـ Workflows واستخدم الـ Self-hosted Runners إذا كنت تريد توفير التكلفة. في النهاية، GitHub Actions ليس مجرد أداة، بل هو نظام تشغيل لمشروعك، وكلما استخدمت أكثر ذكاءً، كلما كان مشروعك أكثر كفاءة واستقراراً.
نصيحة أخيرة: لا تخف من التجربة. أنشئ Workflow صغير لأتمتة مهمة بسيطة، ثم طوره تدريجياً. مع الوقت، ستجد أن GitHub Actions أصبح جزءاً لا يتجزأ من سير عملك، ويوفر لك ساعات من العمل اليدوي. وإذا واجهت مشكلة، تذكر أن الـ Debugging هو جزء من العملية، وكل مشكلة تواجهها هي فرصة لتعلم شيء جديد.