
سيكون هذا المقال ذا أهمية لكل من المختبرين والمطورين ، ولكنه يستهدف بشكل أكبر شركات التشغيل التي تواجه مشكلة تكوين GitLab CI / CD لاختبار التكامل في ظروف موارد البنية التحتية غير الكافية و / أو عدم وجود نظام أساسي لتنسيق الحاوية. سوف أخبرك بكيفية تكوين نشر بيئات الاختبار باستخدام عامل التشغيل الذي يتم إنشاؤه على عداء GitLab shell واحد وعند نشر بيئات متعددة ، لا تتداخل الخدمات التي يتم إطلاقها مع بعضها البعض.
محتوى
الشروط
في ممارستي ، غالبًا ما حدث "شفاء" اختبار التكامل في المشروعات. وغالبًا ما تكون المشكلة الأولى والأكثر أهمية هي خط أنابيب CI ، حيث يتم إجراء اختبار تكامل للخدمة (الخدمات) المتقدمة في بيئة تطوير / مرحلة. تسبب هذا في عدد غير قليل من المشاكل:
- نظرًا لوجود عيوب في خدمة معينة أثناء اختبار التكامل ، قد تتلف دائرة الاختبار بسبب البيانات المعطلة. كانت هناك حالات عند إرسال طلب بتنسيق JSON مقطوع ، علقت إحدى الخدمات ، الأمر الذي أدى إلى توقف تشغيل الحامل تمامًا.
- تباطؤ حلقة الاختبار مع نمو بيانات الاختبار. أعتقد أنه لا معنى لوصف مثال مع تنظيف / استعادة قاعدة بيانات. في ممارستي ، لم أر مشروعًا تمت فيه هذه العملية بسلاسة.
- خطر تعطيل أداء دائرة الاختبار عند اختبار إعدادات النظام العامة. على سبيل المثال ، سياسة المستخدم / المجموعة / كلمة المرور / التطبيق.
- تمنع بيانات الاختبار من الاختبارات الذاتية من العيش في الاختبار.
سيقول شخص ما إن الاختبارات التلقائية الجيدة يجب أن تنظف البيانات بعدها. لدي حجج ضد:
- المدرجات الديناميكية مريحة للغاية للاستخدام.
- لا يمكن حذف كل كائن من النظام من خلال API. على سبيل المثال ، لم يتم تنفيذ استدعاء لحذف كائن ، لأنه يتعارض مع منطق العمل.
- عند إنشاء كائن من خلال واجهة برمجة التطبيقات ، يمكن إنشاء كمية هائلة من البيانات التعريفية ، مما يصعب حذفه.
- إذا كانت الاختبارات مترابطة ، فإن عملية تنظيف البيانات بعد الانتهاء من الاختبارات تتحول إلى صداع.
- مكالمات إضافية (وفي رأيي غير مبررة) إلى واجهة برمجة التطبيقات.
- والحجة الرئيسية: عندما تبدأ بيانات الاختبار في التنظيف مباشرة من قاعدة البيانات. يتحول إلى سيرك PK / FK حقيقي! من المطورين يكون مسموعًا: "لقد قمت فقط بإضافة / حذف / إعادة تسمية اللوحة ، لماذا فشل اختبار التكامل 100500؟"
في رأيي ، الحل الأمثل هو بيئة ديناميكية.
- يستخدم العديد من الأشخاص عامل إنشاء عامل الإرساء لتشغيل بيئة اختبار ، ولكن عددًا قليلًا من المستخدمين يستخدم تكوين عامل ربط عند إجراء اختبار التكامل في CI / CD. وهنا لا تأخذ في الاعتبار kubernetes والسرب وغيرها من منصات تزامن الحاويات. ليس كل شركة لديها. سيكون من الرائع لو كان عامل الإرساء - compose.yml عالميًا.
- حتى إذا كان لدينا عداء ضمان الجودة الخاص بنا ، كيف يمكننا التأكد من أن الخدمات التي يتم إطلاقها من خلال عامل الإرساء لا تتداخل مع بعضها البعض؟
- كيفية جمع سجلات الخدمات المختبرة؟
- كيفية تنظيف عداء؟
لديّ عداء GitLab الخاص بمشاريعي وقد صادفت هذه المشكلات عند تطوير عميل Java لـ TestRail . أو بالأحرى ، عند إجراء اختبارات التكامل. فيما يلي ، سنحل هذه المشكلات بأمثلة من هذا المشروع.
إلى المحتوى
Gitlab قذيفة عداء
بالنسبة للعداء ، أوصي بجهاز Linux ظاهري يحتوي على 4 وحدات تحكم في وحدة المعالجة المركزية (VCPU) وذاكرة وصول عشوائي (RAM) سعة 4 جيجابايت و 50 جيجابايت محرك أقراص ثابتة.
على الإنترنت ، الكثير من المعلومات حول تكوين gitlab-runner ، وذلك باختصار:
- تثبيت gitlab- عداء ، عامل ميناء ، عامل ميناء الإنشاء ، وجعل.
- أضف
gitlab-runner
user to gitlab-runner
group
sudo groupadd docker sudo usermod -aG docker gitlab-runner
- تسجيل gitlab عداء.
فتح للتحرير / /etc/gitlab-runner/config.toml
/ /etc/gitlab-runner/config.toml
/ /etc/gitlab-runner/config.toml
وإضافة
concurrent=20 [[runners]] request_concurrency = 10
سيتيح لك ذلك تشغيل مهام متوازية على عداء واحد. اقرأ المزيد هنا .
إذا كان جهازك أكثر قوة ، على سبيل المثال ، 8 vCPU ، 16 جيجابايت من ذاكرة الوصول العشوائي ، يمكن جعل هذه الأرقام أكبر مرتين على الأقل. لكن كل هذا يتوقف على ما سيتم إطلاقه بالضبط على هذا العداء وبأي كمية.
هذا يكفي.
إلى المحتوى
إعداد عامل ميناء compose.yml
المهمة الرئيسية هي docker-compose.yml ، والتي سيتم استخدامها محليا وفي خط أنابيب CI.
سيتم استخدام المتغير COMPOSE_PROJECT_NAME لبدء عدة مثيلات للبيئة (راجع ملف التعريف).
مثال لبلدي عامل ميناء compose.yml
version: "3" # web (php) fmt , # . # , /var/www/testrail volumes: static-content: services: db: image: mysql:5.7.22 environment: MYSQL_HOST: db MYSQL_DATABASE: mydb MYSQL_ROOT_PASSWORD: 1234 SKIP_GRANT_TABLES: 1 SKIP_NETWORKING: 1 SERVICE_TAGS: dev SERVICE_NAME: mysql migration: image: registry.gitlab.com/touchbit/image/testrail/migration:latest links: - db depends_on: - db fpm: image: registry.gitlab.com/touchbit/image/testrail/fpm:latest container_name: "testrail-fpm-${CI_JOB_ID:-local}" volumes: - static-content:/var/www/testrail links: - db web: image: registry.gitlab.com/touchbit/image/testrail/web:latest # TR_HTTP_PORT TR_HTTPS_PORTS , # 80 443 . ports: - ${TR_HTTP_PORT:-80}:80 - ${TR_HTTPS_PORT:-443}:443 volumes: - static-content:/var/www/testrail links: - db - fpm
إلى المحتوى
إعداد Makefile
يمكنني استخدام Makefile ، لأنه مناسب جدًا لكل من الإدارة المحلية للبيئة وفي CI.
مزيد من التعليقات مضمنة
# `.indirect`, # `docker-compose.yml` # bash pipefail # pipefail - , SHELL=/bin/bash -o pipefail # CI_JOB_ID ifeq ($(CI_JOB_ID),) # local CI_JOB_ID := local endif # export COMPOSE_PROJECT_NAME = $(CI_JOB_ID)-testrail # , , volumes docker-down: docker-compose -f .indirect/docker-compose.yml down # docker-down () docker-up: docker-down # docker-registry docker-compose -f .indirect/docker-compose.yml pull # # force-recreate - # renew-anon-volumes - volumes docker-compose -f .indirect/docker-compose.yml up --force-recreate --renew-anon-volumes -d # , , docker ps # docker-logs: mkdir -p ./logs docker logs $${COMPOSE_PROJECT_NAME}_web_1 >& logs/testrail-web.log || true docker logs $${COMPOSE_PROJECT_NAME}_fpm_1 >& logs/testrail-fpm.log || true docker logs $${COMPOSE_PROJECT_NAME}_migration_1 >& logs/testrail-migration.log || true docker logs $${COMPOSE_PROJECT_NAME}_db_1 >& logs/testrail-mysql.log || true # docker-clean: @echo testrail- docker kill $$(docker ps --filter=name=testrail -q) || true @echo docker rm -f $$(docker ps -a -f --filter=name=testrail status=exited -q) || true @echo dangling docker rmi -f $$(docker images -f "dangling=true" -q) || true @echo testrail docker rmi -f $$(docker images --filter=reference='registry.gitlab.com/touchbit/image/testrail/*' -q) || true @echo volume docker volume rm -f $$(docker volume ls -q) || true @echo testrail docker network rm $(docker network ls --filter=name=testrail -q) || true docker ps
تحقق الاطلاق المحلي $ make docker-up docker-compose -f .indirect/docker-compose.yml pull Pulling db ... done Pulling migration ... done Pulling fpm ... done Pulling web ... done docker-compose -f .indirect/docker-compose.yml up --force-recreate --renew-anon-volumes -d Creating network "local-testrail_default" with the default driver Recreating local-testrail_db_1 ... done Recreating local-testrail_migration_1 ... done Recreating local-testrail_fpm_1 ... done Recreating local-testrail_web_1 ... done docker ps CONTAINER ID NAMES 3b8f9d4af29c local-testrail_web_1 5622c7d742d5 local-testrail_fpm_1 b580e3392038 local-testrail_migration_1 e467630bd3a5 local-testrail_db_1
التحقق من إطلاق CI $ export CI_JOB_ID=123456789 $ make docker-up docker-compose -f .indirect/docker-compose.yml pull Pulling db ... done Pulling migration ... done Pulling fpm ... done Pulling web ... done docker-compose -f .indirect/docker-compose.yml up --force-recreate --renew-anon-volumes -d Creating network "123456789-testrail_default" with the default driver Creating volume "123456789-testrail_static-content" with default driver Creating 123456789-testrail_db_1 ... done Creating 123456789-testrail_fpm_1 ... done Creating 123456789-testrail_migration_1 ... done Creating 123456789-testrail_web_1 ... done docker ps CONTAINER ID NAMES ccf1ad33d0e8 123456789-testrail_web_1 bc079964f681 123456789-testrail_fpm_1 10dc9d4d8f2a 123456789-testrail_migration_1 fe98d43c380e 123456789-testrail_db_1
تحقق جمع السجل $ make docker-logs mkdir -p ./logs docker logs ${COMPOSE_PROJECT_NAME}_web_1 >& logs/testrail-web.log || true docker logs ${COMPOSE_PROJECT_NAME}_fpm_1 >& logs/testrail-fpm.log || true docker logs ${COMPOSE_PROJECT_NAME}_migration_1 >& logs/testrail-migration.log || true docker logs ${COMPOSE_PROJECT_NAME}_db_1 >& logs/testrail-mysql.log || true

