خط الأنابيب الأول ليس عن الأدوات، بل عن الاتساق

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

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

الحل الحقيقي ليس أداة. إنه عملية قابلة للتكرار.

ابدأ بمسار واحد

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

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

إليك تمثيل مرئي لهذا المسار الذهبي:

flowchart TD A[بناء القطعة] --> B[تشغيل اختبارات الوحدة] B --> C[نشر إلى بيئة التطوير] C --> D[تشغيل اختبارات التكامل] D --> E[نشر إلى بيئة الاختبار] E --> F[نشر إلى الإنتاج]
  • بناء القطعة (Build artifact)
  • تشغيل اختبارات الوحدة (Run unit tests)
  • النشر إلى بيئة التطوير (Deploy to a development environment)
  • تشغيل اختبارات التكامل (Run integration tests)
  • النشر إلى بيئة الاختبار (Deploy to staging)
  • النشر إلى الإنتاج (Deploy to production)

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

إليك كيف يبدو هذا المسار الذهبي كسير عمل GitHub Actions بسيط:

name: Golden Path
on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Build artifact"

  unit-tests:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - run: echo "Run unit tests"

  deploy-dev:
    needs: unit-tests
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploy to development"

  integration-tests:
    needs: deploy-dev
    runs-on: ubuntu-latest
    steps:
      - run: echo "Run integration tests"

  deploy-staging:
    needs: integration-tests
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploy to staging"

  deploy-production:
    needs: deploy-staging
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploy to production"

هذا هو مسارك الذهبي. لا يجب أن يكون مثاليًا. فقط يجب أن يكون موجودًا. بمجرد وجوده، يمكنك تحسينه. لكن إذا لم يكن لديك مسار واحد، فليس لديك خط أساس للتحسين منه.

الاتساق هو الهدف، وليس السرعة

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

خط الأنابيب ليس أسرع على المدى القصير. إنه أكثر قابلية للتنبؤ. والقابلية للتنبؤ هي ما يسمح لك بالتحرك بسرعة لاحقًا.

إليك ما يمنحك إياه الاتساق:

  • كل تغييرة تُبنى بنفس الطريقة. لا مزيد من "إنه يعمل على جهازي".
  • كل تغييرة تُختبر بنفس الطريقة. لا مزيد من مجموعات الاختبارات التي تم تخطيها.
  • كل تغييرة تذهب إلى نفس البيئات. لا مزيد من "لقد نسيت النشر إلى بيئة الاختبار".

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

أضف بوابات المخاطر، وليس مطبات السرعة

خط الأنابيب المتسق جيد. خط الأنابيب الذي يعرف متى يتوقف أفضل.

بوابة المخاطر (Risk Gate) هي نقطة في خط الأنابيب يمكنها التوقف أو الإيقاف بناءً على شرط. الغرض ليس إبطاء الأمور. الغرض هو اكتشاف المشاكل قبل أن تصل إلى المستخدمين.

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

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

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

بوابات المخاطر ليست جدرانًا

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

يجب تقييم بوابات المخاطر بانتظام. اطرح هذه الأسئلة:

  • هل تكتشف هذه البوابة مشاكل حقيقية؟
  • هل توقف خط الأنابيب بسبب إنذارات كاذبة؟
  • هل يثق بها الفريق؟

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

عندما يعمل مسار واحد، قم بتوسيعه

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

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

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

قائمة مراجعة عملية لأول خط أنابيب موحد لك

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

الخلاصة

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