بناء CI/CD باستخدام GitHub Actions: نشر مشروع Django تلقائياً

بناء CI CD GitHub Actions: نشر مشروع Django تلقائياً خطوة بخطوة

إذا كنت تطور تطبيقات Django بانتظام، فغالباً أن عملية التشغيل محلياً، تشغيل الاختبارات، ثم رفع الكود يدوياً للسيرفر بدأت تصبح مرهقة وتستهلك وقتاً. هنا يأتي دور CI CD GitHub Actions لبناء خط نشر (Pipeline) آلي يختبر ويبني وينشر مشروعك تلقائياً مع كل تحديث للكود.

في هذا الدليل العملي من افهم صح سنقوم ببناء خط CI/CD كامل باستخدام GitHub Actions لمشروع Django، بداية من الإعدادات الأساسية، مروراً بتشغيل الاختبارات، وحتى نشر التطبيق تلقائياً على السيرفر أو أي منصة استضافة تدعم Git.

ما هو CI/CD ولماذا GitHub Actions بالذات؟

CI (تكامل مستمر) يعني أن كل تغيير في الكود يتم اختباره ودمجه بشكل مستمر مع الفرع الرئيسي. CD (نشر مستمر أو تسليم مستمر) يعني نشر هذه التغييرات تلقائياً إلى بيئة التشغيل (Production أو Staging) بعد نجاح الاختبارات.

GitHub Actions هو نظام CI/CD مدمج داخل GitHub يمكّنك من:

  • تشغيل أوامر معينة عند حدوث أحداث محددة (مثل push أو pull request).
  • تشغيل اختبارات Django تلقائياً.
  • بناء وتغليف المشروع (مثلاً Docker Image).
  • نشر الكود تلقائياً إلى خادم VPS أو أي منصة استضافة.

إذا كنت مهتماً بخطوط نشر أكثر تعقيداً مع AWS، يمكنك قراءة دليلنا: نشر مشروع Django على AWS باستخدام CI/CD عملي.

المتطلبات الأساسية قبل بناء CI/CD

