كل عملية نشر كانت مغامرة: كيف أنقذتني خطوط أنابيب CI/CD من كوابيس ‘النشر اليدوي’؟

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

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

بعد ما خلصت التعديل على جهازي واختبرته مية مرة وتأكدت إنه شغال “تمام التمام”، إجت اللحظة الحاسمة: لحظة رفع الكود على السيرفر الحقيقي (Production Server). وقتها ما كان في إشي اسمه CI/CD في قاموسي، كانت العملية كلها “شغل إيد”.

فتحت الـ Terminal، وعملت SSH على السيرفر، وكتبت الباسوورد اللي حافظها عن غيب. دخلت على مجلد المشروع، وكتبت الأمر الشهير git pull origin main. بعدها، شغّلت أمر بناء المشروع npm run build، وبعد ما خلص، عملت إعادة تشغيل للسيرفر باستخدام pm2 restart app. كل خطوة كنت أعملها وقلبي يدق، كأني بنزع فتيل قنبلة. وبعد ما ضغطت Enter على آخر أمر، فتحت الموقع… وإذ به شاشة بيضاء ورسالة خطأ “502 Bad Gateway”.

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

ومن هنا بدأت رحلتي مع عالم الـ DevOps وأتمتة العمليات، وتحديداً الـ CI/CD، اللي حوّلت عملية النشر من مغامرة محفوفة بالمخاطر إلى عملية روتينية ومملة… وهذا أفضل إشي ممكن يصير لأي مبرمج.

ما هي كوابيس “النشر اليدوي”؟

القصة اللي حكيتها مش حالة فردية، هي سيناريو متكرر بيعيشه آلاف المبرمجين. عملية النشر اليدوي، بالرغم من بساطتها الظاهرية، إلا إنها مليئة بالثغرات والمشاكل، وأهمها:

الأخطاء البشرية واردة… بل حتمية!

نحن بشر، والبشر يخطئون. ممكن تنسى تشغل أمر، أو تكتب أمر بشكل خاطئ، أو تنسخ ملف في المكان الغلط، أو زي ما صار معي، تنسى تضيف متغير بيئة. كل خطأ صغير من هدول ممكن يؤدي لكارثة على السيرفر ويوقف الخدمة بالكامل.

بيئات عمل غير متطابقة

جملة “شغال على جهازي!” أو “It works on my machine!” هي أشهر كذبة في عالم البرمجة. غالباً، بيئة التطوير على جهازك بتختلف عن بيئة الاختبار (Staging) وعن بيئة الإنتاج (Production). ممكن إصدار Node.js يكون مختلف، أو في مكتبة معينة مثبتة على جهازك ومش موجودة على السيرفر. هاي الاختلافات بتسبب مشاكل غير متوقعة وقت النشر.

بطء العملية وضياع الوقت الثمين

تخيل معي كم دقيقة (أو ساعة) بتقضيها في كل مرة بتعمل فيها نشر يدوي: فتح الـ terminal، تسجيل الدخول، سحب التحديثات، بناء المشروع، إعادة تشغيل السيرفر، والتأكد من إن كل شي شغال. هذا الوقت هو وقت ضايع كان ممكن تستغله في كتابة كود جديد أو حل مشاكل أهم.

الخوف من النشر (Deployment Anxiety)

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

المنقذ: خطوط أنابيب CI/CD (The Savior)

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

الاسم هو اختصار لمصطلحين:

ما هو الـ CI (التكامل المستمر – Continuous Integration)؟

الفكرة بسيطة: بدل ما كل مبرمج في الفريق يشتغل على نسخته من الكود لأسابيع وبعدين يحاول يدمج شغله مع شغل باقي الفريق (وهو ما يسبب كوارث دمج أو merge conflicts)، التكامل المستمر بشجع المبرمجين على دمج تغييراتهم بشكل متكرر ويومي في مستودع الكود الرئيسي (main/master branch).

