إصداراتنا كانت عالقة: كيف أنقذني ‘النشر المستمر’ (Continuous Deployment) من عنق الزجاجة؟

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

خلوني أحكيلكم قصة صارت معي قبل كم سنة، قصة كانت السبب في تغيير طريقة تفكيرنا في الشغل كلها. كان يوم خميس بعد الظهر، وكنا على وشك ننهي الأسبوع واحنا مبسوطين. فجأة، بيوصلنا بلاغ عن “بَغ” (Bug) خطير في نظام الدفع على موقعنا، كان بيمنع جزء من المستخدمين من إتمام عمليات الشراء. كارثة بمعنى الكلمة!

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

  • موافقة من مدير الفريق.
  • موافقة من فريق ضمان الجودة (QA) بعد ما يختبروه على بيئة الاختبار (Staging).
  • موافقة من مدير قسم العمليات (Operations).
  • وأخيرًا، لازم واحد من فريق العمليات يسهر بالليل عشان يعمل النشر يدويًا “خارج أوقات الذروة”.

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

ما هو “عنق الزجاجة” في عالم البرمجيات؟

عنق الزجاجة، أو الـ Bottleneck، هو بالضبط ما وصفته في القصة. هو أي مرحلة في عملية تطوير ونشر البرمجيات تكون أبطأ بكثير من المراحل الأخرى، مما يؤدي إلى تكدس العمل وتأخيره. في حالتنا، كانت مرحلة “النشر” هي عنق الزجاجة القاتل.

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

المنقذ: التكامل المستمر والنشر المستمر (CI/CD)

الحل لهذه المعضلة يكمن في مبادئ الأتمتة المعروفة بـ CI/CD. دعونا نفصلها ببساطة:

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

هذا هو الأساس. الفكرة ببساطة هي أن كل مبرمج في الفريق يقوم بدمج (merge) الكود الذي يعمل عليه مع الفرع الرئيسي (main branch) في نظام إدارة الشيفرة المصدرية (مثل Git) عدة مرات في اليوم. مع كل عملية دمج، يتم تشغيل عملية مؤتمتة تقوم بالتالي:

  • بناء المشروع (Build): التأكد من أن الكود سليم ويمكن تحويله إلى برنامج قابل للتشغيل.
  • تشغيل الاختبارات (Test): تشغيل مجموعة من الاختبارات المؤتمتة (Unit Tests) للتأكد من أن التغييرات الجديدة لم تكسر أي شيء في الكود الحالي.

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

2. التسليم المستمر (Continuous Delivery) مقابل النشر المستمر (Continuous Deployment)

هنا يحدث بعض اللبس عند الكثيرين، والفرق دقيق لكنه جوهري:

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

كان الانتقال إلى النشر المستمر بمثابة قفزة إيمانية، لكنها كانت مبنية على أساس متين من الاختبارات المؤتمتة والثقة في عمليتنا.

كيف بنينا خط أنابيب النشر المستمر (Deployment Pipeline)؟

الرحلة لم تكن سهلة، ولكنها كانت منهجية. قسمناها إلى خطوات عملية:

الخطوة الأولى: إرساء قواعد التكامل المستمر (CI)

قبل التفكير في النشر التلقائي، كان علينا التأكد من أن أساسنا صلب. هذا يعني:

  1. ثقافة الاختبارات: نشرنا ثقافة “الاختبارات أولاً” (Testing First). لا يُقبل أي كود جديد بدون اختبارات مؤتمتة (Unit Tests) تغطيه. الاختبارات ليست رفاهية، يا جماعة، هي صمام الأمان الأول.
  2. أتمتة البناء والاختبار: استخدمنا أدوات مثل GitHub Actions لإنشاء سير عمل (workflow) بسيط يقوم بتشغيل الاختبارات مع كل `push` على أي فرع في المستودع (Repository).

نصيحة من أبو عمر: لا تستهينوا أبدًا بالاختبارات الوحدوية (Unit Tests). هي أسرع أنواع الاختبارات وأرخصها، وتكتشف 80% من المشاكل في مرحلة مبكرة جدًا.

كمثال بسيط، هذا شكل ملف workflow في GitHub Actions لتشغيل اختبارات لمشروع Node.js:


name: Node.js CI

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Use Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18.x'
    - run: npm ci
    - run: npm test

هذا الملف البسيط كان بداية كل شيء. يضمن أن الكود دائمًا سليم وقابل للاختبار.

الخطوة الثانية: ممر الاختبارات الصارم (The Testing Gauntlet)

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

  • الاختبارات التكاملية (Integration Tests): للتأكد من أن الأجزاء المختلفة من النظام تعمل معًا بشكل صحيح (مثلاً، التطبيق مع قاعدة البيانات).
  • اختبارات الواجهة الأمامية (End-to-End Tests): باستخدام أدوات مثل Cypress أو Playwright، قمنا بمحاكاة سلوك المستخدم على الواجهة الأمامية (الضغط على الأزرار، ملء النماذج) للتأكد من أن تجربة المستخدم لم تتأثر.
  • فحوصات الأمان (Security Scans): أضفنا أدوات تفحص الكود بحثًا عن ثغرات أمنية شائعة.

أي فشل في أي مرحلة من هذه المراحل يوقف عملية النشر فورًا ويرسل تنبيهًا للفريق.

الخطوة الثالثة: القفزة نحو النشر التلقائي الآمن

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

استراتيجية الأزرق-الأخضر (Blue-Green Deployment)

الفكرة عبقرية وبسيطة. يكون لديك بيئتان متطابقتان تمامًا في الإنتاج:

  • البيئة الزرقاء (Blue): هي البيئة الحالية التي يستخدمها كل المستخدمين.
  • البيئة الخضراء (Green): هي بيئة خاملة، نسخة طبق الأصل من الزرقاء.

عندما يكون هناك إصدار جديد، يتم نشره على البيئة الخضراء. بعد النشر، يتم إجراء اختبارات أخيرة عليها وهي معزولة. إذا نجحت كل الاختبارات، يتم تحويل موجه المرور (Load Balancer) ليشير إلى البيئة الخضراء، فتصبح هي البيئة النشطة. البيئة الزرقاء القديمة تبقى جاهزة للعودة إليها فورًا في حال حدوث أي مشكلة. هذا يجعل عملية التراجع (Rollback) شبه فورية!

استراتيجية الكناري (Canary Releases)

هذه استراتيجية أخرى، حيث يتم إطلاق الإصدار الجديد لمجموعة صغيرة جدًا من المستخدمين (مثلاً 1% فقط). نراقب أداء النظام وسلوك هذه الشريحة الصغيرة. إذا كانت الأمور مستقرة ولا توجد مشاكل، نبدأ بزيادة النسبة تدريجيًا (5%، ثم 20%، ثم 50%…) حتى يصل الإصدار الجديد لجميع المستخدمين. هذا يحد من تأثير أي مشكلة محتملة.

في ملف GitHub Actions، يمكن أن يبدو جزء النشر كالتالي (كمثال مفاهيمي):


# ... (بعد خطوات البناء والاختبار) ...

  deploy:
    needs: build # يعتمد على نجاح خطوة البناء والاختبار
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' # انشر فقط عند الدمج على الفرع الرئيسي

    steps:
      - name: Deploy to Production
        uses: some-deploy-action # هنا تستخدم الأداة الخاصة بالنشر (e.g., to AWS, Azure, etc.)
        with:
          strategy: 'canary' # تحديد استراتيجية النشر
          percentage: 10
          # ... other deployment configurations

الثمار التي قطفناها: النتائج كانت مذهلة

بعد تطبيق هذه المنظومة، تغير كل شيء:

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

    سعادة الفريق: اختفى الإحباط وحل محله شعور بالإنجاز والسرعة. “رجعنا نحب الشغل”.

    دورة تغذية راجعة سريعة: أصبحنا نرى تأثير عملنا على المستخدمين بسرعة، مما يمكننا من التعديل والتحسين بشكل مستمر.

الخلاصة ونصيحة أخيرة 💡

يا حبايب، الانتقال إلى “النشر المستمر” ليس مجرد تغيير تقني، بل هو تغيير في الثقافة وطريقة التفكير. إنه يتطلب الثقة في فريقك، والاستثمار بقوة في الاختبارات المؤتمتة، والشجاعة للتخلي عن العمليات اليدوية البطيئة.

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

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

أتمنى لكم كل التوفيق في رحلتكم. 🙏

أبو عمر

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

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

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

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

آخر المدونات

التوسع والأداء العالي والأحمال

طلبات المستخدمين كانت تغرق خوادمنا: كيف أنقذني ‘تحديد معدل الطلبات’ (Rate Limiting) من استنزاف الموارد؟

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

27 مارس، 2026 قراءة المزيد
التكنلوجيا المالية Fintech

بيانات عملائنا كانت سجينة في بنوكهم: كيف حررتها واجهات ‘الخدمات المصرفية المفتوحة’ (Open Banking)؟

في هذا المقال، أشارككم قصة من أرض الواقع عن بناء تطبيق مالي، وكيف أنقذتني واجهات الخدمات المصرفية المفتوحة (Open Banking APIs) من إعادة بناء العجلة...

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

بياناتي كانت تتغير بشكل غامض: كيف أنقذني مبدأ ‘اللامتغيرية’ (Immutability) من كابوس الآثار الجانبية؟

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

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

تحديث النظام القديم كان كابوساً: كيف أنقذني نمط ‘التين الخانق’ (Strangler Fig) من إعادة كتابة كل شيء من الصفر؟

هل تعاني من نظام قديم ومعقد؟ قبل أن تفكر في إعادة كتابته بالكامل، تعرف على نمط 'التين الخانق' الذي أنقذني وفريقي من كابوس حقيقي، وكيف...

26 مارس، 2026 قراءة المزيد
تسويق رقمي

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

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

26 مارس، 2026 قراءة المزيد
الشبكات والـ APIs

واجهاتي البرمجية كانت ترسل جبلاً من البيانات لتعرض اسماً واحداً: كيف أنقذني GraphQL من كابوس الـ Over-fetching؟

أشارككم قصتي مع "الـ Over-fetching" وكيف تسببت واجهات REST API التقليدية في إبطاء تطبيقاتي. اكتشفوا معي كيف كانت لغة GraphQL هي المنقذ الذي غيّر طريقة...

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