تطور CI في فريق تطوير الأجهزة المحمولة

اليوم ، يتم تطوير معظم منتجات البرمجيات في فرق. يمكن تقديم شروط النجاح لتطوير الفريق في شكل مخطط بسيط.



بعد كتابة الكود ، يجب عليك التأكد من أنه:

  1. إنه يعمل.
  2. إنه لا يكسر أي شيء ، بما في ذلك الكود الذي كتبه زملاؤك.

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

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

  • الناس غالية الثمن . ساعة عمل أي مبرمج أغلى من ساعة عمل أي خادم.
  • الناس مخطئون . لذلك ، قد تنشأ المواقف عندما يجرون اختبارات على الفرع الخطأ أو يجمعون الالتزام الخطأ للمختبرين.
  • الناس كسول . بشكل دوري ، عندما أنتهي من مهمة ما ، لدي فكرة: "لكن ما الذي يجب التحقق منه؟ كتبت سطرين - كل شيء يعمل! أعتقد بالنسبة لبعضكم أن هذه الأفكار تتبادر إلى الذهن في بعض الأحيان. ولكن عليك دائما أن تحقق.

يقول نيكولاي نيستيروف ( nnesterov ) - مشارك في جميع التغييرات التطورية لتطبيق CI / CD Android: تم تقديم وتطوير التكامل المستمر في فريق تطوير Avito المحمول ، وكيف حصلوا على 0 إلى 450 مجموعة في اليوم ، وأن آلات البناء تجمع 200 ساعة في اليوم. .

تم بناء القصة على مثال فريق Android ، ولكن معظم النهج تنطبق على نظام iOS أيضًا.


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

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



يُعرف مفهوم تدفق Git: يوجد فرع تطوير مشترك واحد في المشروع ، ولكل ميزة جديدة ، يقوم المطورون بقطع فرع منفصل ، والالتزام به ، ودفعه ، وعندما يرغبون في ضخ الشفرة الخاصة بهم في فرع التطوير ، فتح طلب السحب. لمشاركة المعرفة ومناقشة الطرق ، قدمنا ​​مراجعة للشفرة ، أي أنه يجب على الزملاء التحقق من كود بعضهم البعض وتأكيده.

الشيكات


مشاهدة الكود بعينيك أمر رائع ، لكن ليس كافيًا. لذلك ، يتم تقديم الشيكات التلقائية.

  • بادئ ذي بدء ، نتحقق من تجميع ARC .
  • الكثير من اختبارات Junit .
  • نحن نعتبر تغطية الشفرة ، لأننا نجري الاختبارات.

لفهم كيفية تشغيل هذه الاختبارات ، دعنا ننظر إلى عملية التطوير في Avito.

من الناحية التخطيطية ، يمكن تمثيلها على النحو التالي:

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

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

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

إذا كانت عمليات الفحص تمنع طلب السحب ، فهناك دافع كافٍ ، لأنه حتى تتحول البنى إلى اللون الأخضر ، لن يتم تطوير الرمز ، مما يعني أن المهمة لن تكتمل.

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

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

استغرقنا يومين لاستكمال إعداد CI الأساسي (فيما يلي ، تقدير مؤقت تقريبي ، مطلوب للقياس).

بعد ذلك ، بدأوا يفكرون أكثر - هل نتحقق منه بشكل صحيح؟ هل نطلق برامج بناء على طلب السحب بشكل صحيح؟

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



للقيام بذلك ، كتبنا premerge.sh النصي باش بسيط :

#!/usr/bin/env bash set -e git fetch origin develop git merge origin/develop 

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

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

تم تطوير التطبيق ، وظهور المزيد والمزيد من المهام ، ونما الفريق ، وبدأت في بعض الأحيان تهدئة premerge.sh. في تطوير اخترقت التغييرات المتعارضة التي كسرت التجمع.

مثال على كيفية حدوث ذلك:



يبدأ مطوران في نفس الوقت ببدء نشر الميزات A و B. يكتشف مطور الميزة A وظيفة answer() غير المستخدمة في المشروع ، ويؤدي إلى إزالتها ، مثل الكشف الجيد. في الوقت نفسه ، يضيف مطور الميزة ب مكالمة جديدة لهذه الوظيفة في فرعه.

