اذهب إلى المحتوى

البحث في الموقع

المحتوى عن 'ci/cd'.

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المحتوى


التصنيفات

  • الإدارة والقيادة
  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • السلوك التنظيمي في المؤسسات
  • عالم الأعمال
  • التجارة والتجارة الإلكترونية
  • نصائح وإرشادات
  • مقالات ريادة أعمال عامة

التصنيفات

  • مقالات برمجة عامة
  • مقالات برمجة متقدمة
  • PHP
    • Laravel
    • ووردبريس
  • جافاسكربت
    • لغة TypeScript
    • Node.js
    • React
    • Vue.js
    • Angular
    • jQuery
    • Cordova
  • HTML
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • لغة C#‎
    • ‎.NET
    • منصة Xamarin
  • لغة C++‎
  • لغة C
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • لغة Rust
  • برمجة أندرويد
  • لغة R
  • الذكاء الاصطناعي
  • صناعة الألعاب
  • سير العمل
    • Git
  • الأنظمة والأنظمة المدمجة

التصنيفات

  • تصميم تجربة المستخدم UX
  • تصميم واجهة المستخدم UI
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب GIMP
    • كريتا Krita
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • نصائح وإرشادات
  • مقالات تصميم عامة

التصنيفات

  • مقالات DevOps عامة
  • خوادم
    • الويب HTTP
    • البريد الإلكتروني
    • قواعد البيانات
    • DNS
    • Samba
  • الحوسبة السحابية
    • Docker
  • إدارة الإعدادات والنشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
    • ريدهات (Red Hat)
  • خواديم ويندوز
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • شبكات
    • سيسكو (Cisco)

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • استسراع النمو
  • المبيعات
  • تجارب ونصائح
  • مبادئ علم التسويق

التصنيفات

  • مقالات عمل حر عامة
  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • العمل الحر المهني
    • العمل بالترجمة
    • العمل كمساعد افتراضي
    • العمل بكتابة المحتوى

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
    • بريستاشوب
    • أوبن كارت
    • دروبال
  • الترجمة بمساعدة الحاسوب
    • omegaT
    • memoQ
    • Trados
    • Memsource
  • برامج تخطيط موارد المؤسسات ERP
    • تطبيقات أودو odoo
  • أنظمة تشغيل الحواسيب والهواتف
    • ويندوز
    • لينكس
  • مقالات عامة

التصنيفات

  • آخر التحديثات

أسئلة وأجوبة

  • الأقسام
    • أسئلة البرمجة
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات

التصنيفات

  • كتب ريادة الأعمال
  • كتب العمل الحر
  • كتب تسويق ومبيعات
  • كتب برمجة
  • كتب تصميم
  • كتب DevOps

ابحث في

ابحث عن


تاريخ الإنشاء

  • بداية

    نهاية


آخر تحديث

  • بداية

    نهاية


رشح النتائج حسب

تاريخ الانضمام

  • بداية

    نهاية


المجموعة


النبذة الشخصية

