نشر تطبيقاتنا كان كابوساً يدوياً: كيف أنقذتنا ‘خطوط أنابيب CI/CD’ من جحيم الإصدارات المليئة بالأخطاء؟

يا جماعة الخير، السلام عليكم ورحمة الله وبركاته، معكم أخوكم أبو عمر.

اسمحوا لي أرجع بالذاكرة ليلة ما بنساها، كانت ليلة خميس والمفروض الكل يستعد لعطلة نهاية الأسبوع. كنا شغالين على تحديث كبير لتطبيق أحد العملاء المهمين. كان معنا قائمة طويلة “Checklist” من المهام اللي لازم نعملها عشان نرفع التحديث الجديد على السيرفر: نسخ الملفات، تشغيل سكربتات قاعدة البيانات، إعادة تشغيل الخدمات، تحديث بعض الإعدادات… قائمة طويلة ومملة وكلها شغل يدوي.

الساعة كانت حوالي 11 بالليل، والكل تعبان ومرهق. “يلا يا شباب، هانت”، قلتها وأنا بحاول أرفع معنويات الفريق. بدأنا عملية النشر خطوة بخطوة. بعد حوالي ساعة من الشغل المتواصل والتركيز العالي، ضغطنا الزر الأخير وأعلنا “تم النشر بنجاح!”. تنفسنا الصعداء، وبدأنا نلم أغراضنا عشان نروح. ما كملنا خمس دقايق إلا والتلفون برن… العميل.

الموقع واقع! “شو هالحكي يا زلمة؟” صرنا نركض على أجهزتنا، والضغط وصل مليون. بعد فحص سريع ومؤلم، اكتشفنا إن زميلنا نسِي يشغّل سكربت واحد صغير لتحديث قاعدة البيانات. خطأ بشري بسيط بسبب الإرهاق، لكنه كلّفنا سمعتنا، وكلّف العميل فلوس، وكلّفنا ليلة كاملة من التصليح والاعتذارات. في هذيك الليلة، وأنا مروّح الصبح وشايف الشمس بتشرق، قلت لنفسي: “مستحيل نكمل هيك. لازم يكون في طريقة أفضل”.

وهنا كانت بداية رحلتي مع ما يُعرف بـ “خطوط أنابيب التكامل والنشر المستمر” أو الـ CI/CD Pipelines. هذه التقنية لم تكن مجرد حل، بل كانت المنقذ الذي انتشلنا من جحيم النشر اليدوي المليء بالأخطاء.

ما هي خطوط أنابيب CI/CD؟ وليش هي مهمة؟

ببساطة شديدة، تخيل أن عملية بناء ونشر تطبيقك مثل خط تجميع في مصنع سيارات. الكود الخام هو المواد الأولية، والتطبيق الجاهز هو السيارة النهائية. خط أنابيب CI/CD هو خط التجميع المؤتمت بالكامل.

بدل ما يكون عندك فريق من العمال (المبرمجين) يقومون بتجميع كل جزء يدويًا في كل مرة (عملية النشر اليدوية)، عندك آلات (الـ Pipeline) تقوم بكل شيء بشكل آلي: تفحص جودة الأجزاء (الاختبارات)، تجمعها معًا (البناء)، وتوصل السيارة النهائية للمعرض (النشر).

الـ CI/CD يتكون من جزئين أساسيين:

  • CI – Continuous Integration (التكامل المستمر): التركيز هنا على دمج تغييرات الكود من كل المطورين في مستودع مركزي بشكل متكرر، ثم بناء الكود وتشغيل الاختبارات عليه تلقائيًا. الهدف هو اكتشاف أي مشاكل تعارض أو أخطاء في الكود في مرحلة مبكرة جدًا.
  • CD – Continuous Delivery/Deployment (التسليم/النشر المستمر): بعد نجاح مرحلة التكامل، يتم أخذ الكود الذي تم بناؤه واختباره وتجهيزه للنشر.
    • التسليم المستمر (Delivery): يتم نشر التحديث على بيئة اختبار (Staging) تلقائيًا، ويكون جاهزًا للنشر على البيئة النهائية (Production) بضغطة زر يدوية.
    • النشر المستمر (Deployment): هي الخطوة الأكثر تقدمًا، حيث يتم نشر التحديث على البيئة النهائية تلقائيًا بدون أي تدخل بشري إذا نجحت كل الاختبارات السابقة.