المطورين الانتهاء من العمل وفي الوقت نفسه فتح طلب السحب. يبني البداية ، يقوم premerge.sh بالتحقق من كلا طلب السحب لحالة تطوير جديدة - كل عمليات الفحص باللون الأخضر. بعد أن يتم دمج ميزات طلب السحب A ، يتم دمج ميزات طلب السحب B ... Boom! تطوير فواصل لأنه في رمز التطوير هناك دعوة إلى وظيفة غير موجودة.



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

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



نظرًا لأن هذا لم يناسبنا ، بدأنا في إعداد خيارات حول كيفية منع ذلك.

كيف لا كسر تطوير


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

لفهم المدة التي سيستغرقها الأمر ، فكر في مثال مع اثنين من الممثلين. نفتح اثنين من العلاقات العامة: اثنين يبني ، واثنين من إطلاق الاختبار. بعد سكب العلاقات العامة الأولى في التطوير ، يجب إعادة بناء الثانية. في المجموع ، تستغرق عمليتا إطلاق الشيكتان PR ثلاثة PRS: 2 + 1 = 3.

من حيث المبدأ ، هذا طبيعي. لكننا نظرنا إلى الإحصاءات ، وكان الوضع المعتاد في فريقنا هو 10 مستفيدين أساسيين مفتوحين ، ثم عدد الشيكات هو مجموع التقدم: 10 + 9 + ... + 1 = 55. وهذا يعني ، من أجل قبول 10 PRS ، تحتاج إلى إعادة بناء 55 مرة. وهذا في وضع مثالي ، عندما تمر جميع الشيكات في المرة الأولى ، عندما لا يفتح أي شخص طلب سحب إضافي أثناء معالجة هذه الشيكات.

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

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

ونتيجة لذلك ، بقي الخيار الثالث فقط - إلى دورة . جميع الكود لدينا ، يتم تخزين جميع مصادرنا في المستودع في خادم Bitbucket. وفقا لذلك ، كان لدينا لتطوير البرنامج المساعد ل Bitbucket.



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



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

قبل تنفيذ هذا البرنامج المساعد ، كان لدينا متوسط ​​2.7 اختبار تشغيل لكل طلب سحب. مع البرنامج المساعد كان هناك 3.6 إطلاق. انها مناسبة لنا.

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

استغرقنا أسبوعين لكتابة الإصدار الأول من البرنامج المساعد لـ Bitbucket.

الشيكات الجديدة


وفي الوقت نفسه ، واصل فريقنا النمو. تم إضافة الشيكات الجديدة.

فكرنا: لماذا إصلاح الأخطاء إذا كان يمكن الوقاية منها؟ وهكذا قدموا تحليل الكود الثابت . لقد بدأنا باستخدام الوبر ، والذي تم تضمينه في Android SDK. لكن في ذلك الوقت لم يكن يعرف كيفية التعامل مع كود Kotlin على الإطلاق ، ولدينا بالفعل 75 ٪ من التطبيق المكتوب في Kotlin. لذلك ، تمت إضافة اختبارات Android Studio المدمجة إلى الوبر .

للقيام بذلك ، كان عليّ أن أكون منحرفًا جدًا: خذ Android Studio ، وحزمه في Docker وقم بتشغيله على CI بجهاز عرض افتراضي حتى ظن أنه يعمل على كمبيوتر محمول حقيقي. لكنها نجحت.

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

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

مختبر اختبار Firebase


تم اختياره لأن Firebase هو منتج من منتجات Google ، أي أنه يجب أن يكون موثوقًا به ومن غير المرجح أن يموت. الأسعار معقولة: 5 دولارات في الساعة لجهاز حقيقي ، 1 دولار في الساعة لمحاكي.

استغرق الأمر حوالي ثلاثة أسابيع لتنفيذ مختبر اختبار Firebase في CI.

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

عامل الميناء + بيثون + باش


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

استغرق الأمر خمسة أسابيع لإنشاء بيئة الاختبار الخاصة بنا.