تم العثور على 6 نتائج

  1. يُعَد نهج التكامل والتسليم والنشر المستمر -المعروف باسم CI/CD- جزءًا لا يتجزأ من التطوير الحديث الذي يهدف إلى تقليل الأخطاء أثناء التكامل والنشر مع زيادة سرعة إنجاز المشروع الرقمي، حيث يمثل هذا النهج فلسفة ومجموعة من الممارسات التي يعزّزها استخدام أدوات قوية تؤكد على الاختبار المؤتمت في كل مرحلة من مراحل خط إنتاج Pipeline البرمجيات، وبالتالي يمكنك من خلال دمج هذه الأفكار ضمن ممارساتك تقليلُ الوقت المطلوب لتكامل التغييرات لإصدارٍ ما واختبار كل تغيير بدقة قبل نقله إلى مرحلة الإنتاج. يتمتع نهج CI/CD بالعديد من الفوائد، ولكن يتطلب التقديم الناجح لهذا النهج في أغلب الأحيان قدرًا كبيرًا من الأمور التي يجب أن تضعها في الحسبان، إذ يمكن أن يكون تحديد كيفية استخدام الأدوات والتغييرات التي قد تحتاجها في عملياتك أمرًا صعبًا بدون اتباع طريقة التجربة والخطأ، ولكن ستكون جميع عمليات التقديم مختلفة، لذا يمكن أن يساعدك الالتزام بأفضل الممارسات على تجنب المشاكل الشائعة والتحسن بصورة أسرع. سنرشدك في هذا المقال لتعلم مبادئ كيفية تقديم وصيانة منظومة CI/CD لخدمة احتياجات مؤسستك بأفضل طريقة، حيث سنوضح عددًا من الممارسات التي ستساعدك على تحسين فعالية خدمة منظومة CI/CD. لا تتردد في القراءة بالترتيب الموجود أو يمكنك الانتقال إلى المجالات التي تهمك مباشرةً. حافظ على سرعة خطوط الإنتاج تساعد خطوط إنتاج CI/CD في الاهتمام بالتغييرات ابتداءً من دورات الاختبار المؤتمت ثم بيئات التحضير Staging Environments وأخيرًا مرحلة الإنتاج، فكلما كانت خطوط الإنتاج تشمل مرحلة الاختبار، زادت ثقتك في أن التغييرات لن تحدث آثارًا جانبية غير متوقعة في مرحلة النشر والتسليم، ولكن يجب أن يمر كل تغيير بهذه العملية، لذا يُعَد الحفاظ على خطوط إنتاجك سريعة وموثوقة أمرًا مهمًا للغاية. يمكن أن يكون من الصعب الموازنة بين هذين المطلبين، فهناك بعض الخطوات المباشرة التي يمكنك اتخاذها لتحسين السرعة مثل توسيع بنية CI/CD التحتية وتحسين مرحلة الاختبارات، ولكن قد تضطر مع مرور الوقت إلى اتخاذ قرارات حاسمة بشأن القيمة النسبية للاختبارات المختلفة ومرحلة أو ترتيب إجرائها. لذا يُعَد تقليص مجموعة اختباراتك -من خلال إزالة الاختبارات ذات القيمة المنخفضة أو التي لا تدل على أمور جوهرية- أذكى طريقة في بعض الأحيان للحفاظ على السرعة التي تتطلبها خطوط الإنتاج المُستخدَمة بكثرة. تأكد عند اتخاذ هذه القرارات المهمة من فهم وتوثيق المقايضات التي تطبّقها، وتشاور مع أعضاء الفريق وأصحاب المصلحة لمواءمة افتراضات الفريق حول مسؤولية مجموعة الاختبار وما يجب التركيز عليه. دورة إدارة تطوير المنتجات احترف إدارة تطوير المنتجات الرقمية بدءًا من التخطيط وتحليل السوق وحتى إطلاق منتج مميز وناجح اشترك الآن عزل وتأمين بيئة منظومة CI/CD تمثل منظومة CI/CD إحدى أكثر البنى التحتية أهمية التي يجب حمايتها من وجهة نظر الأمان التشغيلي، إذ يجب تأمينها بما أن لديها وصولًا كاملًا إلى شيفرتك البرمجية الأساسية وثبوتياتك لنشرها في بيئات مختلفة، ويجب عزلها وقفلها قدر الإمكان نظرًا لقيمتها العالية بوصفها هدفًا للمهاجمين. يجب نشر أنظمة CI/CD على الشبكات الداخلية المحمية دون أن تكون مكشوفة لأطراف خارجية، لذلك يوصَى بإعداد شبكات VPN أو أي تقنية أخرى للتحكم في الوصول إلى الشبكة للتأكد من أن المشغّلين الموثقين فقط هم من يمكنهم الوصول إلى نظامك. يمكن أن تحتاج منظومة CI/CD خاصتك إلى الوصول إلى عدة شبكات مختلفة لنشر الشيفرة البرمجية في بيئات مختلفة اعتمادًا على مدى تعقيد مخطط شبكتك، فإن لم تُؤمَّن أو تُعزَل بصورة صحيحة، فقد يتمكّن المهاجمون الذين يمكنهم الوصول إلى بيئة واحدة من استخدام تقنية قفز الجزيرة Island Hop -وهي تقنية تُستخدَم لتوسيع الوصول من خلال الاستفادة من قواعد الشبكات الداخلية الأكثر تساهلًا- للوصول إلى بيئات أخرى عبر نقاط ضعف خوادم CI/CD. تعتمد استراتيجيات العزل والأمان المطلوبة بصورة كبيرة على مخطط الشبكة وبنيتها التحتية ومتطلبات الإدارة والتطوير. يجب أن تضع في بالك أن أنظمة CI/CD هي أهداف ذات قيمة عالية وتتمتع في كثير من الحالات بدرجة كبيرة من الوصول إلى أنظمتك الأساسية الأخرى، وبالتالي ستساعد حماية الوصول الخارجي إلى الخوادم والتحكم في أنواع الوصول الداخلي المسموح به في تقليل مخاطر تعرض منظومة CI/CD للخطر. جعل خط إنتاج CI/CD الطريقة الوحيدة للنشر في بيئة الإنتاج تساعد الأدوات في أغلب الأحيان في فرض أفضل الممارسات للاختبار والنشر، مما يمكّن منظومة CI/CD من تحسين ممارسات التطوير وجودة الشيفرة البرمجية، إذ تتطلب ترقية الشيفرة البرمجية عبر خطوط إنتاج CI/CD أن يثبت كل تغيير التزامه بالمعايير والإجراءات المُوثّقة الخاصة بمؤسستك. تظهر حالات الفشل في خط إنتاج CI/CD مباشرةً ويتوقف تقدم الإصدار المتأثر إلى مراحل لاحقة من الدورة، إذ تحمي هذه الآلية البيئات الأكثر أهمية من الشيفرة البرمجية غير الموثوق بها. يمكن تحقيق هذه المزايا من خلال التأكد من أن كل تغيير في بيئة إنتاجك يمر عبر خط إنتاجك، إذ يجب أن يكون خط إنتاج CI/CD هو الآلية الوحيدة التي تدخل من خلالها الشيفرة البرمجية إلى بيئة الإنتاج. يمكن أن يحدث ذلك تلقائيًا في نهاية الاختبار الناجح مع ممارسات النشر المستمر، أو من خلال الترقية اليدوية للتغييرات المُختبَرة التي تعتمدها وتتيحها منظومة CI/CD. تبدأ الفِرق باستمرار في استخدام خطوط إنتاجهم للنشر، ولكنها تجري استثناءات عند حدوث مشاكل مع وجود ضغط لحلها بسرعة. يجب التخفيف من وقت التوقف والمشاكل الأخرى في أسرع وقت ممكن، ولكن يجب أن نفهم أن منظومة CI/CD هي أداة جيدة لضمان ألّا تدخل تغييراتك أخطاءً أخرى أو تسبّب تعطل النظام. سيؤدي وضع إصلاحٍ ما لشيفرتك عبر خط الإنتاج (أو استخدام منظومة CI/CD للتراجع) إلى منع نشر الإصدار التالي للتطبيق من إزالة الإصلاحات العاجلة التي طبقتها يدويًا على البيئة الإنتاجية، إذ يحمي خط الإنتاج صلاحية عمليات النشر بغض النظر عمّا إذا كان ذلك إصدارًا منتظمًا أو مخططًا له أو إصلاحًا سريعًا لحل مشكلة جارية. يُعَد هذا الاستخدام لمنظومة CI/CD سببًا آخر للعمل على إبقاء خط إنتاجك سريعًا. الحفاظ على التطابق مع البيئة الإنتاجية ما أمكن ترفع خطوط إنتاج CI/CD التغييرات من خلال سلسلة من مجموعات الاختبار وبيئات النشر، إذ تُنشَر التغييرات التي تجتاز متطلبات مرحلةٍ تلقائيًا أو توضَع في طابور للنشر اليدوي في بيئات أكثر تقييدًا، حيث تهدف المراحل المبكرة إلى إثبات أنه من المفيد مواصلة الاختبار ودفع التغييرات لتصبح مناسبة للبيئة الإنتاجية. يساعد أن تكون بيئة الاختبار مطابقة قدر الإمكان للبيئة الإنتاجية أن نضمن في المراحل اللاحقة أن تظهِر الاختبارات بدقة كيفية تصرّف التغيير في البيئة الإنتاجية. يمكن أن تسمح الاختلافات الكبيرة بين بيئة التحضير staging وبيئة الإنتاج production أن تظهر مشاكل لم يعثر عليها في مرحلة الاختبار، وكلما زادت الاختلافات بين بيئتك الإنتاجية وبيئة الاختبار، قلَّ قياس اختباراتك لكيفية أداء الشيفرة البرمجية عند إصدارها. يُتوقَّع وجود بعض الاختلافات بين بيئتي التحضير والإنتاج، ولكن يجب إبقاؤها قابلة للإدارة والتأكد من فهمها جيدًا، إذ تستخدم بعض المؤسسات عمليات النشر الأزرق والأخضر Blue-green Deployments لمبادلة حركة مرور الإنتاج بين بيئتين متطابقتين تقريبًا تتناوبان بين كونهما بيئتي تحضير وإنتاج، وتضمنت الاستراتيجيات الأقل حِدةً نشر الضبط والبنية التحتية نفسها من الإنتاج إلى بيئة التحضير، ولكن على نطاق أقل. قد تختلف عناصرٌ مثل نقاط نهاية الشبكة بين بيئاتك، ولكن يمكن أن يساعد تحديد المعاملات لهذا النوع من البيانات المتغيرة في التأكد من أن الشيفرة البرمجية متناسقة وأن الاختلافات البيئية مُحدَّدة جيدًا. البناء مرة واحدة فقط وترقية النتائج عبر خط الإنتاج الهدف الأساسي لخط إنتاج التكامل المستمر والتسليم المستمر CI/CD هو بناء الثقة في تغييراتك وتقليل فرصة حدوث تأثير غير متوقع، حيث ناقشنا أهمية الحفاظ على التطابق بين البيئات، ولكن يجب ضمان مزيد من الاهتمام في جميع المكونات، فإن تطلّب برنامجك خطوة بناء أو حزمٍ أو تجميع، فيجب تنفيذ هذه الخطوة مرة واحدة فقط وإعادة استخدام الخرج الناتج على طول خط الإنتاج بأكمله. يساعد هذا المقال في منع المشاكل التي تنشأ عند تصريف البرمجيات أو حزمها عدة مرات، مما يسمح بمنع تعارضات ضئيلة في المنتجات الثانوية الناتجة، إذ يمكن أن يعني بناء البرمجيات بصورة منفصلة في كل مرحلة جديدة أن الاختبارات في البيئات السابقة لم تستهدف البرمجيات نفسها الذي ستُنشَر لاحقًا، مما يؤدي إلى إبطال النتائج. يمكن تجنب هذه المشكلة من خلال أن تتضمن أنظمة CI عملية بناء بوصفها خطوة أولى في خط الإنتاج الذي ينشئ البرمجية ويحزمها في بيئة نظيفة، ويجب إصدار المنتج الثانوي الناتج وتحميله إلى نظام تخزين المنتجات الثانوية لتسحبها المراحل اللاحقة من خط الإنتاج، مما يضمن عدم تغيير البناء أثناء تقدمه عبر النظام. إجراء أسرع الاختبارات في وقت مبكر يُعَد إبقاء خط الإنتاج سريعًا بالكامل هدفًا عامًا ورائعًا، ولكن ستكون أجزاءٌ من مجموعة اختبارك حتمًا أسرع من غيرها. تعمل منظومة CI/CD بوصفها ممرًا لجميع التغييرات التي تدخل نظامك، لذا يُعَد اكتشاف حالات الفشل في أقرب وقت ممكن أمرًا مهمًا لتقليل الموارد المُخصَّصة لعمليات البناء التي تسبب مشاكلًا، ويمكن تحقيق ذلك من خلال تحديد أولويات الاختبارات الأسرع وإجرائها أولًا. احفظ الاختبارات المعقدة التي تستغرق وقتًا طويلًا حتى بعد التحقق من صحة البناء باستخدام اختبارات صغيرة سريعة التشغيل. تحتوي هذه الإستراتيجية على عدد من الفوائد التي يمكن أن تساعد في الحفاظ على صحة عملية CI/CD، وتشجعك على فهم تأثير أداء الاختبارات الفردية، وتسمح لك بإكمال معظم اختباراتك مبكرًا، وتزيد من احتمالية الفشل السريع، مما يعني أنه يمكن التراجع عن التغييرات التي تسبب مشاكلًا أو إصلاحها قبل وقف عمل أعضاء الفريق الآخرين. يعني تحديدُ أولويات الاختبار تشغيلَ اختبارات الوحدة لمشروعك أولًا، لأن هذه الاختبارات تميل إلى أن تكون سريعة ومعزولة وتركز على المكونات، وتمثّل اختبارات التكامل بعد ذلك المستوى التالي من التعقيد والسرعة، وتليها اختبارات على مستوى النظام، وأخيرًا اختبارات القبول التي تتطلب غالبًا مستوًى معينًا من التفاعل البشري. تقليل التفريع في نظام التحكم في الإصدارات يتمثل أحد المبادئ الرئيسية لمنظومة CI/CD في دمج التغييرات في المستودع المشترك الأساسي مبكرًا وفي مرات متعددة، مما يساعد في تجنب مشاكل التكامل المتعبة باستمرار عندما يحاول العديد من المطورين دمج تغييرات كبيرة ومتباينة ومتضاربة في الفرع الرئيسي للمستودع استعدادًا للنشر، إذ تُضبَط أنظمة CI/CD لمراقبة واختبار التغييرات الملتزمة بفرع واحد فقط أو عدة فروع. يمكن الاستفادة من المزايا التي يوفرها التكامل المستمر CI من خلال تحديد عدد الفروع ونطاقها في مستودعك، حيث تشير معظم التطبيقات إلى أن المطورين يلتزمون مباشرة بالفرع الرئيسي main أو master أو يدمجون التغييرات من الفروع المحلية مرةً واحدةً على الأقل يوميًا. تحتوي الفروع التي لا تتعقّبها منظومة CI/CD على شيفرة برمجية غير مُختبَرة بغض النظر عن أهميتها أو وظيفتها، حيث يساعد التقليل من التفريع لتشجيع التكامل المبكر بين شيفرات المطورين المختلفة على الاستفادة من نقاط القوة في النظام، ويمنع المطورين من إبطال المزايا التي يوفرها. إجراء الاختبارات محليًا قبل الالتزام بخط إنتاج CI/CD يجب تشجيع المطورين على إجراء بعض الاختبارات محليًا قبل رفعها على المستودع المشترك فيما يتعلق بنقطة اكتشاف حالات الفشل مبكرًا، مما يجعل من الممكن اكتشاف بعض التغييرات التي تسبب مشاكلًا قبل وقف أعضاء الفريق الآخرين. ليس محتملًا أن تكون بيئة المطور المحلية قادرة على تشغيل مجموعة الاختبارات بأكملها في بيئة شبيهة ببيئة الإنتاج، ولكن تمنح هذه الخطوة الإضافية الأفراد مزيدًا من الثقة بأن التغييرات التي يجرونها تجتاز الاختبارات الأساسية وتستحق محاولة الاندماج مع الشيفرة البرمجية الأساسية الأكبر. يمكن التأكد من أن المطورين يمكنهم الاختبار بفعالية من تلقاء أنفسهم من خلال أن تكون مجموعة اختباراتك قابلة للتشغيل باستخدام أمر واحد يمكن تشغيله من أيّ بيئة، إذ يجب أن تستخدم منظومة CI/CD الأمر نفسه الذي يستخدمه المطورون على أجهزتهم المحلية لبدء الاختبارات على الشيفرة البرمجية المضافة في المستودع، ويمكن تنسيق ذلك في أغلب الأحيان من خلال توفير سكربت bash أو أداة makefile لأتمتة تشغيل أدوات الاختبار بطريقة تكرارية ويمكن التنبؤ بها. إجراء الاختبارات في بيئات مؤقتة عندما يكون ذلك ممكنًا يكون من الجيد في أغلب الأحيان استخدام بيئات اختبار نظيفة ومؤقتة عندما يكون ذلك ممكنًا للمساعدة في ضمان إجراء الاختبارات بالطريقة نفسها في مراحل مختلفة، وهذا يعني تشغيل الاختبارات ضمن حاويات Containers لتجريد الاختلافات بين الأنظمة المضيفة ولتوفير واجهة برمجة تطبيقات معيارية لربط المكونات مع بعضها البعض بمقاييس مختلفة. تعمل الحاويات بأدنى قد من المعلومات المُحتفظة minimal state لذا لا تطّلع عمليات التشغيل اللاحقة لمجموعة الاختبارات على الآثارَ الجانبية أو حالات الاختبارات المحفوظة التي يمكن أن تؤدي إلى إفساد النتائج. هناك فائدة أخرى لبيئات الاختبار الموضوعة ضمن حاويات، وهي قابلية نقل بنية اختبارك التحتية، إذ يمتلك المطورون باستخدام الحاويات وقتًا أسهل لتكرار الضبط الذي سيُستخدَم لاحقًا في خط الإنتاج دون الحاجة إلى إعداد البنية التحتية يدويًا وصيانتها أو التضحية بدقة أداء البيئة. يمكن إنشاء الحاويات بسهولة عند الحاجة ثم تدميرها، لذا يمكن للمستخدمين تقديم تنازلات أقل فيما يتعلق بدقة بيئة اختبارهم عند إجراء الاختبارات المحلية. يقيد استخدام الحاويات في بعض الجوانب بيئة التنفيذ للمساعدة في تقليل الاختلافات بين مراحل خطوط الإنتاج. الخلاصة سيكون كل تقديم لمنظومة CI/CD مختلفًا عن الآخر، ولكن سيساعدك اتباع بعض المبادئ الأساسية التي وضّحناها في هذا المقال على تجنب بعض العقبات الشائعة وتعزيز ممارسات الاختبار والتطوير، وسيساعد مزيج من العملية والأدوات والعادات في جعل تغييرات التطوير أكثر نجاحًا وتأثيرًا كما هو الحال مع معظم جوانب منهج التكامل المستمر والتسليم المستمر. ترجمة -وبتصرُّف- للمقال An Introduction to CI/CD Best Practices لصاحبه Justin Ellingwood. اقرأ أيضًا استخدام GitHub Actions لتحقيق التكامل المستمر والنشر المستمر التوسع أكثر في نهج التكامل والتسليم المستمر إعداد التكامل المستمر والنشر المستمر باستخدام الخدمتين CircleCI وCoveralls
  2. ينبغي أن يبقى الفرع الرئيسي دائمًا في المنطقة الخضراء، ويعني ذلك تنفيذ كل خطوات بناء خط الإنتاج بنجاح، إذ يجب أن يُبنى المشروع بنجاح، وأن تُنفَّذ الاختبارات دون أخطاء، ولا يجب أن يعترض المدقق على أي شيء. ما أهمية هذا الأمر؟ من المرجح أنك ستنشر شيفرتك إلى العالم الخارجي من الفرع الرئيسي تحديدًا، وأي إخفاق في هذا الفرع سيعني أنّ الميزات الجديدة لن تُنشر حتى تُحل المشكلة؛ فقد تكتشف أحيانًا ثغرات في نسخة الإنتاج لم يلتقطها خط الإنتاج لمنظومة التكامل المستمر CI/CD، وفي حالات كهذه، سترغب في التراجع إلى النسخة السابقة بطريقة آمنة. كيف ستُبقي فرعك الرئيسي في المنطقة الخضراء إذًا؟ تحاشى دفع أية تغييرات إلى الفرع الرئيسي مباشرةً، بل ادفع شيفرتك إلى فرع آخر يمثّل أحدث نسخة ممكنة للفرع الرئيسي، وعندما ترى أن هذا الفرع جاهزٌ للدمج مع الرئيسي، أنشئ طلب سحب Pull Request -أو اختصارًا PR- على غيت هب GitHub. العمل مع طلبات السحب تمثل طلبات السحب جزءًا جوهريًا من عملية التعاون في تطوير أي مشروع برمجي يُنفَّذه مساهمَين على الأقل، فعندما تُجري أية تعديلات على مشروعك، ستختبرها على جهازك أولًا، ثم تعتمد هذه التغييرات وتدفعها إلى مستودع على الإنترنت -وهو غيت هب GitHub في حالتنا-، ثم تقدم طلب سحب لكي يراجع أحدٌ ما هذه التغييرات قبل أن تُدمج مع الفرع الرئيسي. هناك عدة أسباب تدفعنا لاستخدام طلبات السحب، كما أنّ مراجعة الشيفرة من قبل شخص آخر على الأقل فكرةٌ جيدةٌ دائمًا. قد تتواجد بعض الثغرات حتى في شيفرة المطورين الخبراء، وهذا مشابهٌ لمشكلة الرؤية النفقية tunnel، إذ لا يستطيع المصاب بها سوى رؤية ما أمامه مباشرة وكأنه ينظر من خلال نفق. يمتلك المراجع منظورًا مختلفًا، فقد يقدم وجهة نظر مختلفة. سيكون هناك مطورٌ واحد على الأقل على دراية بالتغيرات التي أجريتها بعد قراءتها. ستسمح لك طلبات السحب أن تُنفِّذ تلقائيًا كل المهام في خط الإنتاج لمنظومة CI قبل أن تصل الشيفرة إلى الفرع الرئيسي، وستزودك GitHub Actions بآلية لتنفيذ طلبات السحب. يمكنك تهيئة مستودع GitHub بطريقة تمنع دمج الشيفرة المرتبطة بطلب سحب إلى أن يُوافق عليها. لتقديم طلب سحب جديد، افتح فرعك في GitHub بالضغط على الزر الأخضر "Compare & pull request" في الأعلى، وسيظهر لك نموذج لتعبئته بوصفٍ لطلب السحب الذي تقدمه. تقدم لك واجهة طلبات السحب في GitHub إمكانية وصف الطلب ومناقشته، حيث تَظهر لك في الأسفل جميع علامات التحقق من منظومة CI (وهي في حالتنا كل فعل من أفعال GitHub Actions التي نستخدمها) التي هُيِّئت للعمل عند كل طلب سحب وحالة هذه العلامات. وما نهدف إليه فعلًا هو لوحة خضراء. يمكنك النقر على تفاصيل "Details" كل علامة تحقق للاطلاع عليها وتشغيل السجلات. تُنفَّذ جميع مخططات العمل التي واجهناها حتى الآن عند دفع الشيفرة إلى الفرع الرئيسي، ولجعلها تعمل عند كل طلب سحب، لا بدّ من تحديث الجزء المسؤول عن مسببات triggers إقلاع المخطط. سنستخدم المسبب "pull_request" للفرع الرئيسي ونربط هذا المسبب بالحدثين "opened"و "synchronize"؛ ويعني هذا مبدئيًا أن المخطط سيُنفَّذ عندما يُقدَّم طلب سحب إلى الفرع الرئيسي، أو عندما يُحدّث. لنغيّر إذًا الأحداث التي تسبب تشغيل مخطط العمل على النحو التالي: on: push: branches: - master pull_request: branches: [master] types: [opened, synchronize] سنمنع قريبًا دفع الشيفرة مباشرةً إلى الفرع الرئيسي، لكننا سننفذ حاليًا مخطط العمل لكل عمليات دفع الشيفرة المباشر إلى الفرع الرئيسي. التمرينان 11.13 - 11.14 يعمل مخطط العمل على النحو المطلوب للحفاظ على نوعية جيدة لشيفرتنا، لكن طالما أنه يُقلع عند دفع الشيفرة إلى الفرع الرئيسي، فسيلتقط الأخطاء متأخرًا. 11.13: طلب سحب حَدِّث مسببات إقلاع مخطط العمل كما اقترحنا سابقًا ليعمل عند تقديم طلب سحب جديد إلى الفرع الرئيسي. أنشئ فرعًا جديدًا وادفع بشيفرتك إليه، ثم افتح طلب سحب إلى الفرع الرئيسي. إذا لم تكن قد تعاملت مع الفروع سابقًا اطلع على المقالات التالية: مقدمة عن التفريع Branching في Git إدارة التفريعات (branches) في Git واستخدامها لتخطيط سير العمل إعادة تأسيس تفريعات طلب السحب وتحديثه في git تنبيه: تأكد عندما تفتح طلب سحب جديد أنك اخترت مستودعك الخاص واجهةً أساسية، إذ سيكون الاختيار افتراضيًا للمستودع الأصلي ولا يجب أن تفعل هذا: سترى في النافذة "Conversation" ضمن واجهة فتح طلب سحب آخر عملية (أو عمليات) دفع للشيفرة، كما سترى الحالة الصفراء لعلامات التحقق الذي يجري تنفيذه: ينبغي أن تكون العلامات باللون الأخضر بعد أن تنتهي عمليات التحقق. تأكد من نجاح كل اختبارات التحقق، ولا تدمج فرعك الآن، فهناك نقاط ينبغي تحسينها في خط الإنتاج. 11.14: تشغيل خطوة النشر للفرع الرئيسي فقط كل شيء يبدو على ما يرام، لكن هناك مشكلةٌ حقيقية في مخطط العمل الحالي، إذ ستُنفَّذ جميع الخطوات بما فيها خطوة النشر عندما نفتح طلب سحب، وبالتأكيد لا نريد حدوث هذا الأمر. ولحسن الحظ، هناك حلٌ بسيط لهذه المشكلة، إذ يمكننا استخدام العبارة الشرطية if في خطوة النشر لكي تضمن عدم تنفيذ هذه الخطوة إن لم تُدمج الشيفرة أو تُدفع إلى الفرع الرئيسي. يتضمن سياق context شتى أنواع المعلومات حول الشيفرة التي ينفذها مخطط العمل. ستجد المعلومات المتعلقة بالموضوع في GitHub context، إذ يمثل الحقل event_name اسم الحدث الذي يسبب تنفيذ المخطط. عندما يُدمج طلب سحب، سيظهر اسم الحدث على أنه "push"، وهو نفسه الحدث الذي يقع عندما تُدفع الشيفرة إلى المستودع، لذلك سنحصل على السلوك المطلوب بإضافة العبارة الشرطية التالية إلى خطوة النشر: if: ${{ github.event_name == 'push' }} ادفع بشيفرة إضافية إلى فرعك، وتأكد من عدم تنفيذ خطوة النشر. ادمج بعد ذلك فرعك مع الفرع الرئيسي وتأكد من حدوث خطوة النشر. إدارة إصدار نسخ البرمجيات الغاية الرئيسية من تحديد الإصدار هي التعريف الفريد للبرمجية التي تعمل والشيفرة المتعلقة بها. يشكّل ترتيب الإصدارات أيضًا جزءًا مهمًا من المعلومات، فلو احتوى الإصدار الحالي لبرنامج ما، على سبيل المثال وظيفةً حيويةً معطلة، سيلزمنا تحديد النسخة السابقة المستقرة من البرنامج لكي نتمكن من التراجع إليها. إدارة الإصدار بطريقة Semantic وبطريقة Hash تُدعى الطريقة التي يُدار بها إصدار برنامج في بعض الأحيان باستراتيجية إدارة الإصدار Versioning strategy. سنطلّع ونوازن استراتيجيتين في هذا المجال، تدعى الأولى الإدارة الدلالية لنُسخ البرمجيات Semantic، إذ يُكتب الإصدار بالشكل التالي: {major}.{minor}.{patch}. فلو كان إصدار نسخة من البرنامج 1.2.3، سيكون 1 هو رقم الإصدار الرئيسي الجذري major و 2 رقم الإصدار الثانوي (البسيط) minor و 3 هو رقم الإصدار الترميمي (الترقيع) patch. وعمومًا، فأية تغييرات تهدف لمعالجة الوظيفة المخفقة في إصدار دون المساس بالطريقة التي يعمل بها التطبيق من الخارج ستكون تغييرات ترميمية؛ أما التغييرات التي تؤدي إلى تغييرات بسيطة في الوظيفة (كما تبدو من الخارج) فستكون تغييرات ثانوية، وندعو تلك التغيرات التي ستؤثر كليًا على التطبيق (أو تغيير وظائفه بصورةٍ كبيرة) بالتغييرات الرئيسية، وقد يختلف تعريف هذه المصطلحات من مشروع لآخر. تتبع على سبيل المثال مكتبات npm ترميز semantic، ففي وقت كتابة هذه السطر (الثالث من آذار 2022)، يُعد الإصدار 17.0.2 هو الأحدث للمكتبة React إذ أن رقم الإصدار الرئيسي هو 17 والثانوي 0 والترميمي 1. أما الإصدار بترميز Hash (أو الترميز SHA) فهو مختلفٌ تمامًا، فرقم الإصدار هو سلسلة نصية عشوائية مشتقة من محتويات المستودع والتغيرات التي اعتمدت فيه. يُنفّذ ذلك في git تلقائيًا مثل رمز Hash معتمد وفريد لأي مجموعة من التغييرات. يستخدم الإصدار برمز غالبًا في الحالات المؤتمتة، فعملية نقل رمز Hash مكون من 32 محرف للتأكد من نشر كل شيء على النحو الصحيح عمليةٌ مضنية وتولّد الكثير من الأخطاء. إلى ماذا يشير الإصدار؟ تحديد الشيفرة الموجودة في كل إصدار أمرٌ مهمٌ جدًا، ويختلف أسلوبي الترميز السابقين في طريقة فعل ذلك؛ فالعملية في Hash (على الأقل في غيت هب GitHub) بسيطة ببساطة البحث عن تغييرات معتمدة للشيفرة commit لها رمز Hash معرّف ومحدد، إذ سيمنحنا ذلك إمكانية معرفة الشيفرة التي نُشرت في كل إصدار. سيتعقد الوضع قليلُا في semantic، فهناك ثلاث طرق لمقاربة الموضوع: الأولى تتعلق بالشيفرة نفسها، والثانية تتعلق بالمستودع أو البيانات الوصفية له، والثالثة تتعلق بأشياء خارج المستودع كليًا. طالما أننا لن نتطرق إلى المقاربة الثالثة (لأنها متشعبة مثل حجر الأرنب)، فستلاحظ أن العملية بسيطة أيضًا وكأنها جدول بيانات يربط بين الإصدار والشيفرة المعتمدة التي يدل عليها. تتلخص المقاربة المتعلقة بالشيفرة برقم إصدار النسخة في ملف، بينما تعتمد مقاربة المستودع وبياناته الوصفية على الوسوم tags أو في حالة GitHub على الإصدارات، إذ يشير الوسم أو الإصدار في هذه المقاربة إلى شيفرة مُعتمدة هي نفسها الموجودة في الإصدار. ترتيب إصدارات النسخ من السهل في semantic ترتيب الإصدارات حتى لو كانت مختلفة (رئيسي، ثانوي، ترميمي)، فسيأتي الإصدار 1.3.7 قبل 2.0.0 والذي سيأتي قبل 2.1.5 وهذا الأخير سيكون قبل 2.2.0. لكننا سنحتاج إلى قائمة بالإصدارت أو الوسوم ( يؤمنها مدير حزم GitHub بصورةٍ ملائمة) لمعرفة الإصدار الأخير، فمن الأسهل الاطلاع على هذه القائمة ومناقشتها، أي من الأسهل أن نقول أننا سنتراجع إلى الإصدار 3.2.4 بدلًا من التعامل بأنفسنا مع رموز hash التي تشير إلى رقم الإصدار. وطبعًا لا نعني إطلاقًا أنّ رموز hash غير ملائمة؛ فلو عرفت أي شيفرة معتمدة سببت مشكلة بعينها، فمن السهل البحث من خلال تاريخ عمليات GitHub والحصول على رموز hash للإصدار السابق؛ لكن لو كانت لديك سلسلتين من رموز Hash على النحو التالي مثلًا: d052aa41edfb4a7671c974c5901f4abe1c2db071 12c6f6738a18154cb1cef7cf0607a681f72eaff3 فلن تستطيع التمييز أيهما قبل الأخرى، وستحتاج إلى مساعدة إضافية مثل سجل عمل GitHub لكشف الترتيب الصحيح. الموازنة بين أسلوبي إدارة الإصدار لقد لمسنا بالمناقشة السابقة بعض إيجابيات وسلبيات كل أسلوب، لكن من الأفضل التطرق إلى مجال استعمال كل منهما. يعمل أسلوب semantic جيدًا عندما يكون لرقم الإصدار أهميةً خاصة أو عندما تكون هناك حاجة للبحث عنه. فكر مثلًا بمكتبات جافا سكربت JavaScript التي تستخدمها؛ فلو كنت تستخدم الإصدار 3.4.6 من مكتبة محددة وظهر تحديث لها يحمل الرقم 3.4.8، فيمكنك أن تأمل بأن انتقالك إلى الإصدار الأحدث سيكون آمنًا؛ لكن لو حمل الإصدار الجديد الرقم 4.0.1 فلن تضمن انتقالًا آمنًا إليه. يُناسب hash الحالات التي تُبنى فيها الشيفرة داخل أدوات برمجية artifact (مثل الملفات الثنائية القابلة للتنفيذ أو قوالب منصة Docker) قابلة بحد ذاتها للرفع أو التخزين، فإذا تطلبت اختباراتك على سبيل المثال بناء حزمتك داخل أداة برمجية، ثم رفعها إلى الخادم واختبارها، فمن الملائم عندها استخدام أسلوب Hash في تحديد الإصدار لأنه سيمنع وقوع الحوادث. تخيل على سبيل المثال أنك تعمل على الإصدار 3.2.2 وفشل أحد الاختبارات، أصلحت بعد ذلك الخلل ودفعت بشيفرتك إلى مستودعك، لكن طالما أنك تعمل ضمن مستودعك فلن تستطيع تحديث رقم الإصدار. لن يتغير اسم الأداة البرمجية دون تحديد إصدار hash. وإن كان هناك خطأ في رفع الأداة البرمجية، فقد يُنفَّذ الاختبار على الأداة الأقدم (طالما أنها لا تزال موجودة وبنفس الاسم). بينما لو أُعطيت الأداة رقم إصدار بأسلوب hash، ينبغي أن يتغير رقم الإصدار عند كل محاولة لدفع شيفرة معتمدة، ويعني هذا أنه في حال أخفق رفع الأداة، سيظهر خطأ لأن الأداة التي ستُنفَّذ عليها الاختبارات غير موجودة. يُعد ظهور الخطأ عندما يحدث شيء ما أفضل غالبًا من مشكلة تهملها منظومة CI بصمت. أفضل ما في الأسلوبين يمكن أن نستشف من المقارنة السابقة أن استخدام أسلوب semantic مناسب لإصدار برمجيات، بينما استخدام أسلوب hash أكثر منطقية أثناء نشر البرمجيات ولن يسبب هذا الأمر تعارضًا بالضرورة. فكر في ذلك على النحو التالي: تتلخص إدارة الإصدارات بأنها تقنية تشير إلى كمية معتمدة من الشيفرة وتعطيها اسمًا فليكن 3.5.5 لن يمنع ذلك طبعًا من إعطاء الشيفرة نفسها رمز hash. هناك أمر ما، فقد ذكرنا في بداية هذا القسم أنه علينا معرفة ما يحدث تمامًا في شيفرتنا، فعلينا أن نكون واثقين مثلًا بأننا اختبرنا الشيفرة التي نريد نشرها. سيعقد وجود أسلوبين متوازيين لإدارة الإصدار (أو تسميته) الأمور قليلًا. فعندما يكون هناك مشروع يستخدم نسخًا من أداة برمجية بحيث يُدار إصدار هذه النسخ بأسلوب hash أثناء اختبارها، يمكننا دائمًا تعقب نتيجة خطوات البناء والتدقيق والاختبار، وبالتالي سيعلم المطورون حالة هذه النسخ. ويحدث ذلك آليًا وبصورةٍ واضحة بالنسبة للمطور، فليس على المطور الاهتمام بما تفعله منظومة CI في الخفاء من حيث استخدام ترميز hash لتسمية النسخة واختبارها. عندما يدمج المطور شيفرته ضمن الفرع الرئيسي، تتولى منظومة CI الأمر من جديد، إذ ستبني هذه المرة وتختبر كل الشيفرة ومن ثم تمنحها رقم إصدار بأسلوب semantic، وتربط هذا الرقم بآخر شيفرة معتمدة ومختبرة وتحمل وسم git. سيكون البرنامج الذي سنصدره في الحالة السابقة مُختبرًا لأن منظومة CI ستتأكد أنّ الاختبارات قد نجحت على الشيفرة الموسومة بوسم git المحدد، وليس خطأً أن نقول أن المشروع سيستخدم أسلوب semantic في إدارة الإصدار ويتجاهل ببساطة فكرة أن منظومة CI ستختبر الفروع الخاصة بكل مطور أو طلبات السحب الخاصة بكل منهم بأسماء مبنية على أسلوب hash في إدارة الإصدار. نقول ذلك لأن النسخة التي تعنينا (التي سنصدرها) ستُمنح رقم إصدار semantic. التمرينان 11.15 - 11.16 لنوسّع مخطط العمل الذي نبنيه لكي يزيد تلقائيًا رقم الإصدار عندما تجري الموافقة على طلب سحب وتنفيذ عملية الدمج ضمن الفرع الرئيسي وأن يوسم النسخة المصّدرة برقم الإصدار. سنستخدم anothrNick/github-tag-action وهو فعل GitHub Actions مفتوح المصدر طوره أحدهم. 11.15: إضافة رقم إصدار سنوّسع مخطط العمل بإضافة خطوة واحدة: - name: Bump version and push tag uses: anothrNick/github-tag-action@1.36.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} سنمرر متغير البيئة environment variable التالي secrets.GITHUB_TOKEN إلى الفعل، وطالما أنّ مصدر الفعل طرف ثالث، سنحتاج إلى شهادة استيثاق token في مستودعك. يمكن الاطلاع أكثر عن الاستيثاق في توثيق GitHub. يمكن أن نمرر عدة متحولات بيئة إلى الفعل anothrNick/github-tag-action. تعدّل هذه المتغيرات الطريقة التي يُعرِّف بها الفعل الإصدارات. يمكنك الاطلاع على تفاصيل أكثر ضمن ملف README الخاص بالفعل على GitHub واستخدام ما يناسبك. وكما سترى في التوثيق سيزداد الرقم الثانوي لرقم الإصدار تلقائيًا minor bump. عدّل التهيئة في الشيفرة السابقة لكي يكون هناك زيادةٌ تلقائية في رقم الترميم patch bump لرقم الإصدار، أي سيزداد الرقم الأخير تلقائيًا. تذكر أننا نريد فقط زيادة رقم الإصدار عندما تطرأ تغييرات على الفرع الرئيسي. لذلك أضف العبارة الشرطية "if" لمنع زيادة رقم الإصدار عند فتح طلب سحب كما فعلنا في التمرين 11.14. أكمل مخطط العمل وحاول تجربته، ولا تضفه مثل خطوة إضافية فقط، وإنما أجري إعداده على أنه عمل منفصل يعتمد على العمل المهتم بتدقيق وكشف الأخطاء والفحص والنشر. أجرِ التغييرات التالية على تعريف مخطط العمل: name: Deployment pipeline on: push: branches: - master pull_request: branches: [master] types: [opened, synchronize] jobs: simple_deployment_pipeline: runs-on: ubuntu-20.04 steps: // steps here tag_release: needs: [simple_deployment_pipeline] runs-on: ubuntu-20.04 steps: // steps here تُنفَّذ أعمال مخطط العمل على التوازي كما ذكرنا سابقًا، لكن طالما أننا نريد إجراء التدقيق والاختبار والنشر أولاً، سنحتاج لضبط اعتمادية tag_release بحيث تنتظر عملًا آخر ليُنفّذ أولًا نظرًا لأننا لا نريد وضع علامة على الإصدار ما لم يجتاز الاختبارات ويُنشر. إذا لم تكن متأكدًا من إعدادات التهيئة، يمكنك ضبط قيمة DRY_RUN على true، وبالتالي سيعطي الفعل رقم الإصدار التالي دون إنشاء وسم للإصدار. حالما يعمل مخطط العمل على نحوٍ صحيح، سيشير المستودع إلى وجود بعض الوسوم: وبالنقر على هذه الوسوم ستُعرض ضمن قائمة بكل الوسوم (والتي تمثل آلية لتعريف الإصدار ووسمه): 11.16: تجاوز إنشاء وسوم لحزمة شيفرة معتمدة ونشرها من الأفضل في أغلب الأوقات نشر الفرع الرئيسي إلى وضع الإنتاج.، لكن قد تكون هناك بعض الأسباب المقنعة لتجاوز إنشاء وسم شيفرة معتمدة أو طلب سحب جرى الموافقة على دمجه أو نشرهما. عدّل إعداداتك لكي لا تُنشر إلى وضع الإنتاج أية شيفرة جرى دمجها إن احتوت رسالة طلب السحب الكلمة "skip#"، ولا توسم برقم الإصدار. تلميح: أسهل طريقة لإنجاز ذلك هو تبديل العبارة الشرطية "if" للخطوة المناسبة. ويمكنك كما فعلنا في التمرين 11.14 الحصول على المعلومات المطلوبة من سياق GitHub لمخطط العمل: يمكنك الإستعانة بالشيفرة التالية مثل نقطة انطلاق: name: Testing stuff on: push: branches: - main jobs: a_test_job: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: gihub context env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - name: commits env: COMMITS: ${{ toJson(github.event.commits) }} run: echo "$COMMITS" - name: commit messages env: COMMIT_MESSAGES: ${{ toJson(github.event.commits.*.message) }} run: echo "$COMMIT_MESSAGES" لاحظ ما الذي طُبع في سجل مخطط العمل. ملاحظة: يمكنك الوصول إلى الشيفرة المعتمدة أو رسائلها عند الدفع أو الدمج مع الفرع الرئيسي فقط، وبالتالي لن تحمل الخاصية github.event.commits أية قيمة. لا حاجة لهذه القيمة على أية حال طالما أننا نرغب في تجاوز هذه الخطوة. ستحتاج غالبًا إلى الدالتين contains و join ضمن عبارة if الشرطية. لا يُعد نشر مخطط العمل أمرًا سهلًا، وغالبًا ما يكون الخيار المتاح هو المحاولة والخطأ، وينصح أحيانًا بوجود مستودع منفصل للتأكد من صحة تهيئة الإعدادات، ثم تُنقل هذه الإعدادات إلى المستودع الفعلي إن كانت صحيحة. كما يمكن أيضًا تثبيت أداة مثل act، التي تساعدك على تشغيل مخطط العمل على جهازك. وعندما تواجهك حالات مختلفة عن التي ناقشناها، كأن تنشئ أفعال خاصة بك، فإن اقتحام غمار أدوات مثل act وتجربتها سيستحق العناء. ملاحظة لاستخدام الأفعال التي يطورها طرف ثالث عندما تستخدم فعل يؤمنه طرف ثالث مثل github-tag-action، من الأفضل أن تحدد أسلوب hash لإدارة الإصدار بدلًا من رقم الإصدار. والسبب في ذلك أن رقم الإصدار الذي أنجز بوسم git قد يكون عرضة للتغيير، فالإصدار الذي يحمل الرقم 1.33.0 هذا اليوم على سبيل المثال، قد يشير إلى شيفرة مختلفة عن تلك الموجودة في نفس الإصدار لكن في الأسبوع القادم. مع ذلك، فالشيفرة المعتمدة على ترميز hash محددة لا تتغير أيًا كانت الظروف، لذا فإن أردنا التيقن 100% من الشيفرة التي نستخدمها، سيكون الخيار الأكثر أمانًا hash. إنّ الإصدار 1.33.0 من الفعل السابق يتوافق مع شيفرة ترميز hash لها هو الإصدار: eca2b69f9e2c24be7decccd0f15fdb1ea5906598، لذلك من الأفضل أن نغير إعدادات التهيئة على النحو التالي: - name: Bump version and push tag uses: anothrNick/github-tag-action@eca2b69f9e2c24be7decccd0f15fdb1ea5906598 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} وعلينا أن نثق عند استخدام أفعال تزودنا بها GitHub بأنها لن تعبث بوسوم الإصدار version tags وأن نختبر شيفرتها بدّقة. وقد ينتهي بك المطاف عند استخدام أفعال من طرف ثالث أمام أفعال تحتوي ثغرات أو حتى مثيرة للشبهة، وحتى لو لم تكن نية المطور الذي كتب الشيفرة سيئة، فقد ينس معلومات الاستيثاق الخاصة به في ركن إنترنت عام، ومن يدري ما قد يحدث بعدها. سنتأكد عند استخدام أسلوب hash أن هذه شيفرة التي نستخدمها لتشغيل مخطط العمل لن تتغير، لأن تغيير الشيفرة المعتمدة المسؤولة عن تنفيذ المخطط سيؤدي إلى تغيير hash. أبق الفرع الرئيسي آمنا سيسمح لك غيت هب أن تهيئ فروعًا محمية، فمن المهم حماية الفرع الأكثر أهمية الذي يجب ألا يخفق أبدًا وهو الفرع الرئيسي. يمكنك أن تختار بين عدة مستويات حماية عبر إعدادات المستودع. لن نغطي كل هذه الخيارات، لكن يمكنك طبعًا الاطلاع عليها من خلال توثيق GitHub. ومن وجهة نظر منظومة CI، ستتمثل الحماية الأكثر أهمية في نجاح خطوات التحقق من الحالة قبل أن يدمج طلب السحب ضمن الفرع الرئيسي. فلو أعددت أفعال GitHub لتنفذ مهام التدقيق والاختبار، فلن يُدمج طلب السحب قبل تصحيح جميع أخطاء التدقيق وقبل أن تنجح جميع الاختبارات. ونظرًا لكونك مدير مستودعك، ستجد خيارًا لتخطي التقييدات هذه. لن يظهر هذا الخيار لغير المدراء. لتهيئ إعدادات الحماية للفرع الرئيسي، توجه إلى إعدادات "Settings" المستودع من القائمة العليا ضمن المستودع. اختر من قائمة الجهة اليسرى فروع "Branches" ثم انقر زر أضف قاعدة "Add rule" بجوار العنصر قواعد حماية الفروع "Branches protection rules". اكتب نموذج لاسم الفرع ("master" سيكون مناسبًا)، ثم اختر طريقة الحماية التي تريد إعدادها. اختر على الأقل "يجب التحقق من نجاح خطوات التحقق من الحالة قبل الدمج Require status checks to pass before merging" لتضمن تسخير الإمكانات الكاملة لاستضافة GitHub Actions. وتحت هذا الخيار عليك اختيار "يجب أن تكون الفروع محدّثة قبل الدمج Require branches to be up to date before merging"، وفعّل جميع الخيارات التي تتحقق من الحالة قبل دمج أية طلبات سحب. التمرين 11.17 إضافة حماية إلى الفرع الرئيسي أضف حماية لفرعك الرئيسي. إذ عليك حمايته بضمان التالي: الموافقة على جميع طلبات السحب قبل دمجها. نجاح جميع خطوات التحقق من الحالة قبل الدمج. لا تفعِّل الخيار "Include administrators" حاليًا، لأنك لو فعلت ذلك فعليك الانتظار حتى يراجع شخص ما طلب السحب الذي قدمته قبل نشر الشيفرة. ترجمة -وبتصرف- للفصل Keeping Green من سلسلة Deep Dive Into Modern Web Development. اقرأ أيضًا المقال السابق: نشر التطبيقات وتوزيعها وفق نهج التسليم المستمر نشر تطبيقات الويب الموجهة لبيئة الإنتاج نشر تطبيقات iOS على متجر Apple Store
  3. الآن وبعد أن كتبنا تطبيقًا جيدًا، قد حان الوقت لنشره وتوزيعه على المستخدمين الفعليين. لقد فعلنا ذلك في القسم 3 بدفع مستودع git إلى خوادم الاستضافة السحابية Heroku بكل بساطة. تُعد عملية إصدار برمجيات على منصة هيروكو Heroku أمرًا بسيطًا موازنةً بغيرها من الاستضافات، لكن لا تزال هناك طبعًا بعض المخاطر، فلا شيء سيمنعنا من الدفع بشيفرة لا تعمل إلى وضع الإنتاج عن طريق الخطأ. سنتعرف في الفقرات القادمة على مبادئ النشر الآمن للتطبيقات، ومبادئ نشر البرمجيات بالمقاييس الصغيرة والواسعة. يمكن لأي شيء أن يحدث خطأ نريد تحديد بعض القواعد التي تضبط عملية نشرنا للتطبيقات، لكن علينا بداية إلقاء نظرةٍ على بعض المحدوديات الواقعية: "إن أمكن لشيءٍ ما أن يخفق، فسيخفق": هي عبارة يتضمنها قانون مورفي، ومن المهم تذكرها دائمًا عند التخطيط لمنظومة النشر التي سنتبعها، ومن الأشياء التي ينبغي أخذها بالحسبان أيضًا: ماذا لو توقف الحاسوب عن العمل أثناء نشر التطبيق؟ ماذا سيحدث إن انقطع الاتصال بالإنترنت أثناء نشر التطبيق؟ ماذا سيحدث إن أخفقت أية تعليمات من سكربت أو منظومة النشر؟ ماذا سيحدث إن لم يعمل تطبيقي، لسببٍ أو لآخر، على الخادم بعد نشره؟ هل يمكنني التراجع rollback إلى النسخة السابقة؟ ماذا سيحدث إذ أرسل مستخدم ما طلب HTTP إلى التطبيق قبل أن يكتمل نشره (لا يوجد وقتٌ لإرسال استجابة له)؟ هذه عينة صغيرة من المشاكل التي قد تواجهك أثناء النشر أو بالأحرى عينة من الأمور التي ينبغي التخطيط لها. لا ينبغي لمنظومة النشر التي نعتمدها أن تترك البرنامج في حالة إخفاق أيًا كان سببه، كما ينبغي علينا أن نعرف (أو أن نجد بسهولة) حالة منظومة النشر. وطالما نتحدث عن النشر وعن التكامل المستمر CI عمومًا، هناك قاعدةٌ مهمةٌ أخرى عليك تذكرها: "الأخطاء الصامتة قاتلة". لا يعني هذا طبعًا عرض الأخطاء على مستخدم البرنامج، بل يعني أنه يجب علينا الانتباه إلى أي شيء قد يخفق. فلو كنا على دراية بمشكلة محتملة الوقوع، يمكننا إصلاحها. فإن لم تعطي منظومة النشر أية أخطاء لكنها فشلت، سنصل إلى المرحلة التي نعتقد فيها أننا أصلحنا كل الأخطاء الحرجة ومع ذلك تخفق المنظومة، وبالتالي سنترك الثغرة في بيئة الإنتاج غير مدركين لخطورة الوضع. ما الذي تمنحه منظومة النشر الجيدة؟ من الصعب وضع قواعد محددة أو متطلبات خاصة بمنظومة النشر، لكننا سنحاول ذلك: عندما تخفق المنظومة في أية خطوة، يجب أن تخفق دون أية آثار جانبية. لا ينبغي أبدًا أن تترك المنظومة البرنامج في حالة فشل. ينبغي أن تخبرنا المنظومة عن أية حالات إخفاق، فمن الأفضل تنبيهنا إلى حالات الإخفاق عوضًا عن النجاح. ينبغي على المنظومة أن تسمح لنا بالتراجع إلى النسخة المنشورة سابقًا. يفضل أن نتراجع بسهولة إلى نسخة أقل عرضة للإخفاق بالموازنة مع النسخة المنشورة كاملةً. يبقى الخيار الأفضل لنا هو التراجع الآلي في حال أخفق النشر. ينبغي أن تكون المنظومة قادرةً على التعامل مع طلبات HTTP قبل انتهاء أو أثناء عملية النشر. ينبغي أن تتأكد المنظومة أنّ البرنامج الذي ننشره سيلبّي المتطلبات التي وضعناها لعملية النشر (لا تنشر مثلًا برنامج أخفق في أحد الاختبارات). لنحدد أيضًا بعض الأشياء التي نريدها في منظومة النشر الافتراضية التي نقترحها: نريدها أن تكون سريعة. لا نريد وقتًا يتوقف فيه البرنامج عن العمل downtime أثناء النشر (هذا أمر مختلف عن معالجة طلبات المستخدمين قبل انتهاء أو أثناء النشر). التمارين 11.10 - 11.12 قبل أن نبدأ بالتمارين عليك إعداد تطبيقك لبيئة عمل هيروكو Heroku. وهنا لن ندفع الشيفرة بأنفسنا، إذ سينفِّذ مخطط عمل GitHub Actions المهمة من أجلنا. تأكد من تثبيت Heroku CLI ثم سجِّل دخولك مستخدمًا واجهة سطر الأوامر CLI عن طريق heroku login. أنشئ تطبيقًا على هيروكو HeroKu باستخدام الأمر: heroku create --region eu {your-app-name}‎ وانتق منطقةً قريبةً من موقعك الجغرافي. ولِّد شهادة تحقق Token لملفك على Heroku باستخدام الأمر: heroku authorizations:create ثم خزّن معلومات الاستيثاق على ملف ضمن حاسوبك لكن لا تدفعه إلى GitHub. ستحتاج إلى شهادة التحقق من أجل مخطط عمل نشر التطبيق. اطلع أكثر على شهادة تحقق هيروكو عبر الإنترنت. 11.10: نشر تطبيقك على منصة هيروكو Heroku وسّع مخطط العمل بخطوة لنشر تطبيقك على منصة هيروكو Heroku. نفترض فيما سيأتي أنك ستستخدم AkhileshNS/heroku-deploy وهو فعل GitHub Actions الخاص بالنشر على هيروكو والذي طوره مجتمع GitHub Actions. تحتاج إلى شهادة التفويض التي حصلت عليها سابقًا من أجل نشر تطبيقك. ومن الأفضل تمرير قيمتها إلى GitHub Actions باستخدام أسرار المستودع repository secrets: يمكنك الآن الوصول إلى قيمة الشهادة على النحو التالي: ${{secrets.HEROKU_API_KEY}} إذا جرى كل شيء على ما يرام، سيبدو مخطط العمل على الشكل التالي: جرِّب تطبيقك عبر متصفح، لكن الأخطاء ستظهر غالبًا. سنجد أنّ منصة هيروكو تفترض وجود الملف "Procfile" في المستودع والذي يوجّهه لطريقة تشغيل البرنامج. أضف إذًا ملف "Procfile" مناسب إلى المستودع وتأكد أنّ التطبيق سيعمل جيدًا. تذكرة: راقب باستمرار ما يحدث عبر سِجِل الخادم عندما تجرب عملية النشر. استخدم لذلك الأمر heroku logs دائمًا. 11.11: التحقق من عمل التطبيق قبل التوسّع أكثر في التطبيق، تحقق أن التطبيق يعمل جيدًا بعد النشر. لا نحتاج في الواقع لخطوة جديدة في مخطط العمل، إذ يحتوي الفعل deploy-to-heroku على خيار يفي بالغرض. أضف وصلة تخديم end point بسيطة مهمتها التحقق من عمل التطبيق في الواجهة الخلفية. ويمكنك أيضًا نسخ الشيفرة التالية: app.get('/health', (req, res) => { res.send('ok') }) من الجيد أيضًا وجود وصلة تخديم اختبارية في التطبيق، لكي يمتلك إمكانية إجراء بعض التعديلات في الشيفرة ويتأكد من أن التغيرات قد ظهرت أيضًا في النسخة المنشورة: app.get('/version', (req, res) => { res.send('1') // غير هذه القيمة للتأكد من أنها نُشرت في النسخة الجديدة }) راجع التوثيق لتعرف كيف ستضم آلية التحقق من عمل التطبيق إلى خطوة النشر، واستخدم عنوان وصلة التخديم التي أنشأتها للتحقق من عمل التطبيق، وقد تحتاج غالبًا إلى الخيار "checkstring" حتى يُنفَّذ الأمر. تأكد من أنّ GitHub Actions سينتبه إذا ما سبب النشر إخفاق التطبيق. استخدم لاختبار ذلك أمر إقلاع خاطئ مثلًا في الملف "Procfile". قبل الانتقال إلى التمرين التالي، أصلح مشاكل خطوة النشر وتأكد أن التطبيق سيعمل بالشكل المطلوب مجددًا. 11.12: التراجع من الأفضل إذا أخفق التطبيق بعد النشر أن تتراجع إلى الإصدار السابق. ولحسن الحظ، يجعل هيروكو Heroku هذا الأمر بسيطًا جدًا. ينتج عن كل عملية نشر على Heroku إصدار، ويمكنك معرفة الإصدارات الموجودة لتطبيق بتنفيذ الأمر heroku releases: $ heroku releases === calm-wildwood-40210 Releases - Current: v8 v8 Deploy de15fc2b mluukkai@iki.fi 2022/03/02 19:14:22 +0200 (~ 8m ago) v7 Deploy 8748a04e mluukkai@iki.fi 2022/03/02 19:06:28 +0200 (~ 16m ago) v6 Deploy a617a93d mluukkai@iki.fi 2022/03/02 19:00:02 +0200 (~ 23m ago) v5 Deploy 70f9b219 mluukkai@iki.fi 2022/03/02 18:48:47 +0200 (~ 34m ago) v4 Deploy 0b2db00d mluukkai@iki.fi 2022/03/02 17:53:24 +0200 (~ 1h ago) v3 Deploy f1cd250b mluukkai@iki.fi 2022/03/02 17:44:32 +0200 (~ 1h ago) v2 Enable Logplex mluukkai@iki.fi 2022/03/02 17:00:26 +0200 (~ 2h ago) v1 Initial release mluukkai@iki.fi 2022/03/02 17:00:25 +0200 (~ 2h ago) يمكن التراجع إلى إصدار محدد بكتابة أمر واحد ضمن سطر الأوامر، والأفضل من ذلك سيتولى الفعل deploy-to-heroku مهمة التراجع نيابةً عنا. اقرأ توثيق GitHub Actions مجددًا وعدّل مخطط العمل لتمنع إخفاق التطبيق عند النشر. يمكنك محاكاة الأمر أيضًا بكتابة أمر خاطئ في الملف "Procfile" والتجربة: تحقق أنّ التطبيق سيستمر في العمل حتى لو أخفق النشر. تنبيه: على الرغم من إمكانية التراجع التلقائي، قد يخفق البناء في العالم الحقيقي. لذلك يُعد إيجاد سبب المشكلة وإصلاحها بسرعة أمرًا جوهريًا. ويبقى سجل هيروكو Heroku عادةً هو المكان الأنسب للبحث والتقصي عن المسببات: ترجمة -وبتصرف- للفصل Deployment من سلسلة Deep Dive Into Modern Web Development. اقرأ أيضًا المقال السابق: استخدام GitHub Actions لتحقيق التكامل المستمر والنشر المستمر نشر تطبيقات الويب الموجهة لبيئة الإنتاج نشر تطبيقات iOS على متجر Apple Store
  4. سنلقي نظرةً قبل أن نبدأ التعامل مع GitHub Actions على ماهيته والطريقة التي يعمل بها. يعمل GitHub Actions على مبدأ مخططات العمل workflows؛ ومخطط العمل هو سلسلة من الأعمال التي تُنفَّذ عندما يقع حدثٌ معين، وتتضمن هذه الأعمال بحد ذاتها التعليمات التي يجب أن يُنفّذها GitHub Actions. سيبدو تنفيذ مخطط عمل نموذجي على النحو التالي: وقوع حدثٌ ما، مثل دفع push شيفرة إلى الفرع الرئيسي. البدء بتنفيذ مخطط العمل. الإنهاء والتنظيف. الاحتياجات الأساسية نحتاج عمومًا إلى المتطلبات التالية لتشغيل منظومة التكامل المتواصل Continuous Integration -أو اختصارًا CI- ضمن مستودع: مستودع. بعض التعريفات بالمهام التي ستنفذها منظومة CI، وقد يكون ذلك على هيئة ملف ضمن المستودع، أو يمكن أن يُعرَّف ضمن منظومة CI. يجب أن تعرف المنظومة أنّ المستودع (والملف في داخله) موجودٌ فعلًا. تحتاج المنظومة إلى الأذونات اللازمة لتنفيذ الأفعال التي يفترض أن تُنفذها، فلو أردنا من المنظومة أن تكون قادرةً على النشر في بيئة الإنتاج مثلًا، فستحتاج إلى بيانات الاستيثاق الخاصة بهذه البيئة. سنحتاج ما ذكرناه على الأقل في النموذج التقليدي للمنظومة. سنرى لاحقًا كيفية اختصار بعض الخطوات أو تنفيذها بطريقة مريحة لا تسبب لك أية مشاكل تقلق منها. لاستضافة GitHub Actions إيجابياتٌ عظيمة بالموازنة مع الاستضافة الذاتية؛ إذ سيُستضاف المستودع مع مزوِّد لمنظومة CI، أي سيؤمن لك GitHub Actions المستودع ومنظومة CI معًا، ويعني ذلك أننا عندما نُمكِّن الأفعال ضمن المستودع، سيكون GitHub Actions على علم مسبقًا بأنه لدينا مخططات عمل مُعرًّفة، وبما تعنيه هذه التعريفات. التمرين 11.2 سننفذ في معظم تمرينات هذا القسم خط إنتاج لمنظومة CI/CD من أجل المشروع الصغير الموجود على غيت هب GitHub. تنبيه: قد لا تعمل الشيفرة مع الإصدار 15 من Node، وإذا حدث ذلك ولم يُقلع المشروع، انتقل للعمل على الإصدار 14 وإلا عليك حل مشاكلك بنفسك. المشروع النموذجي عليك أولًا إنشاء نسخةٍ من مستودع المشروع ضمن حسابك الخاص ولاستخدامك الشخصي. لاشتقاق المستودع، انقر على الزر "Fork" في أعلى ويمين واجهة المستودع بجانب الزر "Star": سيبدأ بعد ذلك بإنشاء مستودع جديد يُدعى "github_username}/full-stack-open-pokedex}"، وستُنقل بعد انتهاء العملية إلى مستودعك الجديد تلقائيًا: انسخ المشروع الآن إلى جهازك، وكما جرت العادة إبدأ بتفقد الملف "package.json" فهو المكان الأنسب للاطلاع على تفاصيل مشروع جديد. حاول أن تنفّذ ما يلي: تثبيت الاعتماديات باستخدام الأمر npm install. تشغيل الشيفرة في وضع التطوير. إجراء الاختبارات. تدقيق lint الشيفرة. قد تلاحظ وجود بعض أخطاء التدقيق والاختبارات المخفقة في المشروع، دعها كما هي حاليًا، إذ سنتكفل بحلها في التمارين القادمة. وكما ذكرنا في القسم 3، لا ينبغي تشغيل شيفرة React في وضع التطوير بعد نشرها في وضع الإنتاج، لذلك حاول أن تُنفِّذ ما يلي: أنشئ نسخة إنتاج من المشروع. شغل نسخة الإنتاج على جهازك محليًا. ستجد سكربتًا خاصًا لتنفيذ المهمتين السابقتين في المشروع. خذ وقتًا لدراسة هيكيلية المشروع. وكما ستلاحظ، فإن الواجهتين الأمامية والخلفية موجودتان في نفس المستودع، وقد اعتدنا في الأقسام الأولى على وجودهما في مستودعين منفصلين. لكن هذا الأمر سيبسط الأمور عند إعداد بيئة CI. ستجد بالمقابل أنّ الواجهة الأمامية في معظم مشاريع منهاجنا لم تُنفّذ باستخدام "create-react-app"، لكنها تمتلك إعدادات تهيئة بسيطة باستخدام webpack تتكفل بإنشاء بيئة التطوير وبإنشاء حزمة الإنتاج. التعامل مع مخططات العمل تُعد مخططات العمل الأساس الذي تبنى عليه منظومات CI في غيت هب GitHub، فهي مساراتٌ لعملية يمكنك إعدادها لتنفيذ مهام تلقائيًا، مثل بناء التطبيقات واختبارها وتدقيقها وإصدارها ونشرها. تبدو عادةً هيكلية مخططات العمل على النحو التالي: مخطط العمل مهمة خطوة خطوة مهمة خطوة ينبغي أن يحدد كل مخطط مهمةً واحدةً على الأقل تحتوي على خطوات لتنفيذ إجراءات مستقلة. ستُشغّل هذه المهمات على التوازي بينما تُنفًّذ الخطوات في كل مهمة على التتالي. تتنوع الخطوات من تنفيذ سطر أوامر محدد إلى الأفعال المعرَّفة مسبقًا، لهذا تحمل الاستضافة اسم أفعال غيت هب "GitHub Actions". يمكنك إنشاء الأفعال الخاصة بك أو أن تستخدم أفعالُا نشرها آخرون، وهي في الواقع كثيرة، وسنعود إليها لاحقًا. ينبغي أن تُحدِّد مخططات العمل الخاصة بك ضمن المجلد "github/workflows." في مستودعك كي يميزها غيت هب، ولكل مخطط عمل ملفٌ مستقلٌ خاصٌ به والذي يجب تهيئته باستخدام لغة تقسيم البيانات YAML. يُشتق الاسم YAML من العبارة "YAML Ain't Markup Language" والتي تعني "ليست لغة توصيف"؛ فكما تُلمّح إليه التسمية، فالهدف منها أن تكون مفهومةً للبشر. تُستخدم هذه اللغة في كتابة ملفات التهيئة، وستجد أنها سهلة الفهم فعلًا. عليك الانتباه إلى أهمية الانزياحات Indentation في بداية الأسطر البرمجية في YAML، وللاطلاع أكثر حول قواعد اللغة يمكنك الرجوع إلى شبكة الإنترنت. يتضمن مخطط العمل في مستند YAML هذه العناصر الثلاث: name الاسم: ويشير إلى اسم المخطط. triggers المُسبب: الأحداث التي تؤدي إلى تنفيذ المخطط. jobs المهام: المهام المختلفة التي سيُنفّذها المخطط، وقد يحتوي المخطط البسيط مهمةً واحدةً فقط. سيبدو تعريف مخطط بسيط على النحو التالي: name: Hello World! on: push: branches: - master jobs: hello_world_job: runs-on: ubuntu-20.04 steps: - name: Say hello run: | echo "Hello World!" وكما هو واضح، سيكون المُسبب هو عملية دفع الشيفرة إلى الفرع الرئيسي. يحتوي المخطط أيضًا على مهمة واحدة اسمها hello_world_job سيجري تنفيذها ضمن بيئة افتراضية تعمل على نظام التشغيل أوبنتو Ubuntu 20.04، وتتضمن هذه المهمة خطوة واحدة اسمها Say hello ستُنفِّذ الأمر "!echo "Hello World ضمن الصدفة shell. ربما تتساءل، متى يبدأ غيت هب بتنفيذ مخطط معين؟ هناك العديد من الخيارات المتاحة، لكن وبصراحة، يمكنك أن تهيئ المخطط ليعمل حالما: يقع حدث ما، مثل الحالة التي يدفع فيها أحدهم اعتمادًا commit إلى مستودع، أو عندما تحدث مشكلة أو يقدم أحدهم طلب سحب pull request. تُنفَّذ مهمةٌ مجدولةٌ مسبقًا ومحددة باستخدام تعابير cron. يقع حدث خارجي، كأن يُنفَّذ أمر ضمن تطبيق خارجي، مثل تطبيق الرسائل Slack. وللاطلاع على مزيدٍ من الأحداث المسببة لبدء تنفيذ مخطط عمل، عُد إلى توثيق GitHub Actions. التمرينان 11.3- 11.4 لنربط كل ما خلصنا إليه، دعونا نشغِّل GitHub Actions ضمن المشروع النموذجي. 11.3: تطبيق Hello world أنشئ مخططًا يُظهر العبارة "!Hello World" للمستخدم. عليك أن تنشئ المجلد "github/workflows."، والملف "hello.yml" الذي سيحتوي الإعدادات ضمن مستودعك. ولتطلع على ما أنجزه مخطط عمل GitHub Actions الخاص بك، يمكن التوجه إلى النافذة Action ضمن واجهة غيت هب GitHub، حيث من المفترض أن ترى مخطط العمل في مستودعك والخطوات التي أنجزها. ستبدو نتيجة تنفيذ مخططك على النحو التالي إن كانت تهيئة المخطط صحيحة: يُفترض أن ترى الرسالة "!Hello World" نتيجةً لتنفيذ المخطط، وإذا حدث ذلك، ستكون جميع الخطوات قد نُفِّذت بنجاح، وسيكون أول مخططات عمل GitHub Actions الخاصة بك قيد العمل. سيعطيك أيضًا GitHub Actions معلومات عن البيئة (نظام التشغيل، وإعداداته) التي يعمل ضمنها مخطط العمل. وتظهر أهمية ذلك أثناء حدوث أمر طارئ، إذ سيسهل هذا الأمر تنقيح الأخطاء إن استطعت تكرار كل الخطوات على جهازك. 11.4: التاريخ ومحتويات المجلد وسًع مخطط العمل لإضافة خطوات لطباعة التاريخ ومحتويات المجلد الحالي بالصياغة الطويلة long format. يمكن تنفيذ هاتين الخطوتين باستخدام الأمرين date و ls بكل بساطة. سيبدو مخطط عملك الآن على النحو التالي: وطالما أن الأمر ls -l سيُظهر افتراضيًا البيئة الافتراضية التي يعمل عليها مخطط العمل، ستلاحظ أنها لا تحتوي على أية شيفرات. إعداد وتجهيز خطوات التدقيق والاختبار والبناء بعد إنجاز التمارين الأولى، سيكون لدينا مخطط عمل بسيط لكنه لن يفيدنا في عملية الإعداد. لنجعل مخطط العمل قادرًا على فعل مهمة حقيقية. سننجز فعلًا action قادرًا على تدقيق الشيفرة. فإذا أخفق التدقيق، سيُظهر Github Actions الحالة الحمراء. سيبدو المخطط الذي سنخزنه ضمن الملف "pipeline.yml" مبدئيًا على النحو التالي: name: Deployment pipeline on: push: branches: - master jobs: قبل أن نتمكن من تنفيذ الأمر الذي سيبدأ خطوة التدقيق، لا بدّ من تنفيذ فعلين لإعداد البيئة الملائمة للمهمة. إعداد بيئة العمل إعداد بيئة العمل أمرٌ ضروري لتهيئة خط الإنتاج Pipeline، لذلك سنستخدم بيئة العمل الافتراضية Ubuntu 20.04 لأنها ستكون البيئة التي ستعمل عليها نسخة الإنتاج. ولا بدّ من تطابق البيئة نفسها في منظومة CI وفي وضع الإنتاج قدر المستطاع، لتحاشي الحالات التي تعمل فيها الشيفرة نفسها بصورةٍ مختلفة في كليهما، وبالتالي لن تتحقق الغاية من استخدام CI. سنوضح تاليًا الخطوات في مهمة "البناء" لكي تستطيع منظومة CI تنفيذها. وكما لاحظنا في التمارين السابقة، لن تحتوي بيئة العمل افتراضيًا أية شيفرات، لذلك لا بدّ من التحقق من الشيفرة من المستودع. هذه الخطوة سهلة وهي على النحو التالي: name: Deployment pipeline on: push: branches: - master jobs: simple_deployment_pipeline: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 تُستخدم التعليمة uses لإخبار المخطط أن يُنفِّذ فعلًا محددًا. ويُعرَّف الفعل بأنه قطعة من الشيفرة قابلة لإعادة الاستخدام مثل الدوال، ويمكن تعريف الأفعال داخل المستودع ضمن ملف مستقل، أو استخدام الأفعال الموجودة في المستودعات العامة. سنستخدم هنا الفعل العام actions/checkout وبنسخة محددة هي "v3@" لتلافي فشل التعديلات إن جرى تحديث الفعل. ويُنفِّذ الفعل checkout ما يوحي به اسمه، إذ يتحقق من شيفرة المشروع المصدرية من git. وطالما أنّ التطبيق قد كتب باستخدام جافا سكربت، فلا بدّ من تهيئة "Node.js" لكي نتمكن من استخدام الأوامر الموجودة في الملف "package.json". ولإعداد "Node.js" يمكن استخدام الفعل actions/setup-node. سنختار الإصدار "16" لأنه الإصدار الذي تستخدمه بيئة الإنتاج. # name and trigger not shown anymore... jobs: simple_deployment_pipeline: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v2 with: node-version: '16' تُستخدم التعليمة with لإسناد معامل parameter إلى الفعل، إذ يحدد المعامل هنا نسخة Node.js التي ننوي استخدامها. أخيرًا، لا بُد من تثبيت الاعتماديات اللازمة. وكما تفعل عادةً على جهازك، نفِّذ الأمر npm install. ستبدو خطوات المهمة على النحو التالي: jobs: simple_deployment_pipeline: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v2 with: node-version: '16' - name: npm install run: npm install وهكذا ستكون البيئة الآن جاهزةً لأداء مهمة حقيقية ومهمة. التدقيق Lint يمكنك الآن تنفيذ السكربتات التي يحتويها الملف "package.json" كما لو أنك تنفذها على حاسوبك الشخصي، فكل ما عليك فعله لتدقيق الشيفرة، هو إضافة إعدادٍ لتشغيل الأمر npm run eslint: jobs: simple_deployment_pipeline: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v2 with: node-version: '16' - name: npm install run: npm install - name: lint run: npm run eslint التمرينات 11.5 - 11.9 11.5: تدقيق مخطط عمل نفّذ أو انسخ والصق مخطط العمل "Lint" واعتمد شيفرته في مستودعك، ثم أنشئ ملف yml جديد لهذا المخطط، يمكنك تسميته "pipeline.yml". ادفع بشيفرتك إلى الفرع الرئيسي ثم توجه إلى النافذة "ِActions" وانقر على المخطط الذي أنشأته على اليسار. ستجد أن هذا المخطط سيفشل في الإقلاع: 11.6: إصلاح الشيفرة ستجد بعض المشاكل في الشيفرة تتطلب الإصلاح. افتح سِجِل مخطط العمل وتحقق من وجود أخطاء. إليك تليمحين مهمين: من الأفضل أن تصلح أحد الأخطاء بتحديد ملف مناسب لعملية التدقيق (راجع القسم الثالث لمزيد من المعلومات عن كيفية تنفيذ ذلك)؛ كما يمكن إيقاف أحد الاعتراضات التي تخص تنفيذ الأمر console.log بإيقاف القاعدة التي تسببه في السطر الذي توجد به. أجرِ التعديلات اللازمة على الشيفرة المصدرية لكي ينجح مخطط العمل في الإقلاع، وحالما تعتمد الشيفرة الجديدة سيعمل المخطط وستجد خرجًا مُحدَّثًا باللون الأخضر من جديد. 11.7: البناء والاختبار لنوسِّع مخطط العمل الذي يُنفِّذ حاليًا مهمة التدقيق. أضف أوامر البناء والاختبار إلى مخطط العمل، وستبدو النتيجة قريبةً من التالي: ستلاحظ أيضًا وجود بعض المشاكل. 11.8: العودة إلى الوضع الصحيح تحقق من الاختبارات التي أخفقت وأصلح المشكلة في الشيفرة (لا تُغيّر الاختبارات). سيعمل المخطط ويظهر الخرج باللون الأخضر مجددًا عند إصلاح المشاكل. 11.9: اختبار مشترك بسيط للواجهتين تستخدم مجموعة الاختبارات الحالية jest لتتأكد من عمل مكونات React بالطريقة المطلوبة، وهذا تمامًا ما فعلناه في فصل "اختبار تطبيقات React" من القسم 5. يُعد اختبار كل مكوًن بصورةٍ منفصلة أمرًا مفيدًا لكنه لا يضمن عمل كل النظام بالطريقة المطلوبة. وللتأكد أكثر، سنكتب اختبارًا بسيطًا مشتركًا بين الواجهتين الأمامية والخلفية end to end testing، مستخدمين المكتبة Cypress وعلى نحوٍ مشابه للعمل الذي أنجزناه في الفصل الذي يحمل العنوان "الاختبار المشترك للواجهتين" في القسم 5. سنهيئ cypress (ستجد الطريقة في الفصل الذي أشرنا إليه)، ثم سننفذ الاختبار التالي: describe('Pokedex', function() { it('front page can be opened', function() { cy.visit('http://localhost:5000') cy.contains('ivysaur') cy.contains('Pokémon and Pokémon character names are trademarks of Nintendo.') }) }) عرِّف سكربت npm التالي: test:e2e لتشغيل الاختبار المشترك للواجهتين "e2e" باستخدام سطر الأوامر. تنبيه: لا تستخدم الكلمة "spec" في تسمية ملف اختبار cypress، لأنها ستجعل jest ينفذ شيفرة الملف أيضًا، وقد يسبب ذلك عدة مشاكل. تنبيه آخر: على الرغم من قدرة الصفحة على تصيير أسماء "مخلوقات البوكيمون Pokemon" لتبدأ بأحرف كبيرة، إلا أنها مكتوبةٌ بأحرف صغيرة في المصدر، فاسم البوكيمون "Ivysaur" هو أصلًا "ivysaur" تحقق من نجاح الاختبار على جهازك، وتذكر أن الاختبارات ستفترض أن تطبيقك يعمل عندما تُنفِّذ الاختبار. وإن كنت قد نسيت بعض التفاصيل، راجع القسم 5. حالما يعمل الاختبار المشترك للواجهتين على جهازك، ضعه في مخطط عمل GitHub Action، وأسهل الطرق لتنفيذ ذلك هو استخدام الفعل الجاهز cypress-io/github-action، وستكون الخطوة المناسبة لحالتنا على النحو التالي: - name: e2e tests uses: cypress-io/github-action@v2 with: command: npm run test:e2e start: npm run start-prod wait-on: http://localhost:5000 لقد استخدمنا ثلاثة خيارات: command: ويحدد كيف سنشغل اختبار cypress. start: يزودنا بسكربت npm الذي يُشغِّل الخادم. wait-on: يمنع الاختبار من العمل قبل أن يقلع الخادم على العنوان http://localhost:5000. عندما تتأكد من عمل خط الإنتاج، اكتب اختبارًا آخر للتأكد أنّ المستخدم قادرٌ على الانتقال من الصفحة الرئيسية إلى صفحة "بوكيمون" محدد مثل "ivysaur". لا حاجة لتعقيد الاختبار، بل تأكد فقط أن الصفحة التي تنتقل إليها بنقر الرابط، ستحتوي بعض المعلومات الصحيحة مثل النص "chlorophyll" في حالة البوكيمون "ivysaur". ملاحظة: تُكتب أسماء البوكيمون بالأحرف الصغيرة، ويمكن الكتابة بالأحرف الكبيرة في CSS، لذلك لا تكتب أثناء البحث الاسم "Chlorophyll"، بل اكتب "chlorophyll". ملاحظة: لا تحاول الانتقال إلى صفحة البوكيمون "bulbasaur"، فربما لسببٍ ما لن تعمل صفحة هذا البوكيمون. ستبدو النتيجة النهائية على الشكل التالي: إن الأمر الجيد المتعلق بالاختبار المشترك للواجهتين هو الثقة بأنّ البرنامج سيعمل على نحوٍ جيد من وجهة نظر المستخدم النهائي. لكن سيكون الثمن الذي تدفعه بالمقابل هو الاستجابة البطيئة، إذ سيستغرق تنفيذ مخطط العمل بالكامل وقتًا أطول بكثير. ترجمة -وبتصرف- للفصل Getting started with GitHub Actions من سلسلة Deep Dive Into Modern Web Development. اقرأ أيضًا المقال السابق: مدخل إلى التكامل المستمر والنشر المستمر CI/CD التكامل المستمر: تثبيت Concourse CI على أوبنتو إعداد التكامل المستمر والنشر المستمر باستخدام الخدمتين CircleCI وCoveralls إعادة تأسيس تفريعات طلب السحب وتحديثه في git
  5. سنبني خلال هذا المقال خط إنتاج Pipeline لنشر المشروع النموذجي الذي بدأناه في التمرين 11.2. إذ سننشئ نسخة خاصةً بنا من مستودع المشروع لكي نتعامل معها، ثم سنبني في آخر تمرينين خط إنتاج آخر لنشر بعض التطبيقات الخاصة بنا والتي بنيناها سابقًا. يضم القسم 21 تمرينًا من المفترض إكمالها جميعًا حتى تنهي هذا المنهاج، وعليك أن تسلم حلول هذه التمرينات إلى منظومة تسليم التمارين بنفس الأسلوب المُتبع في القسم السابق، إذ تُسلَّم التمرينات إلى نسخة مختلفة من المنهاج. ستعتمد المعلومات في هذا القسم على مفاهيم اطلعنا عليها سابقًا، لذلك ننصحك بإكمال الأقسام 0-5 قبل البدء بهذا القسم. لن تكتب الكثير من أسطر الشيفرة في هذا القسم، فهو يغطي في معظم الأوقات مواضيع عن التهيئة. وعلى الرغم من أن تنقيح الشيفرة صعب، لكن تنقيح أوامر التهيئة أصعب بكثير، فعليك إذًا التحلي بالصبر والمثابرة في هذا القسم. تجهيز التطبيقات لمرحلة الإنتاج ستضطر بعد الانتهاء من كتابة الشيفرة عاجلًا أم آجلًا إلى نقل تطبيقك إلى مرحلة الإنتاج، أي إلى مستخدميه الحقيقيين، ثم ستضطر بعدها إلى صيانة هذا التطبيق باستمرار وإصدار نسخٍ جديدة منه والعمل مع مطورين آخرين لتوسيعه. لقد استخدمنا حاليًا غيت هب GitHub لتخزين الشيفرة المصدرية، لكن ما الحل عندما نعمل ضمن فريق من المطورين؟ ستظهر عدة مشاكل عند تعاون عدة مطورين، فقد يعمل التطبيق جيدًا على حاسوبي، لكن قد يخفق على حواسيب مطورين آخرين يعملون على أنظمة تشغيل مختلفة، أو يستخدمون نسخًا مختلفة من المكتبات التي أدرجناها في التطبيق. يُشار إلى هذه المشكلة بالعبارة "التطبيق يعمل على جهازي works on my machine". هناك مشكلة أخرى، فلو أجرى مطورين تعديلات على شيفرة التطبيق ولم يتفقا من سينشر التعديلات التي أنجزها، من سيمنع أحدهما من محي تعديلات الآخر وكتابة تعديلاته مكانها؟ سنغطي في هذا القسم أساليب العمل المشترك لبناء ونشر التطبيقات بطريقة منضبطة ومحددة جيدًا، يظهر فيها بكل وضوح ما الذي سيحدث وتحت أية ظروف. بعض المصطلحات المفيدة نستخدم في هذا القسم مصطلحات قد لا تعرفها أو لم تفهمها جيدًا، سنناقش هذه المصطلحات تاليًا، وحتى لو كنت على دراية بهذه المصطلحات، اطلع على هذه الفقرة لنكون على وفاق في فهم المصطلح عند وروده. الفروع Branches يسمح نظام غيت Git بوجود نسخ، أو مسارات streams، أو إصدارات مختلفة من الشيفرة تتعايش معًا دون الحاجة لإلغاء بعضها بعضًا؛ فعندما تُنشئ مستودعًا سيكون هذا المستودع بمثابة الفرع الرئيسي (ندعوه في غيت بالاسم "main" أو "master"، لكن الأمر مختلف في المشاريع القديمة). لا بأس بهذا الأسلوب إذا كان هناك مطور واحد يستخدم هذا الفرع، ويعمل على تطوير ميزة واحدة للتطبيق كل مرة. سيكون استخدام الفروع مفيدًا عندما تتعقد بيئة التطوير، إذ سيعمل كل مطور على فرع أو أكثر، وسيمثل كل فرع نسخةً مختلفةً قليلًا عن نسخة الفرع الرئيسي. وعندما تكتمل الميزة التي يجري تطويرها في أحد الفروع ستُدمج مع الفرع الرئيسيٍ، وبالتالي ستصبح هذه التغييرات أو الميزات الجديدة جزءًا من التطبيق الرئيسي. وهكذا سيتمكن كل مطور من العمل على مجموعة من التعديلات بحيث لا يعيق بقية المطورين من العمل على أفكارهم الخاصة قبل إكمال هذه التعديلات. لكن ما الذي سيحدث لبقية الفروع الخاصة بالمطورين الآخرين عندما يدمج أحد المطورين تعديلاته ضمن الفرع الرئيسي؟ إذ سيبتعد بقية المطورين عن النسخة القديمة التي يعملون عليها. وكيف سيعرف المطورون أن تعديلاتهم التي يجرونها على النسخة السابقة ستكون متوافقةً مع الحالة الجديدة التي يفرضها دمج التعديلات ضمن الفرع الرئيسي؟ سنحاول الإجابة عن هذا السؤال الجوهري في هذا القسم. يمكنك الاطلاع على مزيدٍ من المعلومات حول الفروع من خلال قراءة المقالة "أساسيات التفريع (Branching) والدمج (Merging) في Git". طلبات السحب Pull requests يجري عادةً دمج فرع ضمن الفرع الرئيسي وفق آلية تُعرف بطلب السحب، أو كما يُعرف أحيانًا بالاختصار "PR"، إذ يطلب المطور الذي أجرى بعض التعديلات أن تُدمج التعديلات التي أجراها ضمن الفرع الرئيسي، وحالما يُقبل هذا الطلب أو يُفتتح للمراجعة، يمكن لمطور آخر أن يتحقق من أن كل شيء سيجري على مايرام بعد الدمج. لو اقترحت مثلًا تعديلًا على مادة منهجنا، فقد قدمت فعلًا طلب سحب. بناء التطبيق Build لهذا المصطلح معانٍ مختلفة في لغات البرمجة المختلفة. فلا حاجة في بعض اللغات المترجمة، مثل روبي Ruby، أو بايثون Python إلى خطوة بناء فعلية إطلاقًا. عندما نتكلم عن البناء عمومًا، فإننا نعني بذلك إعداد التطبيق ليعمل على المنصة التي صُمِّم لأجلها، وقد يعني ذلك، على سبيل المثال، أننا لو أردنا كتابة التطبيق بلغة TypeScript ثم تنفيذه على Node، فستكون خطوة البناء هي عملية نقل شيفرة TypeScript إلى جافا سكربت JavaScript. ستغدو هذه الخطوة إجبارية وأكثر تعقيدًا في اللغات المُصرَّفة، مثل C و Rust، إذ تتطلب شيفرتها التصريف إلى شيفرة قابلة للتنفيذ. وكنا قد اطلعنا في القسم 7 على برنامج webpack، وهو أداةٌ رائدة حاليًا في بناء نسخ إنتاج من تطبيقات React أو تطبيقات واجهة أمامية مكتوبة بلغة جافاسكربت JavaScript أو TypeScript. نشر التطبيقات Deploy يشير مصطلح "النشر" إلى وضع التطبيق في المكان الذي يمكن للمستخدم النهائي الوصول إليه واستخدامه؛ فقد يعني هذا المصطلح بالنسبة للمكتبات مثلًا وضعها ضمن حزم ثم دفعها إلى أرشيف للحزم (مثل npmjs.com) بحيث يمكن للمستخدمين إيجادها وتضمينها في مشاريعهم. تختلف صعوبة نشر خدمة (مثل تطبيق ويب) حسب تعقيدها، فقد اشتمل مخططنا لنشر التطبيق في القسم 3 مثلًا على تنفيذ بعض السكربتات يدويًا ثم دفع شيفرة المستودع إلى خدمة استضافة Heroku. سنطور في هذا القسم "خط إنتاج" لنشر كل جزء من شيفرتك آليًا إلى Heroku إن لم تسبب هذه الشيفرة أية مشاكل. وقد يكون النشر أحيانًا على درجة عالية من التعقيد خاصةً إذا تطلب التطبيق احتياجات خاصة، كأن يكون متاحًا دائمًا للعمل أثناء تطويره "لا إيقاف من أجل النشر zero downtime deployment"، أو كان علينا أن نأخذ في الحسبان بعض الأمور مثل نقل قواعد البيانات. لن نغطي النقاط المتعلقة بالنشر الذي يحمل تعقيدات مثل التي ذكرناها، لكن من المهم أن تدرك وجودها. ما هو التكامل المتواصل؟ يختلف المفهوم الدقيق لمصطلح التكامل المتواصل Continuous Integration -أو اختصارًا "CI"- عن كيفية استخدامه في مجال التطوير. ستجد نقاشًا قديمًا لكنه يحمل أثرًا كبيرًا عن استخدام هذا المصطلح في مدونة "مارتن فلور". وإذا أردنا التحديد الدقيق للمصطلح CI سنقول أنه يعني غالبًا "دمج التغييرات التي نفذها المطور مع الفرع الرئيسي" ثم أضافت ويكيبيديا Wikipedia العبارة "عدة مرات في اليوم" إلى المصطلح. وهذا الأمر صحيح عادةً، لكن عندما نشير إلى CI في مجال البرمجيات، فنحن نتحدث غالبًا عما سيحدث بعد عملية الدمج الفعلية للتغيرات، إذ قد نحتاج إلى إنجاز بعضٍ من هذه الخطوات: التدقيق lint: للحفاظ على الشيفرة واضحة وقابلة للصيانة. البناء build: وضع كل الشيفرة المُنجزة في برنامج واحد. الاختبار test: لضمان عدم إخفاق أية ميزات موجودة مسبقًا. التحزيم packaging: وضع كل ما نحتاجه في حزمة سهل الحمل والنقل. التحميل/ النشر deploy: لجعل البرنامج متاحًا للاستخدام. سنناقش كل خطوة من تلك الخطوات (عندما نجد فائدةً من ذلك) بشيء من التفصيل لاحقًا. وعلينا أن نتذكر دائمًا أنّ هذه العملية ستكون محددةً بدقة. يعيق التحديد الدقيق strict definition عادةً سرعة التطوير أو الإبداع في إيجاد الحلول، لكن من المفترض أن لا يكون هذا صحيحًا بالنسبة للتكامل المتواصل، إذ يجب وضع هذه القيود بطريقة مرنة تسمح بالتطوير والعمل المشترك. سيسمح استخدام أنظمة CI جيدة، مثل GitHub Actions الذي سنغطيه في هذا القسم بتنفيذ كل ما ذكرناه آليًا وبصورة سحرية. التحزيم والنشر مثل جزء من نظام التكامل المتواصل CI ينبغي التذكير من حين إلى آخر، أنّ عملية التحزيم وعملية النشر خاصة لا تُعدان أحيانًا جزءًا من نظام CI، لكننا سنعدّهما جزءًا من النظام، لأنه من المنطقي في العالم الحقيقي أن نضع كل الخطوات التي أشرنا إليها معًا. ويعود جزءٌ من ذلك للحفاظ على التسلسل في سياق العمل وخط إنتاج البرنامج (الطريق إلى إيصال المنتج إلى المستخدم النهائي)، بينما يعود الأمر في شقه الآخر إلى حقيقة أنّ هذه النقطة هي ما يسبب إخفاق العملية ككل. ستظهر المشاكل غالبًا في مرحلة التحزيم من نظام CI كونها مرحلةٌ لا تختبر محليًا، فمن المنطقي إذًا اختبار عملية تحزيم المشروع خلال سير العمل في CI حتى لو لم نضع هذه الحزمة موضع العمل، كما يمكن في بعض مسارات العمل أن نختبر حزمةً قد بُنيت فعلًا مسبقًا. سيؤكد ذلك أننا اختبرنا الشيفرة بنفس الشكل الذي سننشرها فيه خلال مرحلة الإنتاج. إذًا ما هو وضع عملية النشر؟ سنتحدث عن الاستمرارية وإمكانية التكرار مطولًا في الفصول القادمة، لكن تجدر الإشارة هنا إلى أننا نحتاج إلى عملية تبدو متماثلةً دائمًا، سواءٌ أجرينا الاختبارات في فرع تطوير أو في الفرع الرئيسي. نحتاج في الواقع إلى العملية نفسها "حرفيًا" بحيث يظهر الاختلاف فقط في نهايتها، وذلك عند تحديد ما إذا كنا في الفرع الرئيسي أم لا، وإن كنا نريد النشر أم لا. وفي هذا السياق من المنطقي تضمين خطوة النشر في سير عمل CI طالما أنها ستخضع للصيانة في نفس الوقت الذي نطورها فيه. يشير المصطلحان: "التسليم المتواصل Continuous Delivery" و"النشر المتواصل Continuous Deployment" -أو اختصارًا CD- إلى منظومة CI عندما تتضمن مرحلة النشر. لن نزعجك بالتعريف الدقيق، إذ يمكنك الاطلاع عليه من خلال Wikipedia، أو منشورات مدونة "مارتن فلور"، أو من خلال أكاديمية حسوب، لكننا نستخدم الاختصار CD ليشير إلى أسلوب ممارسة عملي يقتضي إبقاء الفرع الرئيسي متاحًا للنشر والتطوير في أي وقت. لكن ماذا عن المنطقة الغامضة بين مصطلحي CI وCD؟ فلو كان علينا مثلًا أن نجري بعض الاختبارات قبل أن ندمج أية شيفرات جديدة ضمن الفرع الرئيسي، هل نعد ذلك شكلًا من أشكال CI لأننا سنجري دمجًا متواصلًا مع الفرع الرئيسي؟ أم شكلًا من أشكال CD لأننا نتحقق بذلك أن الفرع الرئيسي قابلًا للنشر باستمرار؟ تقع بعض المفاهيم إذًا على الخط الفاصل بين المصطلحين، فمن المنطقي كما أشرنا سابقًا، أن نعد CD جزءًا من CI. لهذا السبب، سيُستخدم غالبًا المصطلح CI/CD للدلالة على العملية برمتها. وانتبه إلى أننا سنستخدم المصطلحين CI و CI/CD بالتناوب طوال الوقت في هذا القسم. أين تكمن أهمية استخدام نظام CI؟ لقد ذكرنا سابقًا مشكلة "يعمل على جهازي" ومشكلة نشر تغييرات متعددة المصادر، لكن ماذا عن بقية المشاكل؟ ماذا لو حملّت "سارة" الشيفرة مباشرةً إلى الفرع الرئيسي؟ ماذا لو استخدم "أحمد" فرعًا ولم يكلف نفسه عناء إجراء بعض الاختبارات قبل دمج ما عدّله ضمن الفرع الرئيسي؟ ماذا لو حاول "عبد الله" بناء نسخة إنتاج من التطبيق لكن بمعاملات خاطئة؟ سيمكِّننا استخدام التكامل المتواصل وفق طريقة منهجية في العمل في: منع رفع الشيفرات مباشرةً إلى الفرع الرئيسي. تنفيذ عملية CI لكل طلبات السحب إلى الفرع الرئيسي وتمكينها من دمج التغييرات. بناء حزم إنتاج للبرامج التي نطورها في بيئة معروفة تمتلك نظام CI. وهنالك أيضًا بعض الإيجابيات لتوسيع هذه الإعدادات: إذا استخدمنا CD في كل مرةٍ ننفذ فيها عملية دمج مع الفرع الرئيسي، سنكون واثقين من عمل الفرع الرئيسي وفق نظام الإنتاج. إذا سمحنا بإتمام عملية الدمج فقط في الحالة التي يكون فيها الفرع الرئيسي محدّثًا، سنضمن أن لا يلغي المطورون التغييرات التي نفذها غيرهم. تنبيه: سنفترض في هذا القسم أن الشيفرة الموجودة في الفرع الرئيسي ("mian" أو "master") ستعمل وفق نظام الإنتاج. ونظرًا لوجود عدد هائل من مخططات العمل (workflows) على git، قد يكون هناك على سبيل المثال حالات يظهر فيها فرع خاص للإصدار release branch يحتوي على الشيفرة التي تعمل وفق نظام الإنتاج. مبادئ هامة من المهم أن نتذكر أنّ CI/CD ليس هدفًا بحد ذاته، لكن الهدف هو تطوير أسرع وأفضل للتطبيقات بأقل عددٍ من الثغرات، وتحقيق أفضل تعاون بين المطورين. ولهذا لا بدّ من تهيئة نظام CI بما يلبّي المهمة التي ننفذها والمشروع بحد ذاته، كما ينبغي أن نبقي الهدف الرئيسي من استخدامه في حساباتنا دائمًا. يمكننا التفكير بنظام CI بمثابة جوابٍ على الأسئلة التالية: كيف سنتأكد أنّ جميع الاختبارات ستُطبّق على كامل الشيفرة التي ستُنشر؟ كيف سنضمن جاهزية الفرع الرئيسي للنشر في كل الأوقات؟ كيف سنتأكد أنّ النسخ التي تُبنى ستكون متوافقة، وستعمل دائمًا على المنصات التي صُمِّمت للنشر عليها؟ كيف سنضمن أن التغييرات الجديدة لن تلغي التغييرات الأقدم؟ كيف سننجز عملية النشر بضغطة زر أو بطريقة آلية، عندما يدمج مطور التغييرات التي أجراها مع الفرع الرئيسي؟ وهناك أيضًا دلائل علمية على الفائدة الهائلة التي يقدمها نظام CI/CD، فبناءً على دراسة واسعة في كتاب ": Building and Scaling High Performing Technology Organizations"، يقترن استخدام CI/CD بشدة مع النجاحات على صعيد المؤسسات (تحسين الأرباح وجودة المنتج وزيادة الحصة السوقية وتقليل زمن التسويق)، وكذلك من ناحية المطورين، فقد جعلتهم أكثر سعادةً وأقل إرهاقًا. سلوك موثق تشيع في أوساط المبرمجين طرفةٌ مفادها أنّ الثغرات هي "ميزات غير موثقة". لكن يجب علينا تفادي أية حالات لا نعلم تمامًا نتيجتها. فلو اعتمدنا مثلًا على عنوان طلب السحب لنحدد ما إذا كان إصدار البرنامج رئيسيًا major، أو ثانويًا minor، أو ترميميًا patch (سنتحدث عن معنى كل إصدار لاحقًا)، سيكون علينا الانتباه إلى الحالة التي يُغفل فيها المطور من وضع عنوانٍ لطلب السحب الذي قدمه. وماذا لو وضع هذا العنوان بعد بدء عملية البناء أو الاختبار؟ أو أنه غيَّر العنوان خلال مرحلةٍ ما، فما الذي سيكون عليه هذا الإصدار؟ من الممكن أن تغطي جميع الحالات التي قد تتوقعها، ومع ذلك، قد تظهر بعض الثغرات عندما يُنفّذ المطور شيئًا "إبداعيًا" لم تتوقعه إطلاقًا، فمن الجيد إذًا أن تنتهي العملية التي ستخفق بأمان في هذه الحالة. فلو عدنا إلى المثال السابق عندما يغير المطور عنوان الطلب أثناء تنفيذ عملية البناء. إذا لم نتمكن من توقع سيناريو مثل هذا مسبقًا، فمن الأفضل ربما أن تتوقف عملية البناء، وأن نبلِّغ المستخدم بأنّ شيئًا غير متوقع قد حدث، فنشر إصدار خاطئ سينتج حتمًا مشاكلًا أكبر، وسيكون إيقاف العملية وإخطار المستخدم هو الحل الأكثر أمانًا. يحدث الشيء ذاته في كل مرة قد نملك أفضل اختبارات لبرمجياتنا يمكن تخيلها، وقد تكون قادرةً على اصطياد أية مشكلة محتملة، لكنها ستبقى عديمة الجدوى إن لم ننفذها على الشيفرة قبل نشرها. علينا أن نضمن أنّ الاختبارات قابلةً للتنفيذ، كما نريد أن نضمن أنها ستعمل مع الشيفرة التي سننشرها فعليًا. فلن يفيدنا الاختبار الذي ينجح مثلًا ضمن فرع "سارة" ويفشل عند دمجه مع الفرع الرئيسي. وطالما أننا سننشر محتويات الفرع الرئيسي، لذا علينا أن نتأكد من نجاح الاختبارات على نسخة من الفرع الرئيسي بعد أن ندمج معه فرع "سارة". ستوصلنا المناقشة السابقة إلى مبدأ جوهري وهو التأكد أنّ السلوك نفسه سيحدث كل مرة، أو أنّ المهام المطلوبة ستُنفَّذ جميعها وبالترتيب الصحيح. يجب أن تبقى الشيفرة قابلة للنشر دائما إنّ وجود شيفرة قابلة للتوزيع والنشر دائمًا أمر مريح جدًا وخاصةً عندما يحتوي الفرع الرئيسي على شيفرة تعمل في وضع الإنتاج؛ فإذا ظهرت ثغرةٌ مثلًا وتطلب الأمر معالجتها، يمكنك سحب نسخة من الفرع الرئيسي (وهي الشيفرة التي تُنفًّذ في وضع الإنتاج) وحل المشكلة، ثم تقديم طلب سحب لإعادة الشيفرة إلى الفرع الرئيسي (دمج من جديد). ويجري هذا الأمر عادةً مباشرةً دون أية مشاكل. إذا اختلفت الشيفرة الموجودة في الفرع الرئيسي عن شيفرة الإنتاج ولم يكن الفرع الرئيسي قابلًا للنشر، سيكون عليك البحث عن الشيفرة التي تعمل في وضع الإنتاج وسحب نسخة عنها، ثم إيجاد الثغرة ومعالجتها، كما عليك إيجاد طريقة لإعادة الشيفرة إلى الفرع الرئيسي والعمل على نشر الجزء المحدد الذي أصلحته. لن يكون هذا الأمر مريحًا وستكون طريقة تنفيذه مختلفةً كليًا عن مخطط نشر التطبيقات الاعتيادي. معرفة أجزاء الشيفرة المنشورة- مجموع SHA/الإصدار من المهم غالبًا تحديد الشيفرة التي تعمل فعليًا في وضع الإنتاج. ولقد ناقشنا سابقًا أن شيفرة الفرع الرئيسي هي من تعمل في هذا الوضع في الحالة النموذجية، لكن هذا الأمر ليس ممكنًا دائمًا؛ فقد تتعرض عملية البناء للإخفاق عندما نحاول تشغيل شيفرة الفرع الرئيسي في وضع الإنتاج، وقد نجري عدة تغييرات على الشيفرة ونريدها أن تُنشر جميعها مباشرةً. ما نحتاج إليه في حالات مثل هذه (وهي فكرة جيدة عمومًا)، هو معرفة الشيفرة التي تعمل في وضع الإنتاج بالضبط؛ إذ يمكن معرفة ذلك أحيانًا عن طريق رقم الإصدار version، وأحيانًا بمجموع SHA sum (وهو جدول HASH يعرِّف بصورةٍ فريدة اعتماد git) متصل بالشيفرة. سنناقش موضوع تحديد رقم الإصدار لاحقًا في هذا القسم. الآلية الأكثر فائدةً هي ربط معلومات الإصدار مع تاريخ جميع الإصدارات، فلو اكتشفنا مثلًا وجود ثغرة في اعتماد محدد، يمكننا أن نعرف متى أُصدر هذا الاعتماد وكم عدد المستخدمين الذين تأثروا بالثغرة. وتظهر فائدة هذه المقاربة عندما تسبب الثغرة أخطاءً في بيانات قواعد البيانات، وهكذا من الممكن تقفي أثر البيانات الخاطئة بناءً على تاريخ إنشائها. أنماط إعدادات منظومة CI علينا تخصيص خادم منفصل لتشغيل مهام منظومة التكامل المتواصل CI لكي نلبي بعضًا من المتطلبات التي ذكرناها سابقًا، إذ سيقلل وجود خادم منفصل المخاطر الناتجة عن اختلاط عمليات أخرى بعملية منظومة CI/CD جاعلةً نتيجتها غير متوقعة. هنالك خياران: استضافة خادم خاص بنا أو الخدمة السحابية cloud service. استضافة Jenkins وإعدادات بيئة الاستضافة الذاتية self-host تُعد استضافة Jenkins الخيار الأكثر شعبيةً من بين خيارات الاستضافة الذاتية، فهي مرنةٌ جدًا وتمتلك عدة إضافات plugin لكل شيء تقريبًا (ماعدا الشئ الوحيد الذي تريده). تمثل هذه الاستضافة خيارًا جيدًا للعديد من التطبيقات. يعني استخدام الاستضافة الذاتية أن تكون بيئة الاستضافة تحت سيطرتك بالكامل، وكذلك جميع الموارد، ولن تكون أسرارك عرضةً للكشف من قبل الآخرين، كما ستتمكن من فعل ما تشاء بالعتاد الصلب. لكن ولسوء الحظ هناك جانبٌ مظلم لاستضافة Jenkins فهي صعبة الإعداد، إذ تتطلب المرونة الكبيرة في الإعداد وجود العديد من قوالب template الشيفرة التي تتطلب الإعداد ليعمل كل شيء، ويتطلب استخدام Jenkins بالتحديد إعداد منظومة CI/CD باستخدام لغة Jenkins الخاصة بالنطاق domain-specific. ولا ننس مخاطر إخفاق العتاد الصلب والذي قد يسبب مشكلةً في حالات الازدحام. تعتمد فاتورة الاستضافة الذاتية على العتاد الصلب الذي تختاره غالبًا، فأنت تدفع مقابل الخادم وما ستفعله على الخادم لن يغير من فاتورتك. استخدام GitHub Actions وحلول أخرى معتمدة على الاستضافة السحابية لن تضطر للتفكير كثيرًا عند إعداد بيئة الاستضافة في الاستضافة السحابية، فكل ما عليك فعله هو أن تطلب من الاستضافة ما تريده، ويتضمن ذلك عادةً وضع ملف في مستودعك (ثم إخبار منظومة CI بقراءته)، أو التحقق من وجود ملف كهذا في المستودع. سيكون ملف تهيئة CI في الاستضافة السحابية أبسط قليلًا، وخاصةً إن لم تتعدّى الحدود "الطبيعية" للاستخدام، لكن قد تغدو خيارات هذه الإستضافة محدودةً قليلًا إن أردت فعل أشياء خاصة بين الفينة والأخرى، أو قد تجد صعوبةً في ذلك، خاصةً في إنجاز مهام محددة لم تُبنى المنصة السحابية لكي تنجزها. سنركز في هذا القسم على الاستخدامات التي تعد "طبيعية"، فقد تتطلب إعدادات بعض المهام الخاصة عتادًا صلبًا خاصًا على سبيل المثال. وبعيدًا عن إعدادات التهيئة التي ذكرناها سابقًا، قد تواجهنا مشاكلًا تتعلق بمحدودية الموارد على الاستضافة السحابية، فلو بدت النسخة بطيئة على الاستضافة الذاتية، يمكنك ببساطة حجز خادم أقوى وتضع ما تحتاجه من الموارد ضمنه، لكن هذا الأمر قد يكون مستحيلًا في الاستضافة السحابية. ستعمل العقد التي تبنيها في GitHub Actions مثلًا على معالجين افتراضيين (vCPU) و8 جيجابايت من ذواكر الوصول العشوائي. ستعتمد فاتورتك في الاستضافة السحابية على الوقت المستغرق في بناء تطبيقك، وهذا أمر يجدر أخذه بالحسبان. لماذا نفضل خيارا على آخر؟ إن كان مشروعك صغيرًا إلى متوسط الحجم ولن يحتاج أية متطلبات خاصة (مثل الحاجة إلى بطاقة رسومية لتنفيذ الاختبارات)، ستكون الاستضافة السحابية الحل المناسب غالبًا، إذ ستكون الإعدادات بسيطةً ولن تدخل دوامة إعدادات النظام الخاص بك، كما ستكون الكلفة أقل للمشاريع الصغيرة خاصة؛ أما بالنسبة للمشاريع الأضخم والتي تحتاج إلى موارد أكبر أو بالنسبة للشركات الكبيرة التي تضم عدة فرق للتطوير وعدة مشاريع، قد يكون اختيار منظومة استضافة ذاتية هو الخيار الأنسب. لماذا استخدمنا GitHub Actions في هذه السلسلة؟ يُعدّ GitHub Actions الخيار الأنسب كوننا نستخدم غيت هب GitHub، إذ سيؤمن لنا منظومة CI قوية تعمل مباشرةً دون الحاجة إلى إعداد خادم أو خدمة سحابية يؤمنها طرف ثالث. إضافةً إلى سهولة استخدامه، يُعد GitHub Actions خيارًا جيدًا من عدة جوانب، فقد يكون أفضل خدمة سحابية موجودة حتى اللحظة، إذ يحظى بشعبية كبيرة منذ إصدار النسخة الأساسية منه في نوفمبر (تشرين الثاني) عام 2019. التمرين 11.1 قبل أن ننغمس في إعداد خطوط إنتاج لأنظمة CI/CD، لا بدّ من مراجعة ما قرأناه. لنتهيأ للانطلاق فكر بحالة افتراضية نكون فيها أمام تطبيق يجري تطويره من قِبل فريق من 6 مطورين وسيصدر قريبًا. لنفترض أنّ اللغة المستخدمة في تطوير التطبيق ليست JavaScript/TypeScript فلنقل Python، أو Java، أو Ruby، أو أية لغات قد تفكر بها. اكتب موضوعُا بسيطًا من 200-300 كلمة تجيب فيه أو تناقش النقاط التي سنطرحها تاليًا. يمكنك التحقق من عدد الكلمات التي تكتبها عبر موقع wordcounter. خزّن إجابتك في ملف اسمه "exercise1.md" في جذر المستودع الذي ستنشئه في التمرين 11.2 ناقش النقاط التالية: بعض الخطوات الشائعة في إعداد CI بما فيها التدقيق والاختبار والبناء، وكذلك الأدوات اللازمة لتنفيذ هذه الخطوات في بيئة عمل اللغة التي تختارها. يمكنك البحث عن الأجوبة عبر غوغل Google. ما هي بدائل إعداد منظومات CI عن GitHub Actions أو Jenkins؟ يمكنك الاستعانة بمحرك البحث غوغل. أين سيكون تطبيق هذه الإعدادات أفضل، على استضافة ذاتية أو استضافة سحابية؟ لماذا؟ ما هي المعلومات التي ستحتاجها لاتخاذ قرارك؟ تذكر أنه لا توجد إجابات صحيحة أو خاطئة لجواب هذا السؤال. ترجمة -وبتصرف- للفصل Introduction to CICD من سلسلة Deep Dive Into Modern Web Development اقرأ أيضًا ما هو Git إعادة تأسيس تفريعات طلب السحب وتحديثه في git إعداد التكامل المستمر والنشر المستمر باستخدام الخدمتين CircleCI وCoveralls التكامل المستمر: تثبيت Concourse CI على أوبنتو
  6. انصب تركيزنا في هذا القسم على بناء منظومة تكامل مستمر CI بسيطة وفعالة ومحكمة، تساعد المطورين على العمل معًا والحفاظ على جودة الشيفرة ومن ثم نشرها بأمان. ما الذي يمكننا فعله أكثر؟ لنتذكر أنه في العالم الحقيقي ستمتد أيادٍ إلى الكعكة غير أياد المطورين والمستخدمين. حتى وإن لم يكن ذلك صحيحًا، وخاصة بالنسبة للمطورين، إلا أنّ هناك الكثير الذي تقدمه منظومة CI غير ما اطلعنا عليه. مجال الرؤية والفهم في جميع الشركات ما عدا الصغيرة منها، لا تُتخذ القرارات حول تطوير المنتجات حصرًا من طرف المطورين. يشير مصطلح أصحاب الشأن "stakeholder" إلى الأشخاص داخل وخارج فريق التطوير، الذين لديهم مصلحة في مراقبة تقدم عملية التطوير.عند هذا المستوى، هناك غالبًا تكاملٌ بين git وأي برنامج لإدارة المشاريع أو تتبع الثغرات قد يستخدمه الفريق. يُعد امتلاك مرجع إلى نظام التتبع في طلبات السحب أو في الشيفرة المعتمدة أكثر الطرق شيوعًا لتنفيذ ذلك. وهكذا، عندما تعمل على النقطة رقم 123 مثلًا، بإمكانك عندها تسمية طلب السحب الخاص بك BUG-123: Fix user copy issue، وسيلاحظ نظام تتبع الثغرات عندها الجزء الأول من اسم طلب السحب، وسينقل النقطة إلى قائمة النقاط المنفَّذة Done عندما يُدمج الطلب. تنبيهات عندما تنتهي عملية CI بسرعة، فمن المناسب أن نراقب العملية فقط وننتظر النتائج، لكن مع ازدياد حجم المشاريع ستزداد أيضًا فترة تنفيذ عمليات بناء واختبار الشيفرة. سيقودنا ذلك إلى الحالة التي تستغرق فيها ظهور نتائج بناء الشيفرة وقتًا طويلًا، مما يدفع المطور للتفكير في العمل على مهمة أخرى، وهذا سيقود بدوره إلى نسيان عملية البناء. ستظهر المشكلة في طرحنا هذا خاصة عندما نتحدث عن دمج طلبات السحب التي قد تؤثر على عمل مطور آخر، إما بالتسبب بمشاكل في عمله أو تأخير هذا العمل. وقد يقودنا ذلك أيضًا إلى الحالة التي تعتقد فيها أنك نشرت شيئًا، لكنك في الواقع لم تنهي عملية النشر، وسيؤدي ذلك إلى سوء التواصل مع أعضاء فريقك أو مع الزبائن (كأن تقول: "جرب من جديد، لا بدّ أنّ المشكلة قد حُلَّت"). هناك عدة أساليب لحل هذه المشكلة، تتدرج من إنشاء تنبيهات بسيطة إلى عمليات أكثر تعقيدًا تدمج ببساطة الشيفرة التي تمرر إليها إن تحققت جملةٌ من الشروط الموضوعة مسبقًا. سنناقش حاليًا التنبيهات مثل حل بسيط، كونها الوحيدة التي تتعلق بسير مخطط عمل الفريق. يرسل غيت هب افتراضيًا بريدًا إلكترونيًا عند إخفاق البناء. يمكن تغيير ذلك لإرسال تنبيهات بغض النظر عن حالة البناء، كما يمكن تهيئته لإنذارك على واجهة ويب غيت هب GitHub. طبعًا هذا الأمر رائع، لكن ماذا لو أردنا أكثر من ذلك؟ ماذا لو لم يعمل هذا الحل لسببٍ ما مع حالتنا؟ يمكن أن يتكامل غيت هب GitHub مع عدة تطبيقات رسائل مثل Slack لإرسال التنبيهات، وستكون هذه التطبيقات قادرةً على تحديد متى ترسل هذه التنبيهات بناءً على منطق يفرضه غيت هب GitHub. التمرين 11.18 أعددنا قناة fullstack_webhookعلى مجموعة Discord على العنوان "https://study.cs.helsinki.fi/discord/join/fullstack" لاختبار تكامل منظومة الرسائل. ستحتاج طبعًا إلى بريد إلكتروني للتسجيل، وانتبه إلى ضرورة استخدام عنوان خطاف الويب webhook الخاص بالتطبيق Discord لتنفيذ هذا التمرين. ستجد هذا الخطاف في الرسالة المنبثقة القناة "fullstack_webhook". ويُستحسن عدم الالتزام بالخطاف على غيت هب GitHub. أفعال لتنبيه المستخدم إلى نجاح أو فشل البناء ستجد العشرات من أفعال GitHub Actions التي طورها مطورون مستقلون على GitHub Action Marketplace بمجرد أن تبحث عن العبارة discord. اختر واحدًا لتستخدمه في هذا التمرين. وقد اخترنا discord-webhook-notify لأنه حصل على تقييم مرتفع وله توثيق جيد. هيئ الفعل بحيث يعطي نوعين من التنبيهات: مؤشر على النجاح إن نُشرت النسخة. مؤشر على الفشل إن أخفق البناء. في حال وقوع خطأ، لا بدّ أن تكون رسالة الخطأ مسهبة لمساعدة المطور على إيجاد الخطأ بسرعة وإيجاد الشيفرة المعتمدة التي سببت هذا الخطأ. ابحث في توثيق GitHub عن كيفية التحقق من حالة المهمة. يمكن أن تبدو التنبيهات على النحو التالي: المقاييس Metrics لقد أشرنا في الفقرة السابقة أنه عندما ينمو المشروع ستزداد مدة إنجاز خطوات البناء والاختبار، وهذا ليس بالأمر المثالي، فكلما طالت حلقة وصول النتائج ستصبح دورة التطوير بطيئة. وعلى الرغم من إمكانية القيام بأشياء لتقليل الوقت اللازم للبناء، من المفيد أيضًا أن ننظر جيدًا إلى الصورة الكلية للوضع. فمن الجيد أن نعرف كم استغرقت عملية البناء قبل أشهر عدة موازنةً مع ما تستغرقه الآن. هل يسلك الاختلاف منحًى خطيًا أم يظهر على هيئة قفزات فجائية؟ كما أنّ معرفة السبب الكامن خلف زيادة زمن البناء سيساعدنا جدًا في حل المشكلة؛ فإذا زاد زمن التنفيذ على نحوٍ خطي من 5 إلى 10 دقائق خلال سنة، فيمكننا أن نتوقع بأنه سيزداد أيضًا بضع دقائق خلال عدة أشهر قادمة ليصل إلى 15 دقيقة، وستكون لدينا فكرةً عن قيمة ما ننفقه من وقت لتسريع عمل منظومة CI. يمكن أن تكون المقاييس ذاتية- التسجيل self-reported وتدعى أيضًا مقاييس "دفع-Push"، إذ تسجل كل عملية بناء الوقت الذي تستغرقه، أو أن نحضر البيانات من واجهة برمجية بعد انتهاء العملية وتدعى أحيانًا مقاييس "سحب-Pull". يتمثل خطر التسجيل الذاتي في الوقت الذي ستستغرقه عملية التسجيل بحد ذاتها، والتي قد يكون لها أثر على الوقت الكلي المستغرق للبناء. يمكن أن تُرسل هذه البيانات إلى قاعدة بيانات تعمل وفق سلاسل زمنية time-series DB، أو إلى سِجِل من نوع آخر. هناك عدة خدمات سحابية لتجميع قياساتك بكل سهولة، ومن الخيارات الجيدة الخدمة Datadog. المهام الدورية هناك بعض المهام الدورية التي يجب تنفيذها ضمن فرق تطوير البرمجيات، إذ يمكن أتمتة بعضها من خلال بعض الأدوات المتوفرة، وعليك أتمتة بعضها الآخر. تتضمن الفئة الأولى من المهام الدورية التحقق من الحزم لتفادي الاختراقات الأمنية، وقد تساعدك في ذلك العديد من الأدوات الجاهزة. سيكون بعض هذه الأدوات مجانيًا لمشاريع محددة (مفتوحة المصدر مثلًا) مثل الأداة Dependabot التي يقدمها GitHub. وإليك النصيحة التالية: من الأفضل دائمًا استخدام أدوات جاهزة لأداء هذه المهام، إن سمحت بذلك ميزانيتك، بدلًا من الاعتماد على حلولك الخاصة، فإن لم تكن مهتمًا بتطوير أدوات تتعلق بأمور الأمن مثلًا، استخدم Dependabot للتحقق من الثغرات الأمنية بدلًا من تطوير الأداة بنفسك. لكن ماذا عن المهام التي لا تتوفر لها أدوات مساعدة؟ يمكنك أتمتة هذه المهام بنفسك عن طريق GitHub Actions أيضًا، إذ يزودك GitHub Actions بمُطلِقات أحداث المجدولة scheduled trigger التي يمكن استخدامها لتنفيذ مهمة محددة في وقت محدد. التمارين 11.19 -11.21 11.19: التحقق الدوري من سلامة البرمجيات لدينا الثقة الآن بأنّ خط الإنتاج الذي عملنا عليه سيمنع نشر الشيفرة المخفقة، لكن مع ذلك هناك مصادر عديدة للأخطاء؛ فعندما يعتمد تطبيقنا مثلًا على قاعدة بيانات قد لا تكون متوفرة دائمًا، سيتوقف التطبيق عن العمل في لحظةٍ ما. لهذا من المفيد جدًا التحقق دوريًا من سلامة عمل التطبيق عن طريق إرسال طلب HTTP-GET إلى الخادم. ندعو هذه العملية عادة بعملية التحقق من الاتصال "ping". من الممكن أن نجدول أفعال GitHub لتُحدّث دوريًا وبصورة منتظمة. استخدم الفعل url-health-check أو أي بديل له وجدول عملية التحقق من الخادم الذي تنشر عليه التطبيق. حاول محاكاة الحالة التي يخفق فيها تطبيقك، تأكد حينها أن عملية التحقق ستكتشف الخطأ. اكتب مخطط العمل الدوري الذي أوجدته على ملف خاص. تنبيه: سيستغرق GitHub Actions وقتًا طويلًا حتى يبدأ بتنفيذ مخطط العمل الذي جدولته للمرة الأولى، فقد تطلب منا الأمر قرابة الساعة، لذلك تُعد فكرة إطلاق مخطط العمل مباشرةً بتنفيذ عملية دفع للشيفرة إلى الاستضافة فكرةً جيدة. انتقل بعد ذلك لتنفيذ المخطط المجدول بعد أن تنجح معك هذه الحيلة. تنبيه: عندما تنجح في تنفيذ ما طلبناه، من الأفضل أن تقلل مرات التحقق من الاتصال مع الخادم إلى مرة كل 24 ساعة أو عطل القاعدة، وإلا ستكلفك عملية التحقق المستمرة ساعاتك المجانية المتاحة خلال الشهر. 11.20: خط إنتاج خاص بك ابنِ خط إنتاج CI/CD لبعض التطبيقات التي أنجزتها سابقًا. من التطبيقات المرشحة للعمل عليها تطبيق دليل الهاتف الذي طورناه في القسمين 2 و3 من المنهاج، أو تطبيق المدونة الذي طورناه في القسم 4 والقسم 5، أو تطبيق الطرائف الذي بنيناه بالاستعانة بالمكتبة Redux في القسم 6. ستضطر غالبًا إلى إعادة هيكلية التطبيق لتجمع قطع الشيفرة المتفرقة، وعليك في الخطوة الأولى وضع الواجهتين الأمامية والخلفية في مستودع واحد. لست مجبرًا على ذلك طبعًا، لكنه سيسهل عليك الأمر كثيرًا. إحدى الهيكليات المقترحة هي وضع الواجهة الخلفية في جذر المستودع وأن تضع الواجهة الخلفية ضمن مجلد فرعي، ويمكنك أيضًا نسخ ولصق بنية التطبيق النموذجي الذي نفذناه في هذا القسم، أو أن تحاول الاستفادة من التطبيق النموذجي الذي اطلعنا عليه في القسم 7. ربما من الأفضل أن تنشئ مستودعًا جديدًا لهذا التمرين، ومن ثم تنسخ وتلصق الشيفرة ضمنه. قد تضطر غالبًا في العمل الواقعي إلى تنفيذ ذلك ضمن المستودع القديم، لكن الإنطلاقة الجديدة الآن ستسهل علينا الأمر. سيستغرق منك هذا التمرين وقتًا وجهدًا، لكن الحالة التي تواجهها هنا، وهي بناء خط إنتاج لنشر شيفرة قديمة، شائعة جدًا في الحياة العملية. لن يُنفّذ هذا التمرين في نفس المستودع الذي نفذت فيه التمارين السابقة، لأنك لا تستطيع أن تعيد سوى مستودع واحد إلى منظومة تسليم التمارين، ضع رابطًا إذًا للمستودع الآخر ضمن المستودع الذي أشرت إليه في نموذج التسليم. 11.21: حماية الفرع الرئيسي وتقديم طلب سحب احمِ الفرع الرئيسي للمستودع الذي أنجزت فيه التمرين السابق، وامنع المدراء أيضًا هذه المرة من دمج الشيفرة مع الفرع الرئيسي دون مراجعتها. قدم طلب سحب، واطلب من أحد مستخدمي GitHub التالية أسماؤهم mluukkai و/ أو kaltsoon أن يراجع شيفرتك، وبعد أن تنتهي المراجعة، ادمج الشيفرة مع الفرع الرئيسي، وانتبه إلى أن يكون المراجع من المتعاونين معك في المستودع. اتصل بنا على Discord لكي نراجع شيفرتك، ومن الأفضل إرسال رسالة خاصة تتضمن رابط دعوة. بعدها يكون العمل قد أُنجز. ترجمة -وبتصرف- للفصل Expanding further من سلسلة Deep Dive Into Modern Web Development اقرأ أيضًا المقال التالي: مدخل إلى الحاويات المقال السابق: نشر إصدارات التطبيق بأمان في منظومة التكامل والتسليم المستمر نشر التطبيقات وتوزيعها وفق نهج التسليم المستمر إعداد التكامل المستمر والنشر المستمر باستخدام الخدمتين CircleCI وCoveralls
×
×
  • أضف...