نصائح لإنشاء مهام سير عمل مخصصة في GitLab CI

ملاحظة perev. : المقال الأصلي كتبه Miłosz Smółka ، أحد مؤسسي الشركة البولندية الصغيرة Three Dots Labs ، والمتخصصة في "حلول الخلفية المتقدمة". يعتمد المؤلف على تجربته في الاستخدام الفعال لـ GitLab CI ويشارك النصائح المتراكمة للمستخدمين الآخرين لهذا المنتج مفتوح المصدر. بعد قراءتها ، أدركنا مدى قرب المشكلات التي وصفها لنا ، لذا قررنا مشاركة الحلول المقترحة مع جمهور أوسع.



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

تشغيل اختبارات التكامل


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

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

في GitLab ، من السهل تشغيل الموارد القابلة للتوصيل مثل حاويات Docker المرتبطة بالحاوية التي تعمل بها البرامج النصية. يمكن تعريف هذه التبعيات باستخدام services . تكون متوفرة حسب اسم الصورة أو بالاسم الذي تختاره ، إذا قمت بتحديده في حقل alias .

فيما يلي مثال بسيط لاستخدام حاوية قابلة للتوصيل مع MySQL:

 integration_tests: stage: tests services: - name: mysql:8 alias: db script: - ./run_tests.sh db:3306 

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

في انتظار الحاويات


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

باستخدام عامل الميناء يؤلف


بالنسبة لمعظم الحالات ، يجب أن تكون services كافية. ومع ذلك ، قد يتطلب الأمر في بعض الأحيان التفاعل مع الخدمات الخارجية. على سبيل المثال ، في حالة تشغيل Kafka و ZooKeeper في حاويتين منفصلتين (هذه هي الطريقة التي يتم بها جمع الصور الرسمية). مثال آخر هو إجراء اختبارات مع عدد ديناميكي من العقد ، مثل السيلينيوم. أفضل حل لتشغيل هذه الخدمات هو Docker Compose :

 version: '3' services: zookeeper: image: confluentinc/cp-zookeeper environment: ZOOKEEPER_CLIENT_PORT: 2181 kafka: image: confluentinc/cp-kafka environment: KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 ports: - 9092:9092 

إذا كنت تستخدم التثبيت الخاص بك مع المتسابقين GitLab على خوادم جديرة بالثقة ، فيمكنك تشغيل Docker Composer من خلال مسؤولي شل . خيار آخر ممكن هو dind في Docker ( dind ). لكن في هذه الحالة ، اقرأ هذا المقال أولاً.

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

 docker-compose up -d ./run_tests.sh localhost:9092 docker-compose down 

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

 version: '3' services: zookeeper: image: confluentinc/cp-zookeeper environment: ZOOKEEPER_CLIENT_PORT: 2181 kafka: image: confluentinc/cp-kafka environment: KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 tests: image: registry.example.com/some-image command: ./run_tests.sh kafka:9092 

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

ويتم إطلاقها بواسطة أمر واحد:

 docker-compose up --exit-code-from tests 

يتضمن --exit-code-from --abort-on-container-exit ، مما يعني: سيتم إيقاف البيئة بأكملها التي docker-compose up بعد اكتمال إحدى الحاويات. سيكون رمز الإكمال لهذا الأمر مكافئًا لرمز الخروج الخاص بالخدمة المحددة (أي هذه tests في المثال أعلاه). إذا اكتمل الأمر الذي يبدأ الاختبارات برمز غير صفري ، docker-compose up بالكامل.

استخدام التسميات كعلامات CI


تحذير : هذه فكرة غير عادية إلى حد ما ، لكنها بدت لي مفيدة ومرنة للغاية.

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



ستسمح لك بعض التحسينات بالوصول إلى تسميات طلب الدمج في البرامج النصية المهمة. في GitLab 11.6 ، أصبح كل شيء أسهل ، لأنه لقد ظهر متغير البيئة CI_MERGE_REQUEST_IID (نعم ، إنه مع IID وليس ID ) ، إذا كان خط الأنابيب يستخدم only: merge_requests .

إذا كان only: merge_requests مستخدم أو كنت تعمل مع إصدار قديم من GitLab ، فيمكنك الحصول على MR - باستخدام مكالمة API:

 curl "$CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/commits/$CI_COMMIT_SHA/merge_requests?private_token=$GITLAB_TOKEN" 