نتيجةً لذلك ، كان لكل طلب سحب قائمة فحص دمج شاملة وممنوعة:

  • جمعية ARC ؛
  • اختبارات Junit
  • الوبر.
  • الشيكات ستوديو أندرويد ؛
  • اختبارات الأجهزة
  • اختبارات لقطة الشاشة.

هذا يمنع العديد من الأعطال المحتملة. من الناحية الفنية ، نجح كل شيء ، لكن المطورين اشتكوا من أن انتظار النتائج طويل جدًا.

كم طويل؟ قمنا بتحميل البيانات من Bitbucket و TeamCity إلى نظام التحليل وأدركنا أن متوسط ​​وقت الانتظار هو 45 دقيقة . وهذا هو ، المطور ، فتح طلب سحب ، في المتوسط ​​تتوقع نتائج البناء من 45 دقيقة. في رأيي ، هذا كثير ، ولا يمكنك العمل بهذه الطريقة.

بالطبع ، قررنا تسريع جميع بنينا.

تسريع


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

نزيل الشيكات الطويلة جدا


تكاملنا المستمر يمكن أن يصاب بهذه الأنواع من الأخطاء والمشكلات.

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

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

بناءً على هذا التصنيف ، هزنا قائمة الشيكات بأكملها. شطب Lint وأرجأ إطلاقه ليلا: فقط بحيث يقدم تقريرا عن عدد المشاكل في المشروع. اتفقنا على العمل بشكل منفصل مع الدين الفني ، لكننا رفضنا تمامًا الشيكات Android Studio . يبدو أن تطبيق Android Studio لتشغيل Docker مثير للاهتمام ، لكنه يثير الكثير من المتاعب في الدعم. أي تحديث لإصدارات Android Studio هو معركة ضد الأخطاء الغامضة. كان من الصعب أيضًا الحفاظ على اختبارات لقطات الشاشة ، لأن المكتبة لم تعمل بثبات شديد ، فقد كانت هناك إيجابيات كاذبة. تمت إزالة اختبارات لقطة الشاشة من قائمة الشيكات .

نتيجة لذلك ، غادرنا:

  • جمعية ARC ؛
  • اختبارات Junit
  • اختبارات الأجهزة.


التخزين المؤقت عن بعد


بدون عمليات تفتيش ثقيلة ، تحسنت الأمور. ولكن ليس هناك حد الكمال!

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

ذاكرة التخزين المؤقت عن بُعد Gradle هي خدمة يمكنها إنشاء أدوات تشفير مؤقتة للمهام الفردية في وحدات منفصلة. Gradle ، بدلاً من تجميع الشفرة فعليًا ، يقرع ذاكرة التخزين المؤقت عن بُعد عبر HTTP ويسأل عما إذا كان شخص ما قد قام بهذه المهمة بالفعل. إذا كان الأمر كذلك ، فما عليك سوى تنزيل النتيجة.

يعد بدء التخزين المؤقت عن بعد Gradle أمرًا سهلاً لأن Gradle يوفر صورة Docker. تمكنا من القيام بذلك في ثلاث ساعات.

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

يوجد أدناه رسم بياني لتفقد ذاكرة التخزين المؤقت.



في البداية ، كانت النسبة المئوية للمخططات التي تجاوزت ذاكرة التخزين المؤقت حوالي 65. وبعد ثلاثة أسابيع ، تمكنا من رفع هذه القيمة إلى 20٪. اتضح أن المهام التي يجمعها تطبيق أندرويد لها تبعيات متعدية غريبة ، بسبب غاب عن Gradle ذاكرة التخزين المؤقت.

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

تحليل التأثير


بناءً على طلب السحب ، نبني فرق git ونجد وحدات Gradle المعدلة.



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

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

استغرق الأمر حوالي ثمانية أسابيع لتحديث اختبارات الأجهزة لاختبار فقط الوحدات المعنية.

لقد عملت تدابير تسريع التحقق بنجاح. من 45 دقيقة وصلنا إلى ما يقرب من 15. ربع ساعة في انتظار بناء أمر طبيعي بالفعل.

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



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