المرحلة الأولى: التكامل المستمر (CI) – وداعاً لـ “Merge Hell”

مشكلة “Merge Hell” أو “جحيم الدمج” هي لما يشتغل كل مطور على جهازه لأسابيع، ولما يجي وقت دمج كل الشغل مع بعض، تطلع ألف مشكلة وتعارض بين الأكواد، وبتقضي أيام بس بتحاول تحل هالمشاكل.

التكامل المستمر يحل هذه المشكلة عن طريق إجبار المطورين على دمج أكوادهم بشكل يومي (أو حتى عدة مرات في اليوم). كل عملية دمج تُطلق عملية آلية تقوم بالآتي:

  1. البناء (Build): يتم تجميع الكود المصدري. إذا كان هناك خطأ في بناء الكود (Syntax Error مثلاً)، تفشل العملية هنا ويتم إبلاغ الفريق فورًا.
  2. الاختبار (Test): يتم تشغيل مجموعة من الاختبارات الآلية (Automated Tests) مثل اختبارات الوحدة (Unit Tests) واختبارات التكامل (Integration Tests). هذه الاختبارات تتأكد أن التغييرات الجديدة لم تكسر أي وظيفة قديمة.
  3. التقرير (Report): إذا فشل البناء أو أي اختبار، يتم إرسال إشعار فوري للفريق (عبر Slack، الإيميل، …إلخ). هذا يعني أن الخطأ يُكتشف ويُصلح في دقائق، وليس بعد أسابيع.

مثال عملي: إعداد CI بسيط باستخدام GitHub Actions

لنفترض أن لدينا مشروع Node.js ونريد التأكد من أن كل عملية push للـ repository تقوم بتشغيل الاختبارات تلقائيًا. كل ما نحتاجه هو إنشاء ملف باسم .github/workflows/ci.yml.


name: Node.js CI

# متى يتم تشغيل هذا الـ workflow
on:
  push:
    branches: [ "main" ] # عند أي عملية push على الفرع الرئيسي
  pull_request:
    branches: [ "main" ] # عند فتح أي pull request على الفرع الرئيسي

jobs:
  build_and_test:
    # نوع الجهاز الذي سيتم تشغيل المهمة عليه
    runs-on: ubuntu-latest

    steps:
    # الخطوة الأولى: سحب الكود من الـ repository
    - name: Checkout code
      uses: actions/checkout@v3

    # الخطوة الثانية: إعداد بيئة Node.js بالإصدار المطلوب
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'

    # الخطوة الثالثة: تحميل الاعتماديات (dependencies)
    - name: Install dependencies
      run: npm install

    # الخطوة الرابعة: تشغيل الاختبارات الآلية
    - name: Run tests
      run: npm test

بهذا الملف البسيط، أصبح لدينا الآن تكامل مستمر! أي مطور يقوم برفع كود يكسر الاختبارات، سيعرف هو والفريق بأكمله خلال دقائق.

المرحلة الثانية: التسليم والنشر المستمر (CD) – نحو الأتمتة الكاملة

بعد أن نتأكد من أن الكود سليم ويعمل بشكل جيد من خلال مرحلة الـ CI، ننتقل إلى مرحلة الـ CD. الهدف هنا هو أتمتة عملية إيصال هذا الكود للمستخدم النهائي.

خطوات هذه المرحلة عادةً ما تكون:

  1. إنشاء الحزمة (Package): يتم تحزيم التطبيق في شكل قابل للنشر. أشهر طريقة اليوم هي بناء Docker Image، لأنها تضمن أن التطبيق سيعمل بنفس الطريقة على أي جهاز.
  2. النشر على بيئة الاختبار (Deploy to Staging): يتم نشر الحزمة تلقائيًا على سيرفر “Staging” الذي يكون نسخة طبق الأصل من سيرفر الإنتاج.
  3. اختبارات القبول (Acceptance Tests): يتم تشغيل مجموعة أخرى من الاختبارات على بيئة الـ Staging، مثل اختبارات الواجهة الأمامية (End-to-End tests) التي تحاكي استخدام المستخدم الحقيقي للموقع.
  4. النشر على بيئة الإنتاج (Deploy to Production): إذا نجحت كل الخطوات السابقة، يتم نشر التحديث على السيرفرات الحقيقية. كما ذكرنا، هذه الخطوة يمكن أن تكون يدوية (Continuous Delivery) أو آلية بالكامل (Continuous Deployment).