والسحر هنا: مع كل عملية دمج، بيشتغل “روبوت” تلقائياً بيقوم بالآتي:

  1. يسحب آخر نسخة من الكود.
  2. يقوم ببناء المشروع (Build).
  3. يشغل كل الاختبارات الآلية (Automated Tests) للتأكد من إن التغيير الجديد ما كسر أي إشي في الكود القديم.

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

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

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

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

الهدف النهائي من الـ CI/CD هو جعل عمليات النشر حدثاً روتينياً، متوقعاً، وآمناً، لدرجة إنك ممكن تنشر تحديثاتك 10 مرات في اليوم بدون ما تحس بأي قلق.

لنطبق عملياً: بناء أول خط أنابيب (Pipeline) باستخدام GitHub Actions

الكلام النظري جميل، بس خلينا نشوف كيف ممكن نطبق هذا الحكي بشكل عملي. رح نستخدم GitHub Actions لأنه أداة مجانية (للمشاريع العامة والكثير من الدقائق للمشاريع الخاصة)، وسهلة، ومدمجة مباشرة مع GitHub.

السيناريو: نشر تطبيق Node.js بسيط

لنفترض أن لدينا تطبيق ويب بسيط مكتوب بـ Node.js و Express، وكل ما نريده هو أتمتة عملية اختباره ونشره على سيرفر Ubuntu كلما قمنا بعمل push على الفرع الرئيسي main.

الخطوة الأولى: تجهيز المشروع

تأكد أن مشروعك يحتوي على ملف package.json الذي يحدد الاعتماديات (dependencies) والسكربتات اللازمة، مثل:


{
  "name": "my-awesome-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "test": "echo "Error: no test specified" && exit 1"
  },
  "dependencies": {
    "express": "^4.18.2"
  }
}

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

الخطوة الثانية: كتابة ملف الـ Workflow

الـ GitHub Actions تدار بواسطة ملفات مكتوبة بصيغة YAML. في مشروعك، أنشئ مجلداً جديداً باسم .github وبداخله مجلد آخر باسم workflows. داخل هذا المجلد، أنشئ ملفاً جديداً وليكن اسمه deploy.yml.

الآن، الصق الكود التالي في ملف deploy.yml:


# اسم الـ Workflow الذي سيظهر في تبويب Actions في GitHub
name: Node.js CI/CD

# متى سيتم تشغيل هذا الـ Workflow؟
on:
  # نريد تشغيله عند كل عملية push على الفرع main
  push:
    branches: [ "main" ]

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

    # الخطوات (Steps) التي سيتم تنفيذها بالترتيب
    steps:
      # الخطوة 1: سحب الكود من المستودع إلى الجهاز الافتراضي
      - name: Checkout repository
        uses: actions/checkout@v3

      # الخطوة 2: إعداد بيئة Node.js بالإصدار المطلوب
      - name: Use Node.js 18.x
        uses: actions/setup-node@v3
        with:
          node-version: "18.x"
          cache: 'npm' # لتسريع عمليات التثبيت المستقبلية

      # الخطوة 3: تثبيت الاعتماديات الخاصة بالمشروع
      - name: Install dependencies
        run: npm install

      # الخطوة 4: تشغيل الاختبارات الآلية (مهم جداً!)
      - name: Run tests
        run: npm test # سيفشل الـ pipeline هنا إذا فشلت الاختبارات

      # الخطوة 5: النشر على السيرفر باستخدام SSH
      # هذه الخطوة تتطلب إعداد SSH Secrets في GitHub
      - name: Deploy to server
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USERNAME }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          port: ${{ secrets.SSH_PORT }}
          script: |
            cd /var/www/my-awesome-app
            git pull origin main
            npm install --only=production
            pm2 restart my-awesome-app

شرح الأسرار (Secrets) وكيفية استخدامها

لاحظ في خطوة النشر أننا استخدمنا ${{ secrets.SSH_HOST }}. هذه طريقة آمنة لاستخدام المعلومات الحساسة (مثل كلمات المرور، مفاتيح SSH، أو مفاتيح API) بدون كتابتها مباشرة في الكود.

ممنوع منعاً باتاً كتابة أي معلومات حساسة مباشرة في ملف الـ YAML!