المجال الذي نحتاجه هو iid . ومع ذلك ، تذكر أن العديد من MRs يمكن أن يعودوا لالتزام معين.

عند استلام MR IID ، يبقى فقط التوجه إلى واجهة برمجة تطبيقات دمج الطلبات واستخدام حقل labels من الإجابة:

 curl "$CI_API_V4_URL/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID?private_token=$GITLAB_TOKEN" 

تسجيل الدخول


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



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

كيف هي آمنة المتغيرات الخاصة بك؟


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

ضع ذلك في الاعتبار عند إضافة أي متغيرات وفكر في حفظ الأسرار في حلول أكثر أمانًا (على سبيل المثال ، Vault من HashiCorp ).

استخدام الحالات


ما عليك القيام به مع قوائم التسميات متروك لك. إليك بعض الأفكار:

  • استخدامها لاختبار القطاع.
  • استخدم دلالات المفتاح ذات القيمة مع النقطتين كفاصل (على سبيل المثال التسميات مثل tests:auth ، tests:user )
  • تضمين ميزات معينة للوظائف.
  • السماح بتصحيح مهام معينة في حالة وجود التسمية.

استدعاء واجهات برمجة التطبيقات الخارجية


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

إذا قمت بإنشاء أدواتك الخاصة ، فيمكنك تعليمهم الاستماع إلى GitLab Webhooks (انظر علامة التبويب " التكامل" في إعدادات المشروع). ومع ذلك ، إذا كنت تنوي استخدامها مع أي أنظمة مهمة ، فتأكد من أنها تفي بمتطلبات التوفر العالية.

مثال: شروح Grafana


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



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



حدد متغيرين في إعدادات المشروع:

  • GRAFANA_URL - عنوان URL لتثبيت Grafana (على سبيل المثال ، https://grafana.example.com ) ؛
  • GRAFANA_APIKEY - مفتاح تم إنشاؤه لواجهة برمجة التطبيقات.

لتتمكن من إعادة استخدامها ، ضع البرنامج النصي في المستودع باستخدام نصوص شائعة :

 #!/bin/bash set -e if [ $# -lt 2 ]; then echo "Usage: $0 <text> <tag>" exit 1 fi readonly text="$1" readonly tag="$2" readonly time="$(date +%s)000" cat >./payload.json <<EOF { "text": "$text", "tags": ["$tag"], "time": $time, "timeEnd": $time } EOF curl -X POST "$GRAFANA_URL/api/annotations" \ -H "Authorization: Bearer $GRAFANA_APIKEY" \ -H "content-type: application/json" \ -d @./payload.json 

يمكنك الآن إضافة مكالمتها إلى تكوين CI باستخدام المعلمات الضرورية:

 deploy: stage: deploy script: - $SCRIPTS_DIR/deploy.sh production - $SCRIPTS_DIR/grafana-annotation.sh "$VERSION deployed to production" deploy-production 

يمكن وضع هذه المكالمات في البرنامج النصي deploy.sh لتبسيط تكوين CI.

المكافأة: نصائح سريعة


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

الاستخدام المتقدم فقط / باستثناء


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

 only: refs: - branches variables: - $CI_COMMIT_REF_NAME =~ /^hotfix/ 

لدى GitLab العديد من المتغيرات المحددة مسبقًا في كل وظيفة من وظائف CI - استخدمها.

المراسي ياميل


استخدامها لتجنب الازدواجية.

من الإصدار 11.3 ، يمكنك أيضًا استخدام الكلمة الأساسية الممتدة :

 .common_before_script: &common_before_script before_script: - ... - ... deploy: <<: *common_before_script 

استبعاد قطعة أثرية


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

 dependencies: - build 

أو - على العكس - تخطي كل شيء تمامًا إذا لم يكن أيًا منهم مطلوبًا:

 dependencies: [] 

استراتيجية بوابة


تخطي استنساخ المخزون إذا لم تستخدم الوظيفة هذه الملفات:

 variables: GIT_STRATEGY: none 

هذا كل شئ!

شكرا للقراءة! للتعليقات والأسئلة ، اتصل بي على Twitter أو Reddit .

يمكن العثور على المزيد من نصائح GitLab في المشاركات السابقة:


PS من المترجم


اقرأ أيضًا في مدونتنا:

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


All Articles