قبل أن نبدأ في كتابة ملف GitHub Actions، تأكد من:

  • وجود مشروع Django جاهز داخل مستودع GitHub.
  • ملف requirements.txt أو pyproject.toml يحتوي على مكتبات المشروع.
  • وجود إعدادات قواعد البيانات (يمكن استخدام SQLite في بيئة CI كتجربة سريعة).
  • وجود سكربت أو طريقة للنشر (مثلاً:
    • نشر عبر SSH إلى VPS.
    • نشر عبر Docker و docker-compose.
    • أو حتى نشر لبيئة اختبار فقط بدون نشر فعلي (لـ CD جزئي).

إذا كنت تستخدم Docker في نشر مشاريعك على VPS، يمكنك الاستفادة من: نشر مشاريع Django و FastAPI على VPS باستخدام Docker Compose خطوة بخطوة.

هيكلة مشروع Django لتسهيل CI/CD

يفضل أن يكون مشروعك منظمًا كالتالي (كمثال شائع):

project-root/
├─ manage.py
├─ requirements.txt
├─ app/ أو core/ (المجلد الرئيسي للتطبيق)
├─ project_name/ (مجلد إعدادات Django)
│  ├─ settings.py
│  ├─ urls.py
│  └─ wsgi.py
└─ .github/
   └─ workflows/

سنضيف داخل مجلد .github/workflows/ ملف ci-cd.yml أو أي اسم تختاره، ليحتوي على إعدادات CI CD GitHub Actions.

مفهوم العمل داخل GitHub Actions: Jobs و Steps

أي ملف GitHub Actions عبارة عن:

  • Triggers: متى يتم تشغيل الـ Workflow (عند push، فتح PR، تاغ جديد، ...).
  • Jobs: كل Job مجموعة من الخطوات تعمل على Runner (ماكينة افتراضية).
  • Steps: أوامر محددة تنفذ داخل Job (تنصيب Python، تثبيت حزم، تشغيل اختبارات...).

سنقوم ببناء خط بسيط مكوّن من:

  1. Job لاختبار مشروع Django (CI).
  2. Job للنشر التلقائي (CD) يعتمد على نجاح الـ CI.

إنشاء Workflow لاختبار مشروع Django (CI)

1. ملف workflow أساسي

أنشئ المسار التالي إن لم يكن موجوداً:

.github/workflows/django-ci-cd.yml

وأضف الهيكل الأولي:

name: Django CI CD

on:
  push:
    branches: [ "main", "master" ]
  pull_request:
    branches: [ "main", "master" ]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

بهذا الشكل نقول لـ GitHub Actions: عند أي push أو pull_request على فرع main أو master شغّل Job اسمه test.

2. إعداد بيئة Python وتثبيت المتطلبات

داخل Job test نحتاج تثبيت Python وحزم المشروع:

  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt

يمكنك تعديل إصدار Python حسب ما تستخدمه في مشروعك.

3. إعداد بيئة Django وتشغيل الاختبارات

في بيئة CI، غالباً نستخدم SQLite بشكل افتراضي لأنها سهلة ولا تحتاج إعدادات. فقط تأكد أن settings.py يدعم هذا (غالباً الإعداد الافتراضي في Django).

الآن نضيف خطوة لتجهيز متغيرات البيئة وتشغيل الاختبارات:

      - name: Run Django tests
        env:
          DJANGO_SETTINGS_MODULE: project_name.settings
        run: |
          python manage.py migrate --noinput
          python manage.py test

استبدل project_name.settings باسم مشروعك الفعلي. هذه الخطوة:

  • تشغّل migrate لتجهيز قاعدة البيانات.
  • ثم تشغّل test لتشغيل اختبارات Django.

لو كنت تستخدم pytest، يمكن تعديل خطوة الاختبار إلى:

      - name: Run tests with pytest
        env:
          DJANGO_SETTINGS_MODULE: project_name.settings
        run: |
          python manage.py migrate --noinput
          pytest

وللمزيد عن pytest، يمكنك مراجعة: اختبار الوحدات في بايثون باستخدام pytest: دليل عملي.

إضافة مرحلة النشر (CD) بعد نجاح الاختبارات

الآن بعد أن أصبح لدينا CI يعمل، نريد نشر مشروع Django تلقائياً على بيئة الإنتاج بعد كل push (أو بعد tag معين مثلاً). سنفترض سيناريو شائع: نشر إلى خادم VPS باستخدام SSH و Git أو Docker.

1. تجهيز مفاتيح وأسرار (Secrets) في GitHub

اذهب إلى:

  1. Repository الخاص بالمشروع في GitHub.
  2. Settings > Secrets and variables > Actions > New repository secret.

أضف أسرار مثل:

  • SSH_HOST: عنوان السيرفر (مثلاً: your-server.com).
  • SSH_USER: اسم المستخدم على السيرفر (مثلاً: ubuntu).
  • SSH_KEY: المفتاح الخاص (Private Key) لـ SSH (يُنسخ محتوى الملف id_rsa).

هذه الأسرار سنستخدمها داخل GitHub Actions للوصول الآمن إلى السيرفر ونشر الكود.

2. إضافة Job جديد للنشر

سنضيف Job جديد داخل نفس الملف اسمه مثلاً deploy، يعتمد على نجاح Job test:

  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

السطر if: github.ref == 'refs/heads/main' يضمن أن النشر يتم فقط إذا كان الـ push على فرع main (يمكنك تغييره حسب سياسة النشر لديك).

3. إعداد اتصال SSH من داخل GitHub Actions

نستخدم Action جاهزة مثل webfactory/ssh-agent لإضافة المفتاح الخاص وتشغيل أوامر SSH:

      - name: Setup SSH
        uses: webfactory/[email protected]
        with:
          ssh-private-key: ${{ secrets.SSH_KEY }}

      - name: Add known hosts
        run: |
          ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts

الآن يمكننا تنفيذ أوامر مباشرة على السيرفر عبر SSH.

4. مثال نشر بسيط باستخدام Git + systemd

نفترض أنك على السيرفر لديك:

  • مجلد مشروع Git مكلون في /var/www/myproject.
  • خدمة gunicorn تعمل كـ systemd service مثلاً gunicorn-myproject.

نضيف خطوة تنفيذ أوامر SSH:

      - name: Deploy to VPS
        run: |
          ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'EOF'
          cd /var/www/myproject
          git pull origin main
          source venv/bin/activate
          pip install -r requirements.txt
          python manage.py migrate --noinput
          python manage.py collectstatic --noinput
          sudo systemctl restart gunicorn-myproject
          sudo systemctl restart nginx
          EOF

بهذه الأوامر:

  • تسحب آخر نسخة من الكود من GitHub.
  • تحدّث الحزم.
  • تطبق الـ migrations.
  • تجمع الملفات الثابتة (static files).
  • تعيد تشغيل خدمات gunicorn و nginx.

يمكنك تعديل المسارات والأوامر حسب إعدادات سيرفرك.

مثال كامل لملف CI CD GitHub Actions لمشروع Django

إليك ملف متكامل يمكنك نسخه وتعديله وفقاً لمشروعك:

name: Django CI CD

on:
  push:
    branches: [ "main", "master" ]
  pull_request:
    branches: [ "main", "master" ]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt

      - name: Run Django tests
        env:
          DJANGO_SETTINGS_MODULE: project_name.settings
        run: |
          python manage.py migrate --noinput
          python manage.py test

  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup SSH
        uses: webfactory/[email protected]
        with:
          ssh-private-key: ${{ secrets.SSH_KEY }}

      - name: Add known hosts
        run: |
          ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts

      - name: Deploy to VPS
        run: |
          ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'EOF'
          cd /var/www/myproject
          git pull origin main
          source venv/bin/activate
          pip install -r requirements.txt
          python manage.py migrate --noinput
          python manage.py collectstatic --noinput
          sudo systemctl restart gunicorn-myproject
          sudo systemctl restart nginx
          EOF

تذكّر تعديل:

  • project_name.settings.
  • مسار المشروع /var/www/myproject.
  • اسم خدمة gunicorn-myproject.
  • فروع Git المستخدمة.

تعامل مع متغيرات البيئة وملفات .env

في بيئة الإنتاج، غالباً تستخدم متغيرات بيئة حساسة مثل SECRET_KEY، بيانات قاعدة البيانات، مفاتيح OAuth2 وغيرها. لا يجب أن تُرفع هذه القيم إلى Git.

أشهر الطرق للتعامل معها في سياق CI/CD:

  • استخدام ملف .env على السيرفر وحده (لا يُرفع إلى المستودع).
  • ضبط القيم في systemd service كـ Environment variables.
  • أو استخدام Secrets في GitHub وتمريرها حسب الحاجة (لبيئات مؤقتة أو Staging).

إذا كنت تبني منظومة مصادقة مثل OAuth2 في مشروع Django أو FastAPI، راجع: تنفيذ OAuth2 في Django و FastAPI: دليل عملي كامل لتفهم حساسية إدارة المفاتيح والأسرار وما يرتبط بها في بيئات الإنتاج.

تحسين الـ CI CD GitHub Actions لمشاريع Django كبيرة

لمشاريع أكبر وأكثر تعقيداً، يمكنك تطوير خط CI/CD كالتالي:

  • إضافة Matrix Testing: تجربة المشروع على أكثر من إصدار Python أو أكثر من قاعدة بيانات (PostgreSQL + MySQL).
  • إضافة مرحلة Linting: تشغيل أدوات مثل flake8 أو black للتحقق من أسلوب الكود.
  • Docker-based CI/CD: بناء صورة Docker في مرحلة CI، ثم دفعها إلى Registry (Docker Hub أو GitHub Container Registry)، وبعدها نشرها على السيرفر.
  • بيئة Staging: جعل النشر التلقائي إلى بيئة Staging فقط، بينما نشر Production يتم بعد موافقة (Manual Approval) أو Tag معين.
  • أتمتة مهام إضافية: مثل إرسال تنبيه إلى Slack/Discord بعد نجاح أو فشل النشر، أو تحديث وثائق API آلياً.

ولأفكار أكثر حول أتمتة المهام للمطورين باستخدام GitHub Actions يمكنك الرجوع إلى: أتمتة مهام الروتين اليومي للمطورين باستخدام GitHub Actions.

نصائح عملية لتجنّب المشاكل الشائعة

  • ابدأ بـ CI فقط: تأكد أن اختباراتك تعمل جيداً على GitHub Actions قبل إضافة مرحلة النشر.
  • استخدم فرعاً خاصاً للتجارب: جرّب Workflow على فرع مثلاً dev حتى لا تعطل بيئة الإنتاج.
  • سجلات GitHub Actions مهمة: عند حدوث أي خطأ، افتح صفحة Actions في GitHub وراجع Log لكل خطوة لمعرفة السبب.
  • حافظ على Secrets محدثة: عند تغيير مفتاح SSH أو كلمة مرور، تذكّر تحديثها في GitHub Secrets.
  • لا تخزن أسراراً في الكود: أي متغير حساس يجب أن يأتي من البيئة أو Secrets، وليس مباشرة داخل settings.py.

خاتمة: CI CD GitHub Actions كأداة أساسية لمطوري Django

بناء خط CI CD GitHub Actions لمشروع Django لم يعد رفاهية، بل أصبح جزءاً أساسياً من أي عملية تطوير احترافية. بفضل GitHub Actions يمكنك:

  • ضمان أن كل تغيير في الكود يمر عبر اختبارات تلقائية.
  • تقليل الأخطاء البشرية في عملية النشر اليدوي.
  • تسريع دورة التطوير والنشر ورفع جودة الكود.

ابدأ بالملف البسيط الذي عرضناه، ثم طوّره تدريجياً ليتناسب مع احتياجات مشروعك: أضف Docker، بيئات متعددة، اختبارات أمان، وتحليلات جودة الكود. ومع الوقت ستجد أن خط CI/CD الخاص بك أصبح جزءاً لا يتجزأ من بنية مشروعك، تماماً مثل كود Django نفسه.

حول المحتوى:

دليل عملي لبناء خط نشر تلقائي باستخدام GitHub Actions لاختبار وبناء ونشر تطبيق Django.

هل كان هذا مفيدًا لك؟

أضف تعليقك