إلى المحتوى
إعداد .gitlab-ci.yml
تشغيل اختبارات التكامل
Integration: stage: test tags: - my-shell-runner before_script: # registry - docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY} # TR_HTTP_PORT TR_HTTPS_PORT - export TR_HTTP_PORT=$(shuf -i10000-60000 -n1) - export TR_HTTPS_PORT=$(shuf -i10000-60000 -n1) script: # - make docker-up # jar ( ) - java -jar itest.jar --http-port ${TR_HTTP_PORT} --https-port ${TR_HTTPS_PORT} # - docker run --network=testrail-network-${CI_JOB_ID:-local} --rm itest after_script: # - make docker-logs # - make docker-down artifacts: # when: always paths: - logs expire_in: 30 days
نتيجة لتشغيل مثل هذه المهمة في القطع الأثرية ، سيحتوي دليل السجلات على سجلات الخدمات والاختبارات. وهو مناسب جدا في حالة وجود أخطاء. بالنسبة لي ، كل اختبار بالتوازي يكتب سجله الخاص ، لكنني سأتحدث عن هذا بشكل منفصل.

إلى المحتوى
عداء التنظيف
سيتم تشغيل المهمة فقط في الموعد المحدد.
stages: - clean - build - test Clean runner: stage: clean only: - schedules tags: - my-shell-runner script: - make docker-clean
بعد ذلك ، انتقل إلى مشروع GitLab الخاص بنا -> CI / CD -> الجداول -> جدول جديد وإضافة جدول جديد

