كانت أنابيبنا تتسرب: كيف أنقذنا ‘البايبلاين كشيفرة’ من جحيم ‘شغال عندي’؟

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

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

أعطينا الضوء الأخضر لزميلنا “سعيد” (اسم مستعار طبعاً) عشان يعمل الـ deployment النهائي على السيرفر. مرت خمس دقايق، عشرة، ربع ساعة… وفجأة، التلفونات والرسائل بلشت تنهال علينا زي المطر: “الموقع واقع!”، “النظام لا يعمل!”، “شو القصة يا شباب؟”.

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

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

ما هو الـ ‘بايبلاين’ أصلاً؟ ولماذا كان ‘يتسرب’؟

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

الـ “بايبلاين” (Pipeline) أو “أنبوب النقل” هو ببساطة هذا الخط التجميعي المؤتمت. هو سلسلة من المراحل اللي بمر فيها الكود تبعك من لحظة ما تكتبه على جهازك حتى يصل للمستخدم النهائي. هذه العملية تُعرف عادةً بـ CI/CD (التكامل المستمر والنشر/التسليم المستمر).

المراحل النموذجية في أي بايبلاين بتكون كالتالي:

  • البناء (Build): تجميع الكود وتحويله لبرنامج قابل للتشغيل.
  • الاختبار (Test): تشغيل اختبارات آلية للتأكد من أن الكود الجديد ما كسر أي شي قديم.
  • النشر (Deploy): أخذ البرنامج الجاهز ووضعه على السيرفرات (سيرفر اختبار، ثم سيرفر الإنتاج).

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

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

الحل السحري: “البايبلاين كشيفرة” (Pipeline as Code – PaC)

بعد ليلة الكارثة تلك، قررنا أن “خلص، بكفي!”. لا يمكن أن نستمر بهذه الطريقة الفوضوية. وهنا كان دخول مفهوم “البايبلاين كشيفرة” (Pipeline as Code) لحياتنا، واللي كان بمثابة طوق النجاة.

تعريف الـ PaC ببساطة

الفكرة بسيطة بشكل عبقري: بدلاً من إعداد البايبلاين عبر واجهات رسومية والنقر على الأزرار وحفظ التكوينات في قاعدة بيانات الأداة (مثل Jenkins)، نقوم بتعريف كل مراحل وخطوات البايبلاين في ملف نصي (شيفرة). هذا الملف يعيش مع الكود المصدري لتطبيقك في نفس مستودع الشيفرة (Code Repository) مثل Git.

هذا الملف هو العقد الموثق الذي يصف بالضبط كيف سيتم بناء واختبار ونشر تطبيقك. أمثلة على هذه الملفات تشمل Jenkinsfile لـ Jenkins، .gitlab-ci.yml لـ GitLab CI، azure-pipelines.yml لـ Azure DevOps، و .github/workflows/main.yml لـ GitHub Actions.

كيف يعمل؟ المبدأ الأساسي

لما تعتمد PaC، العملية بتصير كالتالي:

  1. أنت كمبرمج تكتب الكود تبعك.
  2. تكتب أو تعدّل على ملف البايبلاين (مثلاً .gitlab-ci.yml) لو احتجت تغيير في عملية البناء أو النشر.
  3. ترفع الكود مع ملف البايبلاين إلى Git.
  4. أداة الـ CI/CD (مثل GitLab) بتشوف الملف الجديد، بتقرأه، وبتنفذ المراحل المكتوبة فيه بالحرف الواحد.

البايبلاين لم يعد “شيئًا” غامضًا على سيرفر ما، بل أصبح “ملفًا” واضحًا ومقروءًا ومحفوظًا مع الكود.

فوائد تبني “البايبلاين كشيفرة”: مش بس عشان نريّح راسنا!

الانتقال للـ PaC مش مجرد موضة تقنية، بل هو نقلة نوعية في طريقة عمل الفريق بأكمله. وهذه بعض الفوائد اللي لمسناها بشكل مباشر:

التحكم بالإصدارات (Version Control)

بما أن البايبلاين أصبح مجرد ملف في Git، فهذا يعني أن كل تغيير عليه يتم تتبعه. يمكنك أن ترى من غيّر ماذا ومتى ولماذا. يمكنك الرجوع لإصدار أقدم من البايبلاين بسهولة إذا سبب التغيير الجديد مشاكل. وداعاً للتغييرات “الشبحية”!

التكرار والاتساق (Reproducibility and Consistency)

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

المراجعة والتعاون (Review and Collaboration)

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

الكارثة… والتعافي السريع (Disaster… and quick recovery)

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

أمثلة عملية: خلينا نشوف الكود يا جماعة

الكلام النظري جميل، لكن الكود أبلغ. لنأخذ مثالاً بسيطًا جدًا لملف .gitlab-ci.yml لمشروع Node.js. هذا الملف يصف بايبلاين من ثلاث مراحل.


# .gitlab-ci.yml

# تحديد صورة دوكر التي ستُستخدم لتشغيل المهام
# في هذه الحالة، نستخدم صورة رسمية تحتوي على Node.js إصدار 18
image: node:18

# تعريف المراحل التي سيمر بها البايبلاين بالترتيب
stages:
  - build
  - test
  - deploy

# المهمة الأولى: بناء المشروع
# تنتمي لمرحلة 'build'
build_app:
  stage: build
  script:
    - echo "بدء عملية تثبيت الاعتماديات..."
    - npm install  # تثبيت المكتبات المذكورة في package.json
    - echo "انتهت عملية البناء بنجاح."
  artifacts:
    paths:
      - node_modules/ # حفظ مجلد node_modules للمرحلة التالية

# المهمة الثانية: تشغيل الاختبارات
# تنتمي لمرحلة 'test'
run_tests:
  stage: test
  script:
    - echo "بدء عملية الاختبار..."
    - npm test # تشغيل سكربت الاختبار المحدد في package.json
    - echo "الاختبارات مرت بنجاح."

# المهمة الثالثة: نشر التطبيق
# تنتمي لمرحلة 'deploy'
deploy_to_production:
  stage: deploy
  script:
    - echo "بدء عملية النشر على سيرفر الإنتاج..."
    # هنا تضع سكربت النشر الحقيقي، مثلاً عبر SSH أو أي أداة أخرى
    - ./deploy_script.sh 
  environment:
    name: production
  when: manual # هذه نقطة مهمة: المهمة لن تعمل تلقائياً، بل يجب الضغط على زر التشغيل يدوياً من واجهة GitLab

لاحظوا جمال وبساطة الأمر. كل شيء موثق وواضح في ملف واحد. أي مبرمج جديد ينضم للفريق يمكنه قراءة هذا الملف وفهم دورة حياة المشروع كاملة.

نصائح أبو عمر الذهبية للبدء

إذا تحمست للفكرة وتريد أن تبدأ، اسمح لي أن أقدم لك بعض النصائح من خبرتي المتواضعة:

  • ابدأ صغيراً (Start Small): لا تحاول تحويل كل مشاريعك دفعة واحدة. اختر مشروعًا واحدًا، ربما مشروع جديد أو مشروع صغير، وابدأ بتطبيق PaC عليه. تعلم من أخطائك ثم توسع.
  • اختر الأداة المناسبة (Choose the Right Tool): كل الأدوات (GitLab CI, GitHub Actions, Jenkins, CircleCI) قوية ولها ميزاتها. اختر الأداة الأقرب لنظام عملك الحالي. إذا كنت تستخدم GitLab لإدارة الكود، فمن الطبيعي أن تبدأ بـ GitLab CI.
  • لا تخترع العجلة (Don’t Reinvent the Wheel): معظم الأدوات توفر قوالب جاهزة (templates) لأنواع المشاريع الشائعة (Node.js, Python, Java, etc.). ابدأ من هذه القوالب وعدّل عليها حسب حاجتك.
  • اجعلها قابلة للفشل (Embrace Failure): البايبلاين تبعك سيفشل. كثيرًا. وهذا شيء جيد! كل فشل هو فرصة لتقوية البايبلاين وجعله أكثر صلابة. لا تخف من اللون الأحمر (الذي يعني فشل المهمة)، بل اعتبره صديقك الذي ينبهك للمشاكل مبكرًا.

