ProHoster > بلوق > إدارة > دوائر الجحيم مع إجراءات GitHub (بناء خط أنابيب CI / CD لمشروع Java)
دوائر الجحيم مع إجراءات GitHub (بناء خط أنابيب CI / CD لمشروع Java)
غالبًا ما أضطر إلى بناء خط أنابيب لبناء المشاريع في Java. في بعض الأحيان يكون مفتوح المصدر، وفي بعض الأحيان لا يكون كذلك. قررت مؤخرًا أن أحاول نقل بعض من اتفاقيات إعادة الشراء الخاصة بي من Travis-CI وTeamCity إلى GitHub Actions، وهذا ما نتج عن ذلك.
ماذا سنقوم بأتمتة؟
أولاً، نحتاج إلى مشروع سنقوم بأتمتته، فلنقم بإنشاء تطبيق صغير في Springboot / Java 11 / Maven. لأغراض هذه المقالة، لن نهتم بمنطق التطبيق على الإطلاق؛ فالبنية التحتية المحيطة بالتطبيق مهمة بالنسبة لنا، لذا فإن وحدة تحكم REST API البسيطة ستكون كافية بالنسبة لنا.
تجدر الإشارة إلى أننا عادةً ما نستخدم JIRA كأداة لتتبع المشكلات، لذلك دعونا ننشئ لوحة منفصلة لهذا المشروع ونضيف الإصدارات الأولى هناك:
سنعود بعد ذلك بقليل إلى الأشياء المثيرة للاهتمام التي يمكن أن تقدمها JIRA وGitHub معًا.
نقوم بأتمتة تجميع المشروع
تم إنشاء مشروعنا الاختباري عبر maven، لذا فإن بنائه بسيط للغاية، وكل ما نحتاج إليه هو حزمة mvn النظيفة.
للقيام بذلك باستخدام Github Actions، سنحتاج إلى إنشاء ملف في المستودع يصف سير العمل لدينا، ويمكن القيام بذلك باستخدام ملف yml عادي، لا أستطيع أن أقول إنني أحب "برمجة yml"، ولكن ماذا يمكننا أن نفعل - نقوم بذلك في ملف .github/ Directory Workflow/ Build.yml الذي سنصف فيه الإجراءات عند إنشاء الفرع الرئيسي:
on — هذا وصف للحدث الذي سيتم فيه إطلاق البرنامج النصي الخاص بنا.
على: pull_request/push - يشير إلى أنه يجب تشغيل سير العمل هذا في كل مرة يتم فيها إجراء دفعة إلى الملف الرئيسي ويتم إنشاء طلبات السحب.
وفيما يلي وصف للمهام (وظائف) وخطوات التنفيذ (سلم) لكل مهمة.
يعمل على - هنا يمكننا تحديد نظام التشغيل المستهدف، ومن المثير للدهشة أنه يمكنك حتى اختيار نظام التشغيل Mac OS، ولكن في المستودعات الخاصة يكون هذا مكلفًا للغاية (مقارنة بنظام التشغيل Linux).
يستخدم يسمح لك بإعادة استخدام إجراءات أخرى، على سبيل المثال، باستخدام الإجراء/setup-java نقوم بتثبيت البيئة لـ Java 11.
بواسطة مع يمكننا تحديد المعلمات التي نطلق بها الإجراء، وهذه هي في الأساس الوسائط التي سيتم تمريرها إلى الإجراء.
كل ما تبقى هو تشغيل بناء المشروع باستخدام Maven: run: mvn -B clean package علم -B يقول أننا بحاجة إلى وضع غير تفاعلي حتى لا يرغب الخبير فجأة في أن يطلب منا شيئًا ما
عظيم! الآن، في كل مرة تلتزم فيها بالسيد، يبدأ بناء المشروع.
أتمتة عمليات إطلاق الاختبار
التجميع جيد، ولكن في الواقع، يمكن تجميع المشروع بأمان، ولكن لا يعمل. ولذلك، فإن الخطوة التالية هي أتمتة عمليات الاختبار. بالإضافة إلى ذلك، من المريح جدًا إلقاء نظرة على نتائج اجتياز الاختبارات عند إجراء مراجعة للعلاقات العامة - فأنت تعلم على وجه اليقين أن الاختبارات قد نجحت ولم ينس أحد تشغيل فرعه قبل إجراء الدمج.
سنقوم بإجراء اختبارات عند إنشاء طلب سحب ودمجه في الطلب الرئيسي، وفي الوقت نفسه سنضيف إنشاء تقرير عن تغطية التعليمات البرمجية.
لتغطية الاختبارات، أستخدم برنامج codecov مع البرنامج المساعد jacoco. لدى codecov إجراء خاص به، ولكنه يحتاج إلى رمز مميز للعمل مع طلب السحب الخاص بنا:
${{ secrets.CODECOV_TOKEN }} - سنرى هذا البناء أكثر من مرة، الأسرار هي آلية لتخزين الأسرار في GitHub، يمكننا أن نكتب هناك كلمات المرور/الرموز المميزة/المضيفين/عناوين URL وغيرها من البيانات التي لا ينبغي تضمينها في قاعدة كود المستودع.
يمكنك إضافة متغير إلى الأسرار في إعدادات المستودع على GitHub:
يمكنك الحصول على رمز مميز في codecov.io بعد الحصول على الترخيص عبر GitHub، لإضافة مشروع عام، ما عليك سوى اتباع رابط مثل هذا: اسم مستخدم جيثب/[اسم الريبو]. يمكن أيضًا إضافة مستودع خاص؛ للقيام بذلك، تحتاج إلى منح حقوق codecov للتطبيق في Github.
الآن سيقوم روبوت codecov بإدخال كل طلبات السحب الخاصة بنا وإضافة رسم بياني لتغيير التغطية:
دعونا نضيف محلل ثابت
في معظم مشاريعي مفتوحة المصدر، أستخدم سحابة السونار لتحليل التعليمات البرمجية الثابتة، ومن السهل جدًا الاتصال بـ travis-ci. لذا، فهي خطوة منطقية عند الانتقال إلى GitHub Actions للقيام بنفس الشيء. يعد سوق العمل أمرًا رائعًا، لكنه خذلني هذه المرة قليلاً، لأنني وجدت الإجراء الذي أحتاجه بحكم العادة وأضفته إلى سير العمل. ولكن اتضح أن السونار لا يدعم العمل من خلال إجراء تحليل المشاريع على المخضرم أو المدرج. طبعاً هذا مكتوب في التوثيق، لكن من يقرأه؟!
هذا غير ممكن من خلال إجراء، لذلك سنفعل ذلك من خلال البرنامج الإضافي mvn:
SONAR_TOKEN - يمكن الحصول عليه في sonarcloud.io وتحتاج إلى تسجيله في الأسرار. GITHUB_TOKEN - هذا رمز مميز ينشئه GitHub، وبمساعدته سيتمكن sonarcloud[bot] من تسجيل الدخول إلى Git لترك رسائل لنا في طلبات السحب.
Dsonar.projectKey — اسم المشروع في السونار يمكنك رؤيته في إعدادات المشروع.
Dsonar.organization - اسم المنظمة من جيثب.
نقوم بتقديم طلب سحب وننتظر ظهور sonarcloud[bot] في التعليقات:
إدارة الإفراج
تمت تهيئة البنية، وإجراء الاختبارات، ويمكننا إصدارها. دعونا نلقي نظرة على كيف يمكن لإجراءات GitHub أن تجعل إدارة الإصدار أسهل بكثير.
في العمل، لدي مشاريع قاعدة شفرتها موجودة في bitbucket (كل شيء يشبه تلك القصة "أكتب إلى bitbucket أثناء النهار، وألتزم بـ GitHub في الليل"). لسوء الحظ، لا يحتوي bitbucket على أدوات مدمجة لإدارة الإصدار. هذه مشكلة، لأنه لكل إصدار، يتعين عليك إنشاء صفحة ملتقى يدويًا وإلقاء جميع الميزات المضمنة في الإصدار هناك، والبحث في قصور العقل، والمهام في جيرا، والالتزامات في المستودع. هناك العديد من الفرص لارتكاب خطأ، يمكنك نسيان شيء ما أو إدخال شيء تم إصداره بالفعل في المرة الأخيرة، وفي بعض الأحيان يكون من غير الواضح ببساطة ما يجب تصنيف طلب السحب عليه - هل هو ميزة أم إصلاح خطأ، أو تحرير الاختبارات، أو شيء من البنية التحتية.
كيف يمكن أن تساعدنا إجراءات GitHub؟ هناك إجراء رائع - محرر الإصدار، فهو يسمح لك بتعيين قالب ملف ملاحظات الإصدار لإعداد فئات طلبات السحب وتجميعها تلقائيًا في ملف ملاحظات الإصدار:
مثال لقالب لإعداد تقرير (.github/release-draft.yml):
name-template: 'v$NEXT_PATCH_VERSION'
tag-template: 'v$NEXT_PATCH_VERSION'
categories:
- title: ' New Features'
labels:
- 'type:features'
# в эту категорию собираем все PR с меткой type:features
- title: ' Bugs Fixes'
labels:
- 'type:fix'
# аналогично для метки type:fix и т.д.
- title: ' Documentation'
labels:
- 'type:documentation'
- title: ' Configuration'
labels:
- 'type:config'
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
template: |
## Changes
$CHANGES
أضف برنامجًا نصيًا لإنشاء مسودة إصدار (.github/workflows/release-draft.yml):
سيتم جمع جميع طلبات السحب من الآن فصاعدًا في ملاحظات الإصدار تلقائيًا - سحر!
وهنا قد يطرح السؤال: ماذا لو نسي المطورون وضع العلامات في العلاقات العامة؟ بعد ذلك، ليس من الواضح ما هي الفئة التي سيتم وضعها فيها، ومرة أخرى سيتعين عليك التعامل معها يدويًا، مع كل علاقات عامة على حدة. لإصلاح هذه المشكلة، يمكننا استخدام إجراء آخر - التحقق من التسمية - فهو يتحقق من وجود العلامات في طلب السحب. إذا لم تكن هناك علامات مطلوبة، فسيتم فشل عملية التحقق وسنرى رسالة حول هذا الأمر في طلب السحب الخاص بنا.
الآن يجب وضع علامة على أي طلب سحب بإحدى العلامات: type:fix، type:features، type:documentation، type:tests، type:config.
الشرح التلقائي لطلبات السحب
نظرًا لأننا تطرقنا إلى موضوع مثل العمل الفعال مع طلبات السحب، فإن الأمر يستحق الحديث عن إجراء مثل الملصق، فهو يضع علامات في العلاقات العامة بناءً على الملفات التي تم تغييرها. على سبيل المثال، يمكننا وضع علامة [إنشاء] على أي طلب سحب يحتوي على تغييرات في الدليل .github/workflow.
لم أنجح في إقران الإجراء الذي يضع التصنيفات تلقائيًا في طلبات السحب مع الإجراء الذي يتحقق من وجود التصنيفات المطلوبة؛ لا يريد Match-label رؤية التصنيفات التي أضافها الروبوت. يبدو من الأسهل أن تكتب الإجراء الخاص بك الذي يجمع بين المرحلتين. ولكن حتى في هذا النموذج، فهو مناسب تماما للاستخدام، تحتاج إلى تحديد تسمية من القائمة عند إنشاء طلب سحب.
حان الوقت للنشر
لقد جربت العديد من خيارات النشر عبر GitHub Actions (عبر ssh، وعبر scp، واستخدام docker-hub)، ويمكنني أن أقول إنه على الأرجح، ستجد طريقة لتحميل الملف الثنائي إلى الخادم، بغض النظر عن مدى اعوجاج خط أنابيبك يكون.
أعجبني خيار الاحتفاظ بالبنية التحتية بأكملها في مكان واحد، لذلك دعونا نلقي نظرة على كيفية النشر في حزم GitHub (هذا مستودع للمحتوى الثنائي، npm، jar، docker).
البرنامج النصي لإنشاء صورة عامل الإرساء ونشرها في حزم GitHub:
أولاً، نحتاج إلى إنشاء ملف JAR لتطبيقنا، وبعد ذلك نحسب المسار إلى سجل GitHub docker واسم صورتنا. هناك بعض الحيل التي لم نتعرف عليها بعد:
تسمح لك بنية مثل: echo “::set-output name=NAME::VALUE” بتعيين قيمة متغير في الخطوة الحالية، بحيث يمكن قراءتها بعد ذلك في جميع الخطوات الأخرى.
يمكنك الحصول على قيمة المتغير المحدد في الخطوة السابقة من خلال معرف هذه الخطوة: ${{ Steps.global_env.outputs.DOCKERHUB_IMAGE_NAME }}
يقوم المتغير GITHUB_REPOSITORY القياسي بتخزين اسم المستودع ومالكه ("اسم المالك/المستودع"). من أجل قطع كل شيء من هذا السطر باستثناء اسم المستودع، سنستخدم صيغة bash: ${GITHUB_REPOSITORY#*/}
للإشارة إلى إصدار الصورة، نستخدم الأرقام الأولى من تجزئة SHA للالتزام - GITHUB_SHA هناك أيضًا فروق دقيقة هنا، إذا قمت بإجراء مثل هذه البنيات ليس فقط عند الدمج في الملف الرئيسي، ولكن أيضًا وفقًا لإنشاء طلب السحب قد لا يتطابق SHA مع التجزئة التي نراها في سجل git، لأن إجراء الإجراءات/الخروج يقوم بإنشاء تجزئة فريدة خاصة به لتجنب إجراءات الجمود في العلاقات العامة.
إذا سار كل شيء على ما يرام، فافتح قسم الحزم (https://github.com/antkorwin/github-actions/packages) في المستودع، وسترى صورة عامل إرساء جديدة:
هناك يمكنك أيضًا رؤية قائمة بإصدارات صورة عامل الإرساء.
كل ما تبقى هو تكوين خادمنا للعمل مع هذا السجل وإعادة تشغيل الخدمة. ربما سأتحدث عن كيفية القيام بذلك من خلال systemd مرة أخرى.
رصد
دعونا نلقي نظرة على خيار بسيط حول كيفية إجراء فحص صحي لتطبيقنا باستخدام GitHub Actions. يحتوي تطبيق التمهيد الخاص بنا على مشغل، لذلك لا نحتاج حتى إلى كتابة واجهة برمجة التطبيقات (API) للتحقق من حالته، فقد قمنا بالفعل بكل شيء من أجل الكسالى. تحتاج فقط إلى سحب المضيف: SERVER-URL:PORT/actuator/health
jobs:
ping:
runs-on: ubuntu-18.04
steps:
- name: curl actuator
id: ping
run: |
echo "::set-output name=status::$(curl ${{secrets.SERVER_HOST}}/api/actuator/health)"
- name: health check
run: |
if [[ ${{ steps.ping.outputs.status }} != *"UP"* ]]; then
echo "health check is failed"
exit 1
fi
echo "It's OK"
أولاً، نحفظ في متغير ما استجاب الخادم للطلب، وفي الخطوة التالية نتحقق من أن الحالة UP، وإذا لم يكن الأمر كذلك، فسنخرج مع وجود خطأ. إذا كنت بحاجة إلى "إطاحة" إجراء ما بيديك، إذن خروج 1 - سلاح مناسب .
- name: send alert in telegram
if: ${{ failure() }}
uses: appleboy/telegram-action@master
with:
to: ${{ secrets.TELEGRAM_TO }}
token: ${{ secrets.TELEGRAM_TOKEN }}
message: |
Health check of the:
${{secrets.SERVER_HOST}}/api/actuator/health
failed with the result:
${{ steps.ping.outputs.status }}
نرسل إلى برقية فقط إذا فشل الإجراء في الخطوة السابقة. لإرسال رسالة نستخدم appleboy/telegram-action؛ يمكنك أن تقرأ عن كيفية الحصول على رمز الروبوت ومعرف الدردشة في الوثائق: github.com/appleboy/telegram-action
لا تنس أن تكتب الأسرار على Github: عنوان URL للخادم والرموز المميزة لروبوت telegram.
مسار إضافي - جيرا للكسالى
لقد وعدت بأننا سنعود إلى جيرا، وقد عدنا. لقد لاحظت مئات المرات موقفًا في المواقف عندما قام المطورون بإنشاء ميزة، ودمجوا فرعًا، لكنهم نسوا سحب المشكلة إلى JIRA. بالطبع، لو تم كل هذا في مكان واحد، لكان الأمر أسهل، لكن في الحقيقة نحن نكتب التعليمات البرمجية في IDE، وندمج الفروع في bitbucket أو GitHub، ثم نسحب المهام إلى Jira، ولهذا نحتاج إلى فتح نوافذ جديدة وأحيانًا قم بتسجيل الدخول مرة أخرى وما إلى ذلك. عندما تتذكر تمامًا ما يجب عليك فعله بعد ذلك، فلا فائدة من فتح اللوحة مرة أخرى. ونتيجة لذلك، في الصباح، تحتاج إلى قضاء بعض الوقت في تحديث لوحة المهام.
سيساعدنا GitHub أيضًا في هذه المهمة الروتينية؛ بالنسبة للمبتدئين، يمكننا سحب المشكلات تلقائيًا إلى عمود code_review عندما نرسل طلب سحب. كل ما عليك فعله هو اتباع اصطلاح تسمية الفرع:
[имя проекта]-[номер таска]-название
على سبيل المثال، إذا كان مفتاح المشروع "GitHub Actions" هو GA، إذن GA-8-jira-bot يمكن أن يكون فرعًا لتنفيذ مهمة GA-8.
التكامل مع JIRA يعمل من خلال إجراءات من Atlassian، فهي ليست مثالية، ويجب أن أقول إن بعضها لم يعمل معي على الإطلاق. لكننا سنناقش فقط تلك التي تعمل بالتأكيد وتستخدم بنشاط.
تحتاج أولاً إلى تسجيل الدخول إلى JIRA باستخدام الإجراء: atlassian/gajira-login
- name: Find Issue
id: find_issue
shell: bash
run: |
echo "::set-output name=ISSUE_ID::$(echo ${GITHUB_HEAD_REF} | egrep -o 'GA-[0-9]{1,4}')"
echo brach name: $GITHUB_HEAD_REF
echo extracted issue: ${GITHUB_HEAD_REF} | egrep -o 'GA-[0-9]{1,4}'
- name: Check Issue
shell: bash
run: |
if [[ "${{steps.find_issue.outputs.ISSUE_ID}}" == "" ]]; then
echo "Please name your branch according to the JIRA issue: [project_key]-[task_number]-branch_name"
exit 1
fi
echo succcessfully found JIRA issue: ${{steps.find_issue.outputs.ISSUE_ID}}
إذا بحثت في سوق GitHub، يمكنك العثور على إجراء لهذه المهمة، ولكن كان علي أن أكتب نفس الشيء باستخدام grep باستخدام اسم الفرع، لأن هذا الإجراء من Atlassian لم يرغب في العمل على مشروعي بأي شكل من الأشكال ، لمعرفة الخطأ هناك، يعد وقتًا أطول من فعل نفس الشيء بيديك.
كل ما تبقى هو نقل المهمة إلى عمود "مراجعة الكود" عند إنشاء طلب سحب:
هناك إجراء خاص لهذا على GitHub، كل ما يحتاجه هو معرف المشكلة الذي تم الحصول عليه في الخطوة السابقة والترخيص في JIRA الذي قمنا به أعلاه.
بنفس الطريقة، يمكنك سحب المهام عند الدمج في الحدث الرئيسي والأحداث الأخرى من سير عمل GitHub. بشكل عام، كل هذا يتوقف على خيالك ورغبتك في أتمتة العمليات الروتينية.
النتائج
إذا نظرت إلى مخطط DEVOPS الكلاسيكي، فقد قمنا بتغطية جميع المراحل، ربما باستثناء التشغيل، وأعتقد أنه إذا حاولت، فيمكنك العثور على بعض الإجراءات في السوق للتكامل مع نظام مكتب المساعدة، لذلك سنفترض أن خط الأنابيب قد تحول لتكون شاملة ويمكن استخلاص الاستنتاجات على أساس استخدامه.
الايجابيات:
سوق يحتوي على إجراءات جاهزة لجميع المناسبات، إنه رائع جدًا. في معظمها، يمكنك أيضًا إلقاء نظرة على الكود المصدري لفهم كيفية حل مشكلة مماثلة أو نشر طلب ميزة إلى المؤلف مباشرةً في مستودع GitHub.
يعد اختيار النظام الأساسي المستهدف للتجميع: Linux وmac os وwindows ميزة مثيرة للاهتمام.
تعد حزم Github شيئًا رائعًا، فهي ملائمة للاحتفاظ بالبنية التحتية بأكملها في مكان واحد، ولا يتعين عليك تصفح نوافذ مختلفة، فكل شيء يقع ضمن دائرة نصف قطرها نقرة واحدة أو نقرتين بالماوس ومتكامل تمامًا مع GitHub Actions. يعد دعم تسجيل Docker في الإصدار المجاني ميزة جيدة أيضًا.
يخفي GitHub الأسرار في سجلات البناء، لذا فإن استخدامه لتخزين كلمات المرور والرموز المميزة ليس أمرًا مخيفًا. خلال كل تجاربي، لم أتمكن أبدًا من رؤية السر بشكله النقي في وحدة التحكم.
مجاني للمشاريع مفتوحة المصدر
سلبيات:
YML، حسنًا، أنا لا أحبه. عند العمل مع مثل هذا التدفق، فإن رسالة الالتزام الأكثر شيوعًا التي لدي هي "إصلاح تنسيق yml"، ثم تنسى وضع علامة تبويب في مكان ما، أو تكتبها في السطر الخطأ. بشكل عام، الجلوس أمام الشاشة مع المنقلة والمسطرة ليس تجربة ممتعة للغاية.
تصحيح الأخطاء، وتصحيح التدفق من خلال الالتزامات، وتشغيل إعادة البناء، والإخراج إلى وحدة التحكم ليس أمرًا مناسبًا دائمًا، ولكنه أقرب إلى فئة "لقد تجاوزت الحد"؛ لقد اعتدت على العمل باستخدام IDEA المريح، عندما يمكنك تصحيح أي شيء .
يمكنك كتابة الإجراء الخاص بك على أي شيء إذا قمت بتغليفه في Docker، ولكن جافا سكريبت فقط مدعوم أصلاً، بالطبع هذه مسألة ذوق، لكنني أفضل شيئًا آخر بدلاً من js.
الاسبوع القادم سأقوم بالغناء مع أبلغ عن في مؤتمر Heisenbug 2020 Piter. لن أخبرك فقط بكيفية تجنب الأخطاء عند إعداد بيانات الاختبار، ولكن أيضًا سأشارك أسرار العمل مع مجموعات البيانات في تطبيقات Java!