تحليل الإلتزامات وسحب الطلبات في Travis CI و Buddy و AppVeyor باستخدام PVS-Studio

صورة 11

بدءًا من الإصدار 7.04 ، يوفر محلل PVS-Studio للغات C و C ++ على Linux و macOS ميزة اختبار للتحقق من قائمة الملفات المحددة. باستخدام الوضع الجديد ، يمكنك تكوين المحلل للتحقق من الطلبات وسحب الطلبات. تتناول هذه المقالة إعداد فحص بعض الملفات المعدلة من مشروع GitHub في أنظمة CI (التكامل المستمر) الشائعة مثل Travis CI و Buddy و AppVeyor.

طريقة التحقق من قائمة الملفات


PVS-Studio هي أداة مصممة للكشف عن الأخطاء ونقاط الضعف المحتملة في التعليمات البرمجية المصدر للبرامج ، مكتوبة بلغات C و C ++ و C # و Java. يعمل في أنظمة 64 بت على Windows و Linux و macOS.

في إصدار PVS-Studio 7.04 لنظامي التشغيل Linux و macOS ، يوجد الآن وضع التحقق من قائمة الملفات. إنه يعمل للمشاريع التي يسمح نظام الإنشاء الخاصة بها بإنشاء ملف compile_commands.json . هناك حاجة حتى يتمكن المحلل من الحصول على معلومات حول تجميع ملفات معينة. إذا كان نظام الإنشاء الخاص بك لا يدعم إنشاء ملف compile_commands.json ، يمكنك محاولة إنشاء مثل هذا الملف باستخدام الأداة المساعدة Bear .

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

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

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

يتم حفظ قائمة الملفات المصدر للتحليل في الملف النصي وتمريرها إلى المحلل باستخدام المعلمة -S :

pvs-studio-analyzer analyze ... -f build/compile_commands.json -S check-list.txt 

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

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

 plog-converter ... --indicate-warnings ... -o /path/to/report.tasks ... 

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

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

المبادئ العامة لتحليل طلب السحب


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

لنلقِ نظرة على مثال شجرة الالتزام ثنائية الفروع:

الصورة 5


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

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

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

للقيام بذلك ، سوف نتعرف على الفرق بين الفروع ، في رأس الفرع ، الذي نريد دمجه في الرئيسي:

 git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list 

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

لذلك حصلنا على الفرق بين الفروع ، وهي قائمة أسماء الملفات المعدلة. نحن الآن بحاجة إلى تغذية ملف .pvs-pr.list هذا للمحلل. لقد أعدنا توجيه الإخراج إليه سابقًا.

 pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ -S .pvs-pr.list 

بعد التحليل ، نحتاج إلى تحويل ملف السجل (PVS-Studio.log) إلى تنسيق سهل الاستخدام:

 plog-converter -t errorfile PVS-Studio.log --cerr -w 

سيقوم هذا الأمر بإخراج قائمة الأخطاء في stderr (دفق الأخطاء القياسي).

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

ترافيس سي


يتم التكوين في شكل ملف .travis.yml . للراحة ، أنصحك بعزل جميع الأوامر المتعلقة بـ PVS-Studio في برنامج نصي bash منفصل مع الوظائف التي سيتم استدعاؤها من الملف .travis.yml ( bash script_name.sh function_name ).

من خلال توسيع البرنامج النصي ، ستحصل على المزيد من الوظائف. في قسم التثبيت ، اكتب ما يلي:

 install: - bash .travis.sh travis_install 

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