الخلاصة: من الفوضى إلى الأتمتة المنظمة

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

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

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

أبو عمر

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

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

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

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

آخر المدونات

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

كان مستخدمونا في الطرف الآخر من العالم ينتظرون إلى الأبد: كيف أنقذتنا شبكات توصيل المحتوى (CDN) من جحيم زمن الاستجابة المرتفع؟

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

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

من شبكة مثقوبة إلى حصن منيع: كيف أنقذتنا قواعد البيانات الرسومية من كابوس الاحتيال؟

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

30 مايو، 2026 قراءة المزيد
البنية التحتية وإدارة السيرفرات

ميزانيات الخطأ (Error Budgets): كيف أنهت كابوس مكالمات منتصف الليل وأنقذتنا من الإرهاق؟

كنا غارقين في مكالمات طوارئ ليلية لا تنتهي، فريق منهك والمنتج على المحك. في هذه المقالة، أشارككم قصة كيف أنقذنا مفهوم "ميزانيات الخطأ" (Error Budgets)...

30 مايو، 2026 قراءة المزيد
ادارة الفرق والتنمية البشرية

كانت اجتماعاتنا الفردية استجواباً صامتاً: كيف حولنا الـ 1-on-1 من تقرير حالة ممل إلى محرك لنمو الفريق؟

أشارككم تجربتي كقائد فريق تقني في تحويل الاجتماعات الفردية (1-on-1s) من جلسات استجواب مملة إلى محادثات مثمرة تساهم في بناء الثقة وتطوير الفريق. هذه المقالة...

30 مايو، 2026 قراءة المزيد
اختبارات الاداء والجودة

كانت اختباراتنا تصرخ ‘الذئب’: كيف قضينا على ‘الاختبارات المتقلبة’ (Flaky Tests) واستعدنا الثقة في خطوط الأنابيب؟

في هذه المقالة، أشارككم قصة من أرض المعركة البرمجية، وكيف تغلب فريقي على كابوس "الاختبارات المتقلبة" أو Flaky Tests. سنغوص في أسبابها الخفية، ونتعلم استراتيجيات...

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

كانت أصابعي تصرخ من التكرار: كيف أنقذتني ‘مقتطفات الشفرة’ (Code Snippets) من جحيم كتابة Boilerplate؟

أشارككم قصتي مع التكرار الممل في البرمجة وكيف غيرت "مقتطفات الشفرة" (Code Snippets) طريقة عملي تماماً. دليل عملي من مبرمج فلسطيني لزيادة إنتاجيتك والتخلص من...

30 مايو، 2026 قراءة المزيد
أتمتة العمليات

كانت تبعياتنا قنبلة موقوتة: كيف أنقذنا ‘التحديث الآلي للتبعيات’ من جحيم الثغرات الأمنية المنسية؟

أشارككم قصة حقيقية عن ليلة كادت فيها ثغرة أمنية في إحدى المكتبات المنسية أن تدمر مشروعنا بالكامل. اكتشفوا معنا كيف تحولنا من الفوضى إلى الأمان...

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

كانت شفرتنا هرمًا من الهلاك: كيف أنقذتنا ‘شروط الحماية’ (Guard Clauses) من جحيم الـ if/else المتداخلة؟

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

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

كانت خدماتنا متلاصقة كالغراء: كيف أنقذتنا ‘المعمارية الموجهة بالأحداث’ (EDA) من جحيم الاقتران المحكم؟

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

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