أمضيت ستة أسابيع على ردود فعل مفصلة.

خطط


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

بالإضافة إلى ذلك ، هناك خطط أخرى.

  • عودة ينت (والتحليلات الساكنة الأخرى). نحن نعمل بالفعل في هذا الاتجاه.
  • قم بإجراء جميع الاختبارات الشاملة على مانع العلاقات العامة على جميع إصدارات SDK.

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

نصائح


إذا أمكنني تقديم نصيحة واحدة فقط ، فستكون هذه هي:

يرجى توخي الحذر مع البرامج النصية قذيفة!

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

بدأ كل شيء بنصوص بسيطة تم تشغيلها على آلات الإنشاء الخاصة بنا:

 #!/usr/bin/env bash ./gradlew assembleDebug 

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



يمكنك أن تتخيل العمل الذي ينطوي عليه تطوير هذه النصوص. أنصحك بعدم الوقوع في هذا الفخ.

ما يمكن استبداله؟

  • أي لغة البرمجة. تعد الكتابة في Python أو Kotlin Script أكثر ملاءمة لأنها برمجة وليست نصوص برمجية.
  • أو صف كل منطق الإنشاء في شكل مهام gradle المخصصة لمشروعك .

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

نصيحة رقم 2: حافظ على البنية الأساسية الخاصة بك في رمز.

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

يمكن تخزين البرامج النصية في المشروع. وماذا تفعل مع البيئة؟

نصيحة رقم 3: عامل الميناء يمكن أن تساعد في البيئة.

بالتأكيد سوف يساعد مطوري Android ، iOS ، لسوء الحظ.

هذا مثال على ملف عامل ميناء بسيط يحتوي على jdk و android-sdk:

 FROM openjdk:8 ENV SDK_URL="https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip" \ ANDROID_HOME="/usr/local/android-sdk" \ ANDROID_VERSION=26 \ ANDROID_BUILD_TOOLS_VERSION=26.0.2 # Download Android SDK RUN mkdir "$ANDROID_HOME" .android \ && cd "$ANDROID_HOME" \ && curl -o sdk.zip $SDK_URL \ && unzip sdk.zip \ && rm sdk.zip \ && yes | $ANDROID_HOME/tools/bin/sdkmanager --licenses # Install Android Build Tool and Libraries RUN $ANDROID_HOME/tools/bin/sdkmanager --update RUN $ANDROID_HOME/tools/bin/sdkmanager "build-tools;${ANDROID_BUILD_TOOLS_VERSION}" \ "platforms;android-${ANDROID_VERSION}" \ "platform-tools" RUN mkdir /application WORKDIR /application 

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

الحجتين الرئيسيتين لماذا هذا منطقي هي التدرجية والتكرار. باستخدام عامل ميناء ، يمكنك بسرعة جمع عشرة عوامل بناء سيكون لها نفس البيئة تمامًا مثل البيئة القديمة. هذا يجعل الحياة أسهل لمهندسي CI. إن عملية دفع android-sdk إلى docker بسيطة للغاية ، حيث تكون المحاكاة أكثر تعقيدًا: يجب عليك التدرب قليلاً (جيدًا ، أو تنزيل المكالمة النهائية مرة أخرى من GitHub).

نصيحة رقم 4: لا تنس أن الشيكات تتم ليس من أجل الشيكات ، ولكن للناس.

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

نصيحة رقم 5: كن براغماتية مع التكامل المستمر.

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

نصيحة رقم 6: استخدام الأدوات الجاهزة.

الآن هناك العديد من الشركات التي توفر سحابة CI.



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

نصيحة رقم 7: في فريق كبير ، تكون الحلول الداخلية أكثر ربحية.

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

يصف الاقتصاد حياتنا كلها ، بما في ذلك التكامل المستمر. لقد قمت ببناء جدول عمل لكل مرحلة من مراحل تطوير التكامل المستمر.



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

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

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

: 20% . , . , , , - , develop, . , , - .

Continuous Integration. .

, , AppsConf . . 22-23 .

Source: https://habr.com/ru/post/ar447608/


All Articles