إنشاء خط أنابيب (Pipeline) يرفض الأكواد التي تفشل في الاختبارات

دقائق القراءة: 6

إنشاء خط أنابيب (Pipeline) يرفض الأكواد التي تفشل في الاختبارات

في البيئات الاحترافية، لا يكفي أن يعمل الكود على جهاز المطور، بل يجب أن يثبت صلاحيته تلقائياً قبل دمجه أو نشره. هنا تظهر قيمة Pipeline مصمم كحارس جودة يمنع مرور أي تعديل يفشل في Unit Tests أو فحوصات البناء الأساسية.

هذا النمط ليس رفاهية تنظيمية، بل هو أحد أهم تطبيقات Continuous Integration التي تقلل من أخطاء الدمج، وتحمي الفروع الحساسة، وتمنع انتقال العيوب إلى المراحل اللاحقة. وإذا كنت تريد أساساً نظرياً أوسع، فراجع مقال ما هو الـ CI/CD؟ ولماذا نؤتمت عمليات اختبار ونشر الأكواد؟.

الفكرة الجوهرية بسيطة: أي عملية Push أو Pull Request تشغّل سلسلة مهام آلية، وإذا فشل الاختبار يتوقف المسار فوراً وتُرفض عملية الدمج. بهذه الطريقة يتحول التحقق من الجودة من مجهود بشري متذبذب إلى قاعدة هندسية قابلة للقياس والفرض.

لماذا يجب أن يرفض الخط الكود الفاشل تلقائياً؟

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

الرفض التلقائي يحقق عدة فوائد عملية:

  • منع إدخال تغييرات تكسر التطبيق أو إحدى وحداته الداخلية.
  • تقليل زمن مراجعة الكود لأن المراجع يركز على المنطق لا على التحقق اليدوي الأساسي.
  • رفع موثوقية الفرع الرئيسي مثل main أو master.
  • تسريع دورات التسليم لأن الفشل يظهر مبكراً بدلاً من اكتشافه بعد النشر.

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

المعمارية النموذجية لخط الرفض التلقائي

أي Pipeline فعال يجب أن يكون حتمياً وقابلاً لإعادة التشغيل بنفس النتائج قدر الإمكان. لهذا السبب تُشغَّل الوظائف داخل بيئة معزولة ونظيفة، سواء عبر آلة افتراضية مؤقتة أو حاوية مبنية مسبقاً.

المكونات الأساسية

  • مستودع Git يستقبل التعديلات.
  • محرك أتمتة مثل GitHub Actions أو Jenkins.
  • مرحلة تثبيت الاعتماديات Dependencies.
  • مرحلة فحص أو بناء Build.
  • مرحلة اختبارات تكون هي بوابة الرفض أو القبول.

إذا كنت بدأت للتو في بناء مسارات الأتمتة، فمقال مقدمة في GitHub Actions: كتابة أول مسار عمل (Workflow) يوضح أساسيات التشغيل من الصفر.

تنفيذ الرفض التلقائي باستخدام GitHub Actions

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

name: test-gate

on:
  push:
    branches:
      - main
      - develop
  pull_request:
    branches:
      - main
      - develop

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm

      - name: Install dependencies
        run: npm ci

      - name: Run unit tests
        run: npm test

      - name: Build application
        run: npm run build

هذا الملف يكفي وظيفياً لجعل الفشل في npm test يوقف المهمة بالكامل. النتيجة العملية أن حالة الفحص تظهر كـ failed ولا يمكن تمرير الدمج إذا كانت سياسات الحماية مفعلة.

ولفهم بناء أوامر YAML بصورة أدق، يفيدك مقال بناء أوامر YAML لأتمتة تشغيل السكربتات التلقائية عند كل Push.

كيف يحدث الرفض فعلياً؟

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

  1. أنشئ مسار العمل داخل المستودع.
  2. شغّل المسار مرة واحدة ليتعرف النظام على اسم المهمة.
  3. اذهب إلى إعدادات حماية الفرع.
  4. فعّل شرط اجتياز الفحوصات المطلوبة قبل الدمج.
  5. اختر المهمة المسماة test أو الاسم الذي حددته.

مثال مكافئ باستخدام Jenkins

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

pipeline {
  agent any

  stages {
    stage('Install') {
      steps {
        sh 'npm ci'
      }
    }

    stage('Test') {
      steps {
        sh 'npm test'
      }
    }

    stage('Build') {
      steps {
        sh 'npm run build'
      }
    }
  }
}

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

استخدام الحاويات لضمان ثبات بيئة الاختبار

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

إذا كانت بيئة التطبيق معقدة أو تتضمن خدمات متعددة، فبناء صورة موحدة أو استخدام ملف docker-compose.yml يجعل الاختبارات أقرب إلى الواقع. وهذا ينسجم مع مقال ما هو Docker Compose؟ ولماذا نحتاجه لتشغيل المشاريع المعقدة؟.

docker compose up --build --abort-on-container-exit --exit-code-from app

هذا النمط مفيد عندما يعتمد التطبيق على قاعدة بيانات أو خدمة خارجية داخل بيئة اختبار محلية معزولة.

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

أفضل الممارسات لرفع موثوقية بوابة الاختبارات

1) اجعل الفحوصات سريعة وحاسمة

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

2) لا تعتمد على جهاز المطور فقط

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

3) أضف تقارير واضحة للفشل

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

4) اربط الجودة بالتدفق الجماعي

خط الرفض التلقائي يعمل بأفضل صورة عندما يكون نموذج الفروع واضحاً. لذلك يفيد الرجوع إلى استراتيجيات العمل الجماعي: نظام GitHub Flow وكيف تعمل الشركات الكبرى؟ لبناء مسار تطوير لا يسمح للفوضى بالتسلل إلى الفرع الرئيسي.

متى لا يكفي رفض الاختبارات وحده؟

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

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

الخلاصة

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

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

10 comments

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *