التكامل والنشر المستمر (CI/CD)
درس 3 من 4
3التكامل والنشر المستمر (CI/CD)
الصورة الكبيرة«شغّلت الاختبارات؟» سؤال ينساه الجميع أحيانًا. CI يجيب عنه آليًا لكل push، وCD يأخذ ما نجح ويوصله للإنتاج بنفس الخطوات كل مرة.
ماذا تشاهد في الرسم: خط CI/CD: كل مرحلة تمنع التالية إن فشلت. ما يصل للنشر اجتاز كل شيء.
خارطة هذا الجزء
المفاهيم بالترتيب، اضغط أيًّا منها للقفز إليه:
طريقان إلى نفس الفكرة
مثل خط إنتاج في مصنع: كل قطعة تمر على محطة فحص الأبعاد، ثم محطة اختبار التشغيل، ثم التغليف. القطعة المعيبة تُرفض عند أول محطة، ولا تصل للزبون. CI/CD هو هذا الخط للكود.
GitHub Actions: ملف YAML في .github/workflows/ يُشغّل على أحداث (push، pull_request). الملف فيه مهام (jobs) تعمل متوازية أو متتابعة (needs)، وكل مهمة خطوات (uses لإجراء جاهز، run لأمر). مصفوفة (matrix) لتجربة عدة إصدارات. التخزين المؤقت (actions/cache أو cache: pip) يسرّع التثبيت. الأسرار من secrets.*، والصلاحيات بأقل حد (permissions:). حماية الفرع: الفحوص المطلوبة تمر ومراجعة واحدة قبل الدمج. CD: بعد الدمج في main تُبنى صورة بوسم الـ commit وتُنشر، مع بيئات (environments) وموافقة يدوية للإنتاج إن لزم. وثبّت إصدارات الإجراءات الخارجية.
قبل أن تبدأ
🔀Git وGitHub
الفروع وطلبات الدمج.
🧪الاختبارات
مسار جودة الكود.
🐳Docker
مسار الحاويات والنشر.
الفكرة الجوهرية
1أول workflow
ملف واحد يفحص ويختبر كل push وطلب دمج على إصدارين من بايثون:
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python: ["3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
cache: pip
- run: pip install -r requirements.txt
- run: ruff check .
- run: pytest -q|| true أو continue-on-error: true. الفحص الذي لا يفشل لا يحمي شيئًا.2من CI إلى CD
مهمة نشر تعمل فقط بعد نجاح الاختبار وعلى main فقط، وتأخذ أسرارها من GitHub:
deploy:
needs: test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- run: docker build -t registry.example.com/cafe-api:${{ github.sha }} .
- run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login registry.example.com -u ci --password-stdin
- run: docker push registry.example.com/cafe-api:${{ github.sha }}
- run: ./scripts/deploy.sh ${{ github.sha }}github.sha يربط كل نسخة منشورة بـ commit محدد، فالتراجع إعادة نشر sha سابق.3حماية الفرع الرئيسي
من إعدادات المستودع: Branches ثم قاعدة لـ main: اطلب طلب دمج، واطلب نجاح فحص test، واطلب مراجعة واحدة، وامنع الدفع المباشر. الآن لا يدخل main كود لم يُختبر، حتى منك.
مثال محلول
المسألة: CI يأخذ 14 دقيقة فيتجاهله الفريق ويدمج قبل انتهائه. القياس: 9 دقائق تثبيت اعتماديات، و4 اختبارات تكامل متتابعة. الحل: cache: pip يحوّل التثبيت لـ 40 ثانية، وتقسيم الاختبارات لمهمتين متوازيتين، وفحص التنسيق كأول خطوة ليفشل خلال ثوانٍ. النتيجة: 4 دقائق، والفريق ينتظر النتيجة.
خرافة مقابل حقيقة
| الخرافة | الحقيقة |
|---|---|
| CI للفرق الكبيرة فقط. | مطوّر واحد ينسى تشغيل الاختبارات أيضًا. ملف واحد يكفي. |
| النشر التلقائي خطر. | النشر اليدوي بخطوات متغيرة أخطر. التلقائي نفس الخطوات كل مرة مع فحوص. |
اختبر فهمك
أين يوضع ملف workflow في GitHub Actions؟
GitHub يقرأ ملفات YAML من هذا المجلد فقط.
كيف تجعل مهمة النشر تنتظر نجاح الاختبار؟
needs يجعلها تبدأ فقط بعد نجاح المهمة المذكورة.
ما فائدة حماية الفرع بفحص مطلوب؟
الفرع الرئيسي يبقى دائمًا في حالة سليمة.
بطاقات مراجعة سريعة
تحقق من فهمك
لماذا يكون الفحص الأسرع أولًا؟
ليفشل الخطأ الواضح خلال ثوانٍ بدل انتظار الاختبارات الطويلة.
أين تضع مفتاح النشر؟
في أسرار المستودع أو البيئة، ويُقرأ بـ secrets.NAME.
ما خطر إجراء خارجي غير مثبت الإصدار؟
قد يتغير محتواه فيشغل كودًا لم تراجعه بصلاحيات مستودعك.
مصادر هذا الدرس
مرتّبة بالنوع. ابدأ بالتوثيق الرسمي إذا تبي المرجع الدقيق، وبالمقال أو الفيديو إذا تبي الشرح أولًا.
توثيق رسمي2
خلّصت الدرس؟
سجّل الدخول ليُحفظ تقدّمك.