افتح الملف .travis.sh وأضف تثبيت المحلل في وظيفة travis_install () :

 travis_install() { wget -q -O - https://files.viva64.com/etc/pubkey.txt \ | sudo apt-key add - sudo wget -O /etc/apt/sources.list.d/viva64.list \ https://files.viva64.com/etc/viva64.list sudo apt-get update -qq sudo apt-get install -qq pvs-studio } 

الآن لنقم بإضافة محلل التشغيل في قسم البرنامج النصي :

 script: - bash .travis.sh travis_script 

وفي البرنامج النصي bash:

 travis_script() { pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then git diff --name-only origin/HEAD > .pvs-pr.list pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ -S .pvs-pr.list \ --disableLicenseExpirationCheck else pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ --disableLicenseExpirationCheck fi plog-converter -t errorfile PVS-Studio.log --cerr -w } 

يجب تشغيل هذا الرمز بعد بناء المشروع ، على سبيل المثال ، إذا كان لديك بناء على CMake:

 travis_script() { CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}" cmake $CMAKE_ARGS CMakeLists.txt make -j8 } 

ستحصل على ما يلي:

 travis_script() { CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}" cmake $CMAKE_ARGS CMakeLists.txt make -j8 pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then git diff --name-only origin/HEAD > .pvs-pr.list pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ -S .pvs-pr.list \ --disableLicenseExpirationCheck else pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ --disableLicenseExpirationCheck fi plog-converter -t errorfile PVS-Studio.log --cerr -w } 

على الأرجح ، لقد لاحظت بالفعل متغيرات البيئة $ TRAVIS_PULL_REQUEST و $ TRAVIS_BRANCH . يعلن Travis CI عن نفسه:

  • $ TRAVIS_PULL_REQUEST يخزن رقم طلب السحب أو خطأ إذا كان فرعًا عاديًا ؛
  • يخزن TRAVIS_REPO_SLUG $ اسم مستودع المشروع.

إليك الخوارزمية التشغيلية لهذه الوظيفة:

صورة 13

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

الآن دعونا نلقي نظرة فاحصة على هذا الكود من التعليمات البرمجية:
 git diff --name-only origin/HEAD > .pvs-pr.list 

الحقيقة هي أن Travis CI يدمج الفروع تلقائيًا عند تحليل طلب السحب:

الصورة 8

لهذا السبب نقوم بتحليل A4 ، وليس B3-> A3 . نظرًا لهذه الخصوصية ، نحتاج إلى تقييم الفرق مع A3 ، وهو رأس الفرع من الأصل .

يبقى أحد التفاصيل المهمة - التخزين المؤقت تبعيات ملفات الرأس من وحدات الترجمة المترجمة (* .c ، * .cc ، * .cpp وغيرها). يقوم المحلل بتقييم هذه التبعيات أثناء التشغيل الأول في وضع التحقق من قائمة الملفات ثم يخزنها في دليل .PVS-Studio. يسمح Travis CI بمستودعات التخزين المؤقت ، لذلك سنقوم بحفظ البيانات في .PVS-Studio / directory:

 cache: directories: - .PVS-Studio/ 

يجب إضافة هذا الرمز في ملف .travis.yml : يخزن هذا الدليل بيانات متنوعة ، يتم جمعها بعد التحليل. تسرع هذه البيانات بشكل ملحوظ عمليات اللاحقة لتحليل قائمة الملفات أو التحليل التزايدي. إذا لم تقم بذلك ، فسيقوم المحلل بتحليل جميع الملفات في كل مرة.

رفيق


تمامًا مثل Travis CI ، يمكّنك Buddy من إنشاء واختبار المشروعات تلقائيًا من GitHub. على عكس Travis CI ، يتم تكوينه في واجهة الويب (يتوفر دعم bash) ، لذلك ليست هناك حاجة لتخزين ملفات التكوين في المشروع.

أولاً ، نحتاج إلى إضافة خطوة جديدة إلى خط الأنابيب:

الصورة 1

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

صورة 6

الآن لنقم بتثبيت PVS-Studio والأدوات المساعدة الضرورية:

الصورة 2

أضف الأسطر التالية إلى المحرر:

 apt-get update && apt-get -y install wget gnupg jq wget -q -O - https://files.viva64.com/etc/pubkey.txt | apt-key add - wget -O /etc/apt/sources.list.d/viva64.list \ https://files.viva64.com/etc/viva64.list apt-get update && apt-get -y install pvs-studio 

دعنا ننتقل إلى علامة التبويب "تشغيل" (الرمز الأول) وإضافة الكود التالي إلى حقل المحرر المناسب:
 pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY if [ "$BUDDY_EXECUTION_PULL_REQUEST_NO" != '' ]; then PULL_REQUEST_ID="pulls/$BUDDY_EXECUTION_PULL_REQUEST_NO" MERGE_BASE=`wget -qO - \ https://api.github.com/repos/${BUDDY_REPO_SLUG}/${PULL_REQUEST_ID} \ | jq -r ".base.ref"` git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ --disableLicenseExpirationCheck \ -S .pvs-pr.list else pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ --disableLicenseExpirationCheck fi plog-converter -t errorfile PVS-Studio.log --cerr -w 

إذا قرأت القسم الخاص بـ Travs-CI ، فهذا الرمز مألوف بالنسبة لك. ولكن هنا هناك خطوة جديدة:

صورة 14

الحقيقة هي أننا نحلل الآن ليس نتيجة الدمج ، ولكن رأس الفرع مع طلب السحب المحدد:

الصورة 10

لذلك نحن في التزام B3 ونحتاج إلى الحصول على الفرق مع A3 :

 PULL_REQUEST_ID="pulls/$BUDDY_EXECUTION_PULL_REQUEST_NO" MERGE_BASE=`wget -qO - \ https://api.github.com/repos/${BUDDY_REPO_SLUG}/${PULL_REQUEST_ID} \ | jq -r ".base.ref"` git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list 

لتعريف A3 ، دعونا نستخدم واجهة برمجة تطبيقات GitHub:

 https://api.github.com/repos/${USERNAME}/${REPO}/pulls/${PULL_REQUEST_ID} 

استخدمنا المتغيرات التالية التي يوفرها لنا Buddy:

  • BUDDY_EXECUTION_PULL_REQEUST_NO $ - رقم طلب السحب ؛
  • BUDDY_REPO_SLUG $ - مجموعة من اسم المستخدم ومستودع (على سبيل المثال ، max / test).

الآن دعونا نحفظ التغييرات ، باستخدام الزر أدناه وتمكين تحليل طلب السحب:

الصورة 3

على عكس Travis CI ، لا يتعين علينا تحديد .pvs-studio للتخزين المؤقت ، حيث يقوم Buddy تلقائيًا بتخزين جميع الملفات للتشغيلات اللاحقة. لذا فإن آخر ما تبقى هو حفظ تسجيل الدخول وكلمة المرور لـ PVS-Studio في Buddy. بعد حفظ التغييرات ، سنعود إلى خط الأنابيب. نحتاج إلى الانتقال لإعداد المتغيرات وإدخال تسجيل الدخول والمفتاح لـ PVS-Studio:

صورة 4

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

AppVeyor


يشبه إعداد AppVeyor Buddy ، حيث يحدث كل ذلك في واجهة الويب ولا توجد حاجة لإضافة ملف * .yml في مستودع المشروع.

دعنا نذهب إلى علامة التبويب "الإعدادات" في مراجعة المشروع:

صورة 12

قم بالتمرير في هذه الصفحة لأسفل وتمكين حفظ ذاكرة التخزين المؤقت لإنشاء طلب السحب:

صورة 18


الآن ، دعنا ننتقل إلى علامة التبويب "البيئة" ، حيث سنقوم بتحديد الصورة لمتغيرات البيئة والبناء اللازمة:

صورة 19

إذا كنت قد قرأت الأقسام السابقة ، فأنت على دراية بهذين المتغيرين - PVS_KEY و PVS_USERNAME . إذا لم يكن الأمر كذلك ، اسمح لي بتذكيرك بأنها ضرورية للتحقق من ترخيص محلل PVS-Studio. في المستقبل ، سنلتقي بهم مرة أخرى في البرامج النصية Bash.

في نفس الصفحة في الأسفل ، دعونا نحدد مجلد ذاكرة التخزين المؤقت:

صورة 15

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

الآن حان الوقت لفحص البرنامج النصي. افتح علامة التبويب الاختبارات واختر Script:

صورة 20

يجب إدخال الكود التالي في هذا النموذج:

 sudo apt-get update && sudo apt-get -y install jq wget -q -O - https://files.viva64.com/etc/pubkey.txt \ | sudo apt-key add - sudo wget -O /etc/apt/sources.list.d/viva64.list \ https://files.viva64.com/etc/viva64.list sudo apt-get update && sudo apt-get -y install pvs-studio pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY PWD=$(pwd -L) if [ "$APPVEYOR_PULL_REQUEST_NUMBER" != '' ]; then PULL_REQUEST_ID="pulls/$APPVEYOR_PULL_REQUEST_NUMBER" MERGE_BASE=`wget -qO - \ https://api.github.com/repos/${APPVEYOR_REPO_NAME}/${PULL_REQUEST_ID} \ | jq -r ".base.ref"` git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ --disableLicenseExpirationCheck \ --dump-files --dump-log pvs-dump.log \ -S .pvs-pr.list else pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ --disableLicenseExpirationCheck fi plog-converter -t errorfile PVS-Studio.log --cerr -w 

لنلاحظ الجزء التالي من الكود:

 PWD=$(pwd -L) if [ "$APPVEYOR_PULL_REQUEST_NUMBER" != '' ]; then PULL_REQUEST_ID="pulls/$APPVEYOR_PULL_REQUEST_NUMBER" MERGE_BASE=`wget -qO - \ https://api.github.com/repos/${APPVEYOR_REPO_NAME}/${PULL_REQUEST_ID} \ | jq -r ".base.ref"` git diff --name-only HEAD origin/$MERGE_BASE > .pvs-pr.list pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ --disableLicenseExpirationCheck \ --dump-files --dump-log pvs-dump.log \ -S .pvs-pr.list else pvs-studio-analyzer analyze -j8 \ -o PVS-Studio.log \ --disableLicenseExpirationCheck fi 

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

أثناء إعداد المحلل في AppVeyor ، تعثرت في سلوك محلل غريب للغاية. من ناحية ، كان كل شيء يعمل بشكل صحيح ، لكن التحليل لم يبدأ. استغرق الأمر الكثير من الوقت لإشعار أننا كنا في / home / appveyor / projects / testcalc / directory ، بينما كان المحلل متأكدًا من أننا كنا في / opt / appveyor / build-agent /. في تلك اللحظة أدركت أن المتغير PWD $ مخادع. لهذا السبب ، قمت بتجديد قيمتها يدويًا قبل تشغيل التحليل.

الترتيب الإضافي للإجراءات كان كما كان في السابق:

الصورة 16

الآن نلقي نظرة على هذه الشظية:

 PULL_REQUEST_ID="pulls/$APPVEYOR_PULL_REQUEST_NUMBER" MERGE_BASE=`wget -qO - \ https://api.github.com/repos/${APPVEYOR_REPO_NAME}/${PULL_REQUEST_ID} \ | jq -r ".base.ref"` 

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

  • APPVEYOR_PULL_REQUEST_NUMBER $ - رقم طلب السحب ؛
  • APPVEYOR_REPO_NAME $ - اسم المستخدم ومستودع المشروع.

استنتاج


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

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

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

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


All Articles