إلى المحتوى
يؤدي
تشغيل 4 مهام في GitLab CI

في سجلات المهمة الأخيرة مع اختبارات التكامل ، نرى حاويات من مهام مختلفة
CONTAINER ID NAMES c6b76f9135ed 204645172-testrail-web_1 01d303262d8e 204645172-testrail-fpm_1 2cdab1edbf6a 204645172-testrail-migration_1 826aaf7c0a29 204645172-testrail-mysql_1 6dbb3fae0322 204645084-testrail-web_1 3540f8d448ce 204645084-testrail-fpm_1 70fea72aa10d 204645084-testrail-mysql_1 d8aa24b2892d 204644881-testrail-web_1 6d4ccd910fad 204644881-testrail-fpm_1 685d8023a3ec 204644881-testrail-mysql_1 1cdfc692003a 204644793-testrail-web_1 6f26dfb2683e 204644793-testrail-fpm_1 029e16b26201 204644793-testrail-mysql_1 c10443222ac6 204567103-testrail-web_1 04339229397e 204567103-testrail-fpm_1 6ae0accab28d 204567103-testrail-mysql_1 b66b60d79e43 204553690-testrail-web_1 033b1f46afa9 204553690-testrail-fpm_1 a8879c5ef941 204553690-testrail-mysql_1 069954ba6010 204553539-testrail-web_1 ed6b17d911a5 204553539-testrail-fpm_1 1a1eed057ea0 204553539-testrail-mysql_1
سجل أكثر تفصيلا $ docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY} WARNING! Using --password via the CLI is insecure. Use --password-stdin. WARNING! Your password will be stored unencrypted in /home/gitlab-runner/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded $ export TR_HTTP_PORT=$(shuf -i10000-60000 -n1) $ export TR_HTTPS_PORT=$(shuf -i10000-60000 -n1) $ mkdir ${CI_JOB_ID} $ cp .indirect/docker-compose.yml ${CI_JOB_ID}/docker-compose.yml $ make docker-up docker-compose -f ${CI_JOB_ID:-.indirect}/docker-compose.yml kill docker network rm testrail-network-${CI_JOB_ID:-local} || true Error: No such network: testrail-network-204645172 docker network create testrail-network-${CI_JOB_ID:-local} 0a59552b4464b8ab484de6ae5054f3d5752902910bacb0a7b5eca698766d0331 docker-compose -f ${CI_JOB_ID:-.indirect}/docker-compose.yml pull Pulling web ... done Pulling fpm ... done Pulling migration ... done Pulling db ... done docker-compose -f ${CI_JOB_ID:-.indirect}/docker-compose.yml up --force-recreate --renew-anon-volumes -d Creating volume "204645172-testrail_static-content" with default driver Creating 204645172-testrail-mysql_1 ... Creating 204645172-testrail-mysql_1 ... done Creating 204645172-testrail-migration_1 ... done Creating 204645172-testrail-fpm_1 ... done Creating 204645172-testrail-web_1 ... done docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c6b76f9135ed registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" 13 seconds ago Up 1 second 0.0.0.0:51148->80/tcp, 0.0.0.0:25426->443/tcp 204645172-testrail-web_1 01d303262d8e registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 16 seconds ago Up 13 seconds 9000/tcp 204645172-testrail-fpm_1 2cdab1edbf6a registry.gitlab.com/touchbit/image/testrail/migration:latest "docker-entrypoint.s…" 16 seconds ago Up 13 seconds 3306/tcp, 33060/tcp 204645172-testrail-migration_1 826aaf7c0a29 mysql:5.7.22 "docker-entrypoint.s…" 18 seconds ago Up 16 seconds 3306/tcp 204645172-testrail-mysql_1 6dbb3fae0322 registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" 36 seconds ago Up 22 seconds 0.0.0.0:44202->80/tcp, 0.0.0.0:20151->443/tcp 204645084-testrail-web_1 3540f8d448ce registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 38 seconds ago Up 35 seconds 9000/tcp 204645084-testrail-fpm_1 70fea72aa10d mysql:5.7.22 "docker-entrypoint.s…" 40 seconds ago Up 37 seconds 3306/tcp 204645084-testrail-mysql_1 d8aa24b2892d registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" About a minute ago Up 53 seconds 0.0.0.0:31103->80/tcp, 0.0.0.0:43872->443/tcp 204644881-testrail-web_1 6d4ccd910fad registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" About a minute ago Up About a minute 9000/tcp 204644881-testrail-fpm_1 685d8023a3ec mysql:5.7.22 "docker-entrypoint.s…" About a minute ago Up About a minute 3306/tcp 204644881-testrail-mysql_1 1cdfc692003a registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" About a minute ago Up About a minute 0.0.0.0:44752->80/tcp, 0.0.0.0:23540->443/tcp 204644793-testrail-web_1 6f26dfb2683e registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" About a minute ago Up About a minute 9000/tcp 204644793-testrail-fpm_1 029e16b26201 mysql:5.7.22 "docker-entrypoint.s…" About a minute ago Up About a minute 3306/tcp 204644793-testrail-mysql_1 c10443222ac6 registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" 5 hours ago Up 5 hours 0.0.0.0:57123->80/tcp, 0.0.0.0:31657->443/tcp 204567103-testrail-web_1 04339229397e registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 5 hours ago Up 5 hours 9000/tcp 204567103-testrail-fpm_1 6ae0accab28d mysql:5.7.22 "docker-entrypoint.s…" 5 hours ago Up 5 hours 3306/tcp 204567103-testrail-mysql_1 b66b60d79e43 registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" 5 hours ago Up 5 hours 0.0.0.0:56321->80/tcp, 0.0.0.0:58749->443/tcp 204553690-testrail-web_1 033b1f46afa9 registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 5 hours ago Up 5 hours 9000/tcp 204553690-testrail-fpm_1 a8879c5ef941 mysql:5.7.22 "docker-entrypoint.s…" 5 hours ago Up 5 hours 3306/tcp 204553690-testrail-mysql_1 069954ba6010 registry.gitlab.com/touchbit/image/testrail/web:latest "nginx -g 'daemon of…" 5 hours ago Up 5 hours 0.0.0.0:32869->80/tcp, 0.0.0.0:16066->443/tcp 204553539-testrail-web_1 ed6b17d911a5 registry.gitlab.com/touchbit/image/testrail/fpm:latest "docker-php-entrypoi…" 5 hours ago Up 5 hours 9000/tcp 204553539-testrail-fpm_1 1a1eed057ea0 mysql:5.7.22 "docker-entrypoint.s…" 5 hours ago Up 5 hours 3306/tcp 204553539-testrail-mysql_1
تم إنجاز جميع المهام بنجاحالتحف المهمة تحتوي على سجلات الخدمة والاختبار


يبدو أن كل شيء جميل ، ولكن هناك فارق بسيط. يمكن إلغاء خط الأنابيب قسراً أثناء تنفيذ اختبارات التكامل ، وفي هذه الحالة لن يتم إيقاف تشغيل الحاويات قيد التشغيل. من وقت لآخر تحتاج إلى تنظيف العداء. لسوء الحظ ، لا تزال مهمة المراجعة في GitLab CE في حالة فتح
لكننا أضفنا إطلاق المهمة المجدولة ، ولا أحد يمنعنا من بدء التشغيل يدويًا.
انتقل إلى مشروعنا -> CI / CD -> جداول وقم بتشغيل المهمة Clean runner

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