لإضافة هذه الأسرار:

  1. اذهب إلى مستودعك على GitHub.
  2. اضغط على تبويب Settings.
  3. في القائمة الجانبية، اذهب إلى Secrets and variables ثم Actions.
  4. اضغط على زر New repository secret.
  5. أضف الأسرار التالية واحدًا تلو الآخر:
    • SSH_HOST: عنوان IP الخاص بسيرفرك.
    • SSH_USERNAME: اسم المستخدم الذي تستخدمه للدخول للسيرفر (مثلاً: ubuntu).
    • SSH_PRIVATE_KEY: المفتاح الخاص (Private Key) الذي يسمح بالدخول للسيرفر بدون كلمة مرور.
    • SSH_PORT: منفذ SSH (غالباً 22).

بمجرد إضافة هذا الملف وعمل push له على فرع main، اذهب إلى تبويب Actions في مشروعك على GitHub وراقب السحر وهو يحدث! سترى الـ Pipeline وهو يعمل خطوة بخطوة، وفي النهاية (إذا سارت الأمور على ما يرام) سيتم نشر تطبيقك تلقائياً.

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

بعد سنوات من التعامل مع خطوط الأنابيب هذه، تعلمت بعض الدروس التي أحب أن أشاركها معكم:

  • ابدأ صغيراً وبسيطاً: لا تحاول أتمتة كل شيء من أول يوم. ابدأ بخط أنابيب يقوم فقط بالبناء (Build) وتشغيل الاختبارات (Test). عندما تتقن هذه المرحلة، أضف خطوة النشر على بيئة تجريبية، ثم انتقل إلى الإنتاج.
  • الاختبارات هي شبكة الأمان: أكررها مرة أخرى لأهميتها. جودة الـ Pipeline من جودة اختباراتك. استثمر وقتاً في كتابة اختبارات جيدة (Unit, Integration, End-to-End) لتكون واثقاً من أن الكود الذي يتم نشره سليم.
  • اجعل الفشل واضحاً وسريعاً (Fail Fast): يجب أن يتوقف الـ Pipeline فوراً عند أول خطأ. لا تسمح له بالاستمرار إذا فشلت الاختبارات مثلاً. هذا يوفر الوقت ويجعل اكتشاف الأخطاء أسهل.
  • استخدم الإشعارات (Notifications): قم بإعداد إشعارات على Slack أو Microsoft Teams أو حتى البريد الإلكتر الإلكتروني لإعلامك بنجاح أو فشل كل عملية. هذا يبقيك على اطلاع دائم بحالة مشروعك.

الخلاصة: من كابوس إلى عملية روتينية مملة (وهذا شيء رائع!) 😌

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

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

بالتوفيق يا جماعة!

أبو عمر

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

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

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

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

آخر المدونات

التكنلوجيا المالية Fintech

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

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

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

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

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

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

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

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

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

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

أتذكر جيدًا ذلك اليوم الذي انهار فيه نظامنا بالكامل بسبب تحديث بسيط في خدمة الإشعارات. هذه هي قصة رحلتي من معمارية "كُبّة الصوف" المترابطة بإحكام...

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

ذاكرة التخزين المؤقت كانت بلا فائدة: كيف أنقذتني خوارزمية ‘الأقل استخدامًا مؤخرًا’ (LRU) من بطء قاعدة البيانات؟

أشارككم قصة حقيقية عن مشروع كاد أن يفشل بسبب بطء قاعدة البيانات رغم استخدامي للتخزين المؤقت. اكتشفوا كيف كانت خوارزمية بسيطة مثل LRU هي طوق...

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

ألواني الزاهية كانت فخاً: كيف أنقذني ‘تباين الألوان’ من تصميم واجهات كارثية؟

أشارككم قصة حقيقية من بداياتي، عندما كاد حبي للألوان الزاهية أن يدمر مشروعاً كاملاً. اكتشفوا معي كيف تعلمت بالطريقة الصعبة أهمية تباين الألوان (Color Contrast)...

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