مثال على توسيع الـ Workflow ليشمل النشر

لنكمل على مثالنا السابق في GitHub Actions. لنفترض أننا نريد بناء Docker Image ونشرها على Docker Hub بعد نجاح الاختبارات.


# ... (نفس إعدادات الـ CI السابقة) ...

jobs:
  build_and_test:
    # ... (نفس خطوات الـ build and test) ...

  build_and_push_docker:
    # هذه المهمة تعتمد على نجاح المهمة السابقة
    needs: build_and_test
    runs-on: ubuntu-latest
    
    # يتم تشغيل هذه المهمة فقط عند الـ push على الفرع الرئيسي
    if: github.ref == 'refs/heads/main'

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

    - name: Login to Docker Hub
      uses: docker/login-action@v2
      with:
        username: ${{ secrets.DOCKERHUB_USERNAME }}
        password: ${{ secrets.DOCKERHUB_TOKEN }}

    - name: Build and push Docker image
      uses: docker/build-push-action@v4
      with:
        context: .
        push: true
        tags: yourusername/your-app:latest

ملاحظة هامة: في المثال أعلاه، استخدمنا secrets.DOCKERHUB_USERNAME. لا تقم أبدًا بكتابة كلمات المرور أو المفاتيح السرية مباشرة في ملفات الـ CI/CD. استخدم دائمًا مدير الأسرار (Secrets Manager) الذي توفره منصة الـ CI/CD التي تستخدمها (مثل GitHub Secrets, GitLab CI/CD Variables, etc.).

نصائح من خبرة أبو عمر

بعد سنوات من بناء وتطبيق هذه الأنظمة، تعلمت بعض الدروس بالطريقة الصعبة. اسمحوا لي أن أشارككم بعض النصائح العملية:

  • ابدأ صغيراً ثم توسع: لا تحاول بناء خط أنابيب كامل ومعقد من اليوم الأول. ابدأ بأتمتة الاختبارات (CI). عندما تستقر هذه العملية، انتقل لأتمتة البناء والنشر على بيئة الاختبار، وهكذا. التدرج هو مفتاح النجاح.
  • الاختبارات هي روح الـ Pipeline: خط أنابيب CI/CD بدون اختبارات جيدة هو مجرد أداة سريعة لنشر الأخطاء! استثمر وقتًا في كتابة اختبارات وحدة واختبارات تكامل قوية. جودة الـ Pipeline من جودة اختباراتك.
  • اجعل الفشل واضحًا ومؤلمًا: يجب أن يكون فشل البناء (Broken Build) حدثًا طارئًا. قم بإعداد إشعارات فورية على قنوات التواصل الخاصة بالفريق (مثل Slack). بعض الفرق تضع شاشة كبيرة في المكتب تعرض حالة الـ Pipeline، وإذا تحولت للأحمر، يتوقف الجميع عن العمل ويساهم في إصلاحها.
  • الأمان ليس رفاهية: أضف خطوات لفحص الأمان داخل الـ Pipeline. هناك أدوات تقوم بفحص الكود بحثًا عن ثغرات (SAST) وأدوات تفحص الاعتماديات (Dependencies) بحثًا عن مكتبات قديمة وغير آمنة (SCA).
  • وحّد بيئات العمل باستخدام Docker: مشكلة “شغال عندي ومش شغال عندك” تنتهي تمامًا عند استخدام Docker. عندما تقوم ببناء Docker Image في الـ Pipeline، أنت تضمن أن هذه الحزمة ستعمل بنفس الطريقة على جهاز المطور، سيرفر الاختبار، وسيرفر الإنتاج.

الخلاصة: استثمار يستحق كل قرش ووقت

