كان زر النشر يسبب لنا نوبات هلع: كيف أنقذتنا خطوط أنابيب CI/CD من جحيم الإصدارات اليدوية؟

يا الله شو بتذكر هداك اليوم… كانت الساعة 2 بعد نص الليل، وإحنا في المكتب بنحاول نطلق تحديث ضروري على واحد من أكبر تطبيقاتنا. قهوة باردة، عيون حمرا، والتوتر واصل للسما. كان المفروض إنه تحديث بسيط، مجرد إصلاح لعلّة (bug) مزعجة اشتكى منها العملاء.

كانت عملية النشر وقتها أشبه بطقوس السحرة: واحد منا بيعمل SSH على السيرفر، الثاني بيذكّره يعمل نسخة احتياطية من قاعدة البيانات، والثالث بيصرخ ” espir ya zalameh, la tinsa el environment variables!” (اصبر يا زلمة، لا تنسى متغيرات البيئة!). كنت أنا المسؤول عن سحب آخر نسخة من الكود من Git. سحبت الكود، عملت build، وشغّلت السيرفر… وفجأة، الشاشة صارت بيضا. الموقع وقع.

ساعتين من الجحيم ونوبات الهلع، مكالمات من المدير، ومحاولات يائسة للعودة للنسخة القديمة يدويًا. اكتشفنا في النهاية إني سحبت الكود من الـ branch الغلط. يومها، بعد ما رجّعنا كل شي لوضعه الطبيعي وقررنا ننام في المكتب، حلفت يمين إننا ما رح نضل هيك. كانت هاي هي الشرارة اللي خلتنا نبحث عن حل جذري، حل اسمه CI/CD.

ما هي قصة الـ CI/CD؟ شو يعني هالمصطلحات؟

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

التكامل المستمر (Continuous Integration – CI)

تخيل فريق شغال على مشروع، كل واحد بيكتب كود في فرع (branch) خاص فيه. في الطريقة التقليدية، بضل كل واحد شغال لحاله أيام أو أسابيع، ولما ييجوا يدمجوا شغلهم مع بعض بتصير “مجزرة”. أكواد بتتعارض، ومشاكل ما إلها أول من آخر.

الـ CI بيجي بحل هاي المشكلة. الفكرة هي إن كل مبرمج، كل ما يعمل تغيير بسيط على الكود تبعه، بيدمجه مباشرة على الفرع الرئيسي (زي main أو develop). هون بتبدأ السحر: بمجرد ما يتم الدمج، فيه سيرفر أوتوماتيكي (زي GitHub Actions أو GitLab CI) بيلقط التغيير هذا وبيعمل ثلاث شغلات أساسية:

  1. بناء المشروع (Build): بيتأكد إنه الكود الجديد ما كسر عملية البناء الأساسية.
  2. تشغيل الاختبارات (Tests): بيشغّل كل الاختبارات الآلية (Unit tests, integration tests) عشان يتأكد إنه الكود الجديد ما خرب وظائف كانت شغالة قبل.
  3. إعطاء تقرير فوري: إذا فشل البناء أو أي اختبار، النظام بيرسل تنبيه فوري للفريق عشان يصلحوا المشكلة وهي لسا “طازة”.

ببساطة، الـ CI هو شرطي المرور الذكي اللي بيضمن إنه ما في سيارة خربانة بتدخل على الشارع الرئيسي وبتعمل أزمة. “بنكتشف المشاكل بدري بدري”.

التسليم والنشر المستمر (Continuous Delivery/Deployment – CD)

بعد ما الـ CI يتأكد إنه الكود سليم وناجح في كل الاختبارات، بيجي دور الـ CD. وهون فيه نوعين لازم نميز بينهم:

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

الهدف من الـ CD هو جعل عملية النشر حدث روتيني، ممل، وآمن، بدل ما يكون مغامرة محفوفة بالمخاطر.

رحلتنا من الفوضى إلى الأتمتة: خطوات عملية

طيب يا أبو عمر، حكي جميل، بس كيف بنطبق هالحكي على أرض الواقع؟ خليني أعطيكم خارطة الطريق اللي مشيناها.

الخطوة الأولى: اختيار الأدوات المناسبة

السوق مليان أدوات: Jenkins, GitLab CI/CD, CircleCI, Travis CI, GitHub Actions وغيرها. نصيحتي كالتالي: “ما فيه أداة هي الأحسن بالمطلق، فيه الأداة الأنسب لمشروعك وفريقك”.

إذا كنتوا بتستخدموا GitHub، فالبداية مع GitHub Actions هي أسهل وأذكى خيار لأنه متكامل مع نظامكم. إذا كنتوا على GitLab، استخدموا GitLab CI/CD. ابدأوا بالأداة الأقرب إليكم لتجنب تعقيدات الإعداد الأولية.

الخطوة الثانية: بناء أول خط أنابيب (Pipeline) بسيط (مرحلة الـ CI)

ابدأوا بالأساسيات. هدفنا الأول هو أتمتة البناء والاختبارات. لنفترض عندك تطبيق Node.js، ملف الـ pipeline على GitHub Actions ممكن يكون بالبساطة هاي:

بتعمل ملف جديد في مشروعك اسمه .github/workflows/ci.yml وبتكتب فيه التالي:


# اسم الـ workflow اللي بيظهر في GitHub
name: CI Pipeline

# متى يشتغل هاد الـ workflow؟
# هنا، عند أي عملية push على فرع main أو أي pull request بستهدف main
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

# الوظائف (Jobs) اللي رح تتنفذ
jobs:
  # اسم الوظيفة، ممكن يكون أي اسم
  build-and-test:
    # نوع الجهاز الافتراضي اللي رح يشتغل عليه الكود
    runs-on: ubuntu-latest

    # الخطوات اللي رح تتنفذ بالترتيب
    steps:
      # 1. سحب الكود من المستودع (Repository)
      - name: Checkout code
        uses: actions/checkout@v3

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

      # 3. تنزيل الاعتماديات (Dependencies)
      - name: Install dependencies
        run: npm install

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

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

الخطوة الثالثة: إضافة مرحلة النشر (مرحلة الـ CD)

بعد ما صار عنا ثقة في مرحلة الـ CI، بننتقل للمرحلة اللي بعدها: أتمتة النشر. رح نضيف وظيفة (job) جديدة اسمها deploy بتعتمد على نجاح وظيفة build-and-test.

ملاحظة مهمة: قبل هاي الخطوة، لازم تخزن معلومات الدخول للسيرفر (مثل مفتاح SSH) في الـ Secrets الخاصة بمستودعك على GitHub. إياك ثم إياك تكتبها مباشرة في الملف!

هيك بيصير شكل الملف بعد إضافة مرحلة النشر:


name: CI/CD Pipeline

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '18'
      - run: npm install
      - run: npm test

  # وظيفة النشر الجديدة
  deploy:
    # هاي الوظيفة ما بتشتغل إلا بعد نجاح build-and-test
    needs: build-and-test
    # ما بدنا ننشر إلا لما يكون التغيير على فرع main مباشرة
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to production server
        # هاي action جاهزة بتسهل عملية الـ SSH
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USERNAME }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            # الأوامر اللي كانت تتنفذ يدويًا على السيرفر
            cd /var/www/my-app
            git pull origin main
            npm install --omit=dev
            # استخدام أداة مثل pm2 لإعادة تشغيل التطبيق بدون downtime
            pm2 restart app

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

نصائح من قلب “الورشة”

خلال رحلتنا، تعلمنا كم شغلة “باللحم الحي”، وبدي أشارككم إياها:

  • ابدأ صغيراً (Start Small): لا تحاول أتمتة كل شيء من أول يوم. ابدأ بالـ CI فقط. خلي فريقك يتعود على فكرة إن الاختبارات لازم تنجح دايماً. بعدين ضيف خطوة Linting (فحص تنسيق الكود). بعدين ضيف النشر على بيئة تجريبية (Staging). “شوي شوي” بتوصل.
  • الاختبارات هي العمود الفقري: pipeline بدون اختبارات آلية قوية هو مجرد “أتمتة للفوضى”. استثمروا وقت في كتابة unit tests و integration tests. “الأتمتة بدون اختبارات زي اللي بيسوق سيارة سباق وهو مغمض عينيه”.
  • أسراركم في بئر أمين (Keep Your Secrets Safe): تعلمت بالطريقة الصعبة أهمية الـ Secrets. كل أدوات الـ CI/CD بتوفر مكان آمن لحفظ كلمات المرور ومفاتيح الـ API. استخدموها دايماً.
  • اجعل الفشل واضحاً: إعدادات التنبيهات (Notifications) ضرورية. اربط الـ pipeline مع Slack أو بريد الفريق. لما يفشل build، لازم الكل يعرف فوراً عشان تصير مسؤولية جماعية.
  • الـ Rollback مش عيب: الأتمتة مش بس للنشر، هي كمان للتراجع. فكروا كيف ممكن تعملوا pipeline يعكس عملية النشر ويرجعكم للنسخة المستقرة السابقة بضغطة زر في حالات الطوارئ.

الخلاصة: من نوبات الهلع إلى الثقة بالنفس

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

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

تذكروا يا جماعة، أفضل كود هو الكود اللي بيوصل للمستخدمين وبحل مشاكلهم. والـ CI/CD هو الجسر اللي بيوصل هالكود بأمان وسرعة. يلا، شدّوا حيلكم وخلونا نبني جسور قوية! 💪

أبو عمر

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

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

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

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

آخر المدونات

ادارة الفرق والتنمية البشرية

كان أفضل مهندسينا يرحلون: كيف أنقذ “سلم المسار الوظيفي” شركتنا من جحيم الركود؟

أشارككم قصة حقيقية عن كيفية مواجهتنا لمشكلة "نزيف العقول" في فريقنا الهندسي. نستعرض بالتفصيل كيف قمنا ببناء "سلم مسار وظيفي" (Career Ladder) واضح وشفاف أنقذنا...

1 مايو، 2026 قراءة المزيد
نصائح برمجية

كانت سجلات التغيير لدينا لغزاً: كيف أنقذنا معيار ‘Conventional Commits’ من جحيم ‘git log’ عديم الفائدة؟

أشارككم قصة حقيقية من قلب المعركة البرمجية، كيف انتقلنا من سجلات Git غامضة وفوضوية إلى تاريخ واضح ومنظم باستخدام معيار Conventional Commits. هذه ليست مجرد...

1 مايو، 2026 قراءة المزيد
​معمارية البرمجيات

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

أشارككم قصة حقيقية من قلب المعركة التقنية، عندما كان نظامنا القديم على وشك الانهيار وفشلت محاولات إعادة كتابته. اكتشفوا كيف أنقذنا نمط "التين الخانق" (Strangler...

1 مايو، 2026 قراءة المزيد
ذكاء اصطناعي

من الصندوق الأسود إلى الوضوح: كيف أنقذتنا أدوات SHAP و LIME من جحيم حيرة نماذج الذكاء الاصطناعي

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

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

كان كل فريق يصمم على هواه: كيف أنقذنا ‘نظام التصميم’ من جحيم الفوضى البصرية؟

أشارككم قصة حقيقية من قلب المعركة البرمجية، كيف انتقلنا من فوضى الواجهات البصرية والتطبيقات غير المتناسقة إلى عالم من التناغم والكفاءة بفضل بناء "نظام تصميم"...

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