البناء: المرحلة التي يتحول فيها الكود إلى شيء قابل للتشغيل

لقد قمت للتو بدفع أحدث تغييراتك. تلتقطها pipeline، وتستخرج الكود، وتجهز البيئة. ماذا الآن؟ الخطوة التالية هي التأكد من أن الكود يمكنه بالفعل العمل في مكان ما. هذه هي مرحلة البناء.

كثير من الأشخاص الجدد في pipelines يعتقدون أن البناء هو مجرد ترجمة (compilation). إذا كنت تكتب بلغة Java، فإنك تترجم إلى bytecode. إذا كنت تكتب بلغة Go، فإنك تترجم إلى binary. هذا جزء منه، لكن البناء أوسع من ذلك. كل نوع من العمل في توصيل البرمجيات يحتاج إلى خطوة بناء، حتى لو لم يكن الناتج ملفًا ثنائيًا.

ماذا يعني البناء فعليًا

الكود كما يكتبه المطورون عادة لا يكون جاهزًا للتشغيل على خادم. يحتاج إلى تحويل إلى شيء يمكن للنظام المستهدف تنفيذه. بالنسبة لتطبيق Java، يعني ذلك ترجمة الكود المصدري إلى bytecode وتجميعه في ملف JAR أو WAR. بالنسبة لتطبيق Node.js، قد يعني البناء تشغيل bundler أو minifier أو transpiler ليكون الكود جاهزًا للإنتاج. بالنسبة لتطبيق Go، يعني البناء الترجمة إلى binary مستقل.

لكن البناء ليس فقط لكود التطبيق. قواعد البيانات تحتاج أيضًا إلى خطوة بناء. كود SQL، والإجراءات المخزنة، ومخططات قواعد البيانات تحتاج إلى ترجمة أو تحقق. الناتج ليس binary. إنه مجموعة من ملفات الترحيل (migration files) الجاهزة للتشغيل ضد قاعدة بيانات مستهدفة بالترتيب الصحيح. البناء لقواعد البيانات ينتج عادةً أوامر SQL مُتحقق منها وتم فحصها بحثًا عن أخطاء بناء الجملة وترتيب التبعيات.

إليك كيف قد تبدو مرحلة البناء في تكوين pipeline لنوعين شائعين من التطبيقات:

build-nodejs:
  stage: build
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/

build-go:
  stage: build
  script:
    - go build -o app .
  artifacts:
    paths:
      - app

البنية التحتية تمر أيضًا بعملية بناء. ملفات Terraform، وقوالب CloudFormation، وplaybooks الخاصة بـ Ansible تحتاج إلى فحص بناء الجملة، والتحقق، وأحيانًا الترجمة إلى تمثيل أكثر قابلية للنشر. قد يكون ناتج بناء البنية التحتية ملف تكوين مُتحقق منه، أو قالبًا تم فحصه، أو حتى صورة آلة مبنية مسبقًا.

الخيط المشترك هو هذا: البناء يحول المصدر إلى شيء يمكن التحقق منه ثم استخدامه بواسطة المراحل اللاحقة.

الرسم البياني أدناه يلخص كيف يحول البناء أنواعًا مختلفة من الكود المصدري إلى أرتيفاكتات قابلة للتشغيل:

flowchart TD A[Source Code] --> B{Build Stage} B --> C[Application: Binary / Package / Container Image] B --> D[Database: Verified Migration Scripts] B --> E[Infrastructure: Validated Config / Plan] C --> F[Artifact with Metadata] D --> F E --> F F --> G[Next Stage: Test & Scan]

ما ينتجه البناء الجيد

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

يتضمن ناتج البناء المنظم جيدًا ما يلي:

  • أرتيفاكت جاهز للاستخدام. قد يكون binary، أو حزمة، أو صورة حاوية، أو ملف ترحيل.
  • سجل للإصدار والـ commit الذي أطلق هذا البناء.
  • بيانات وصفية مثل التجزئة (hash) أو المجموع الاختباري (checksum) لتتمكن من التحقق من أن الأرتيفاكت لم يتغير أثناء النقل.
  • حالة نجاح أو فشل واضحة.

بدون هذه العناصر، لا يمكنك الوثوق بما تسلمه pipeline إلى المرحلة التالية.

البناء يجب أن يكون قابلاً للتكرار

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

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

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

البناء هو البوابة الأولى

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

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

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

البناء لأنواع مختلفة من العمل

دعنا ننظر إلى كيفية عمل البناء لكل مجال رئيسي.

التطبيقات. بالنسبة للغات المترجمة، يعني البناء الترجمة والتعبئة. بالنسبة للغات المفسرة، قد يعني البناء حل التبعيات، وتجميع الأصول، والتجميع في حزمة. التطبيقات المحتواة (Containerized) تضيف خطوة إضافية: بناء صورة الحاوية نفسها يصبح جزءًا من مرحلة البناء.

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

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

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

قائمة تحقق سريعة للبناء

قبل أن تعتبر مرحلة البناء منتهية، تحقق من هذه النقاط:

  • البناء ينتج أرتيفاكت قابل للتحقق (binary، صورة، ملف ترحيل، تكوين)
  • البناء حتمي: نفس الكود، نفس النتيجة، في كل مرة
  • البناء يعمل في أقل من خمس دقائق
  • البناء يفشل بسرعة ويعطي رسائل خطأ واضحة
  • ناتج البناء يتضمن الإصدار، والـ commit، وبيانات المجموع الاختباري
  • التبعيات الخارجية مقفلة على إصدارات محددة
  • بيئة البناء نظيفة ومتسقة عبر عمليات التشغيل

ماذا بعد

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

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