التحول إلى CI/CD ليس مجرد تطبيق لمجموعة من الأدوات، بل هو تغيير في ثقافة العمل. هو الانتقال من الخوف والترقب عند كل عملية نشر، إلى الثقة والسرعة. نعم، الإعداد الأولي يتطلب جهدًا وتعلمًا، ولكنه استثمار سيوفر عليك وعلى فريقك ساعات لا تحصى من العمل اليدوي، ويحميك من كوابيس الأخطاء في منتصف الليل.

إذا كنت لا تزال تنشر تطبيقاتك يدويًا، فأتمنى أن تكون قصتي دافعًا لك للبدء. ابدأ اليوم، ولو بخطوة بسيطة. ابدأ بأتمتة اختباراتك. ستشكرني لاحقًا. 🚀

والله ولي التوفيق.

أبو عمر

سجل دخولك لعمل نقاش تفاعلي

كافة المحادثات خاصة ولا يتم عرضها على الموقع نهائياً

آراء من النقاشات

لا توجد آراء منشورة بعد. كن أول من يشارك رأيه!

آخر المدونات

ذكاء اصطناعي

نماذجنا اللغوية كانت تهلوس: كيف أنقذنا التوليد المعزز بالاسترجاع (RAG) من جحيم المعلومات الخاطئة؟

أشارككم قصة حقيقية عن "هلوسة" الذكاء الاصطناعي وكيف تسببت في مشكلة حقيقية لأحد عملائنا. اكتشفوا كيف أنقذتنا تقنية التوليد المعزز بالاسترجاع (RAG) من خلال ربط...

13 أبريل، 2026 قراءة المزيد
تجربة المستخدم والابداع البصري

واجهاتنا كانت قمرة قيادة لطائرة حربية: كيف أنقذنا ‘تقليل الحمل المعرفي’ من جحيم إرهاق المستخدمين؟

بتذكر مرة كُنا نبني لوحة تحكم معقدة، وصارت زي قمرة قيادة طائرة حربية من كثرة الأزرار والمؤشرات. في هذه المقالة، بحكي لكم كيف اكتشفنا مفهوم...

13 أبريل، 2026 قراءة المزيد
برمجة وقواعد بيانات

بحثنا كان يزحف كالسلحفاة: كيف أنقذتنا ‘فهارس قاعدة البيانات’ (Database Indexing) من جحيم المسح الكامل للجدول؟

أشارككم قصة حقيقية عن مشروع كاد أن يفشل بسبب بطء كارثي، وكيف كانت "فهارس قواعد البيانات" هي المنقذ الذي حول زحف السلحفاة إلى سرعة البرق....

13 أبريل، 2026 قراءة المزيد
الحوسبة السحابية

بنيتنا التحتية كانت قصورًا من رمال: كيف أنقذتنا ‘البنية التحتية كشيفرة’ (IaC) من جحيم الانحراف في الإعدادات؟

أنا أبو عمر، وأهلاً بكم في مقالة جديدة. دعوني أحكي لكم قصة عن ليلة خميس كادت أن تدمر مشروعاً كاملاً بسبب تغيير يدوي بسيط، وكيف...

13 أبريل، 2026 قراءة المزيد
التوظيف وبناء الهوية التقنية

ملفي الشخصي على GitHub كان مدينة أشباح: كيف أنقذتني ‘المشاريع المثبتة والـ READMEs’ من جحيم التجاهل؟

هل تشعر أن ملفك على GitHub لا يعكس خبرتك الحقيقية ويتم تجاهله من قبل مسؤولي التوظيف؟ في هذه المقالة، أشاركك قصتي وكيف حولت ملفي من...

13 أبريل، 2026 قراءة المزيد
التوسع والأداء العالي والأحمال

خادمنا الوحيد كان على وشك الانهيار: كيف أنقذنا ‘موازن الأحمال’ من جحيم نقطة الفشل الواحدة؟

أشارككم قصة حقيقية من بداياتي، حين كاد خادمنا الوحيد أن ينهار تحت الضغط، وكيف كان "موازن الأحمال" (Load Balancer) هو البطل الذي أنقذ الموقف. سنتعمق...

13 أبريل، 2026 قراءة المزيد
البودكاست