ProHoster > وبلاگ > اداره > حلقه های جهنم با GitHub Actions (ساخت خط لوله CI/CD برای پروژه جاوا)
حلقه های جهنم با GitHub Actions (ساخت خط لوله CI/CD برای پروژه جاوا)
من اغلب مجبورم برای ساختن پروژه ها در جاوا یک خط لوله بسازم. گاهی اوقات متن باز است، گاهی اوقات اینطور نیست. من اخیراً تصمیم گرفتم برخی از مخازن خود را از Travis-CI و TeamCity به GitHub Actions منتقل کنم و این همان چیزی است که از آن بیرون آمد.
چه چیزی را خودکار خواهیم کرد؟
ابتدا به پروژه ای نیاز داریم که آن را خودکار می کنیم، بیایید یک برنامه کوچک در Spring boot / Java 11 / Maven ایجاد کنیم. برای اهداف این مقاله، ما به هیچ وجه علاقه ای به منطق برنامه نخواهیم داشت، زیرساخت اطراف برنامه برای ما مهم است، بنابراین یک کنترلر ساده REST API برای ما کافی است.
در اینجا می توانید منابع را مشاهده کنید: github.com/antkorwin/github-actions تمام مراحل ساخت خط لوله در درخواست های کشش برای این پروژه منعکس شده است.
JIRA و برنامه ریزی
شایان ذکر است که ما معمولاً از JIRA به عنوان ردیاب مشکل استفاده می کنیم، بنابراین بیایید یک برد جداگانه برای این پروژه ایجاد کنیم و اولین شماره ها را در آنجا اضافه کنیم:
کمی بعد به چیزهای جالبی که JIRA و GitHub می توانند در ترکیب ارائه دهند باز خواهیم گشت.
ما مونتاژ پروژه را خودکار می کنیم
پروژه آزمایشی ما از طریق maven ساخته شده است، بنابراین ساخت آن بسیار ساده است، تنها چیزی که ما نیاز داریم بسته mvn تمیز است.
برای انجام این کار با استفاده از Github Actions، باید یک فایل در مخزن ایجاد کنیم که گردش کار ما را شرح می دهد، این را می توان با یک فایل yml معمولی انجام داد، نمی توانم بگویم که برنامه نویسی yml را دوست دارم، اما چه کاری می توانیم انجام دهیم - ما این کار را در .github/directory workflow/ file build.yml انجام می دهیم که در آن اقدامات هنگام ساختن شاخه اصلی را شرح می دهیم:
on - این شرح رویدادی است که فیلمنامه ما در آن راه اندازی می شود.
در: pull_request/push - نشان می دهد که این گردش کار باید هر بار که فشاری به master انجام می شود و درخواست های کشش ایجاد می شود راه اندازی شود.
در زیر شرح وظایف (شغل ها) و مراحل اجرا (مراحل) برای هر کار.
اجرا می شود - در اینجا ما می توانیم سیستم عامل مورد نظر را انتخاب کنیم، با کمال تعجب، شما حتی می توانید Mac OS را انتخاب کنید، اما در مخازن خصوصی این بسیار گران است (در مقایسه با لینوکس).
استفاده به شما امکان می دهد تا از سایر اقدامات استفاده مجدد کنید، برای مثال، با استفاده از actions/setup-java که ما محیط را برای جاوا 11 نصب می کنیم.
با استفاده از با ما میتوانیم پارامترهایی را که با آن اکشن را راهاندازی میکنیم مشخص کنیم، در اصل این آرگومانهایی هستند که به اکشن ارسال میشوند.
تنها چیزی که باقی می ماند اجرای ساخت پروژه در Maven است: run: mvn -B clean package پرچم -B می گوید که ما به یک حالت غیر تعاملی نیاز داریم تا ماون ناگهان نخواهد چیزی از ما بپرسد
عالی! اکنون، هر بار که به Master متعهد می شوید، ساخت پروژه شروع می شود.
راه اندازی آزمایشی خودکار
مونتاژ خوب است، اما در واقع، یک پروژه را می توان با خیال راحت مونتاژ کرد، اما کار نمی کند. بنابراین، گام بعدی، خودکار کردن اجرای آزمایشی است. علاوه بر این، هنگام بررسی روابط عمومی، نگاه کردن به نتایج گذراندن آزمونها بسیار راحت است - مطمئناً میدانید که آزمونها قبول میشوند و هیچکس فراموش نکرده است که شعبه خود را قبل از انجام ادغام اجرا کند.
هنگام ایجاد یک درخواست کشش، آزمایشهایی را اجرا میکنیم و در Master ادغام میکنیم، و در همان زمان ایجاد یک گزارش در مورد پوشش کد را اضافه میکنیم.
برای پوشش تست ها، من از codecov به همراه پلاگین jacoco استفاده می کنم. codecov عمل خودش را دارد، اما برای کار با درخواست کشش ما به یک توکن نیاز دارد:
${{ secrets.CODECOV_TOKEN }} - ما بیش از یک بار این ساختار را خواهیم دید، Secrets مکانیزمی برای ذخیره اسرار در GitHub است، ما می توانیم رمزهای عبور / نشانه ها / میزبان ها / URL ها و سایر داده هایی را که نباید در پایگاه کد مخزن گنجانده شوند، در آنجا بنویسیم.
می توانید در تنظیمات مخزن در GitHub یک متغیر به Secrets اضافه کنید:
شما می توانید یک نشانه دریافت کنید codecov.io پس از مجوز از طریق GitHub، برای افزودن یک پروژه عمومی فقط باید پیوندی مانند این را دنبال کنید: نام کاربری GitHub/[نام مخزن]. یک مخزن خصوصی نیز میتواند اضافه شود؛ برای این کار، باید حقوق codecov را به برنامه در Github بدهید.
اکنون ربات codecov هر یک از درخواست های کشش ما را وارد می کند و یک نمودار تغییر پوشش اضافه می کند:
بیایید یک تحلیلگر استاتیک اضافه کنیم
در بسیاری از پروژه های منبع باز خود از ابر سونار برای تجزیه و تحلیل کد استاتیک استفاده می کنم، اتصال به travis-ci بسیار آسان است. بنابراین در هنگام مهاجرت به GitHub Actions انجام همین کار یک مرحله منطقی است. بازار اکشن چیز جالبی است، اما این بار من را کمی ناامید کرد، زیرا از روی عادت اکشن مورد نیاز خود را پیدا کردم و آن را به جریان کار اضافه کردم. اما مشخص شد که سونار از کار از طریق یک اقدام برای تجزیه و تحلیل پروژه ها در maven یا gradle پشتیبانی نمی کند. البته این در مستندات نوشته شده ولی کی میخونه؟!
از طریق یک عمل امکان پذیر نیست، بنابراین ما آن را از طریق افزونه mvn انجام خواهیم داد:
SONAR_TOKEN - می توان در به دست آورد sonarcloud.io و شما باید آن را به صورت مخفیانه ثبت کنید. GITHUB_TOKEN - این یک توکن داخلی است که GitHub تولید میکند و با کمک آن sonarcloud[bot] میتواند به Git وارد شود تا در درخواستهای کشش برای ما پیام بگذارد.
Dsonar.projectKey - نام پروژه در سونار، می توانید آن را در تنظیمات پروژه ببینید.
Dsonar.سازمان - نام سازمان از GitHub.
ما یک درخواست کشش می کنیم و منتظر می مانیم تا sonarcloud[bot] در نظرات بیاید:
مدیریت انتشار
بیلد پیکربندی شده است، تستها اجرا شدهاند، و ما میتوانیم آن را منتشر کنیم. بیایید ببینیم که چگونه GitHub Actions میتواند مدیریت انتشار را بسیار آسانتر کند.
در محل کار، پروژههایی دارم که پایه کدشان در bitbucket است (همه چیز مانند آن داستان است: «در روز به bitbucket مینویسم، شبها به GitHub متعهد میشوم»). متأسفانه، bitbucket ابزارهای مدیریت انتشار داخلی ندارد. این یک مشکل است، زیرا برای هر نسخه باید به صورت دستی یک صفحه را به صورت همزمان ایجاد کنید و تمام ویژگی های موجود در نسخه را در آنجا پرتاب کنید، در قصرهای ذهن، وظایف در جیرا، commit ها در مخزن جستجو کنید. شانس های زیادی برای اشتباه وجود دارد، می توانید چیزی را فراموش کنید یا چیزی را وارد کنید که قبلاً آخرین بار منتشر شده است، گاهی اوقات به سادگی مشخص نیست که یک درخواست کشش را به عنوان طبقه بندی کنید - آیا این یک ویژگی است یا رفع اشکال، یا آزمایش های ویرایش، یا چیزی زیرساختی .
اقدامات GitHub چگونه می تواند به ما کمک کند؟ یک اقدام عالی وجود دارد - پیش نویس انتشار، به شما امکان می دهد یک الگوی فایل یادداشت های انتشار را تنظیم کنید تا دسته بندی درخواست های کشش را تنظیم کنید و به طور خودکار آنها را در فایل یادداشت های انتشار گروه بندی کنید:
الگوی مثال برای تنظیم گزارش (github/release-drafter.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):
همه درخواست های کشش از این پس به صورت خودکار در یادداشت های انتشار جمع آوری می شوند - جادو!
در اینجا ممکن است این سوال پیش بیاید: اگر توسعه دهندگان فراموش کنند برچسب ها را در روابط عمومی قرار دهند چه؟ بعد مشخص نیست که در کدام دسته قرار دهیم و باز هم باید به صورت دستی و با هر PR جداگانه با آن برخورد کنید. برای رفع این مشکل، میتوانیم از اقدام دیگری استفاده کنیم - تأییدکننده برچسب - وجود برچسبها را در درخواست کشش بررسی میکند. اگر هیچ تگ مورد نیازی وجود نداشته باشد، بررسی ناموفق خواهد بود و پیامی در این مورد در درخواست pull خود مشاهده خواهیم کرد.
اکنون هر درخواست کششی باید با یکی از تگ ها علامت گذاری شود: type:fix، type:features، type:documentation، type:tests، type:config.
حاشیه نویسی خودکار درخواست های کشش
از آنجایی که ما به موضوعی به عنوان کار مؤثر با درخواست های کششی دست زدیم، ارزش دارد در مورد چنین اقدامی مانند برچسب زدن صحبت کنیم، برچسب هایی را در روابط عمومی قرار می دهد که بر اساس آن فایل ها تغییر کرده اند. برای مثال، میتوانیم هر درخواست کششی را که حاوی تغییراتی در دایرکتوری باشد، به عنوان [build] علامتگذاری کنیم .github/workflow.
من موفق نشدم اقدامی را که بهطور خودکار برچسبها را در درخواستهای کشش قرار میدهد، با عملی که وجود برچسبهای مورد نیاز را بررسی میکند، جفت کنم؛ Match-label نمیخواهد برچسبهای اضافه شده توسط ربات را ببیند. به نظر می رسد نوشتن اکشن خود که هر دو مرحله را با هم ترکیب می کند آسان تر باشد. اما حتی در این فرم استفاده از آن کاملاً راحت است؛ هنگام ایجاد درخواست کشش باید یک برچسب از لیست انتخاب کنید.
زمان استقرار فرا رسیده است
من چندین گزینه استقرار را از طریق GitHub Actions (از طریق ssh، از طریق scp و با استفاده از docker-hub) امتحان کردم، و می توانم بگویم که به احتمال زیاد، شما راهی برای آپلود باینری در سرور پیدا خواهید کرد، مهم نیست که خط لوله شما چقدر کج باشد. است.
من گزینه نگهداری کل زیرساخت را در یک مکان دوست داشتم، بنابراین بیایید نحوه استقرار در بستههای GitHub را بررسی کنیم (این یک مخزن برای محتوای باینری، npm، jar، docker است).
اسکریپت ساخت یک تصویر داکر و انتشار آن در بستههای GitHub:
ابتدا باید فایل JAR برنامه خود را بسازیم و پس از آن مسیر رجیستری داکر GitHub و نام تصویر خود را محاسبه می کنیم. در اینجا چند ترفند وجود دارد که ما هنوز به آنها برخورد نکرده ایم:
ساختاری مانند: echo "::set-output name=NAME::VALUE" به شما امکان می دهد مقدار یک متغیر را در مرحله فعلی تنظیم کنید تا در تمام مراحل دیگر قابل خواندن باشد.
می توانید مقدار مجموعه متغیر در مرحله قبل را از طریق شناسه این مرحله دریافت کنید: ${{ steps.global_env.outputs.DOCKERHUB_IMAGE_NAME }}
متغیر استاندارد GITHUB_REPOSITORY نام مخزن و صاحب آن ("مالک/نام ذخیره") را ذخیره می کند. برای برش همه چیز از این خط به جز نام مخزن، از دستور bash استفاده می کنیم: ${GITHUB_REPOSITORY#*/}
برای نشان دادن نسخه تصویر، ما از اولین ارقام از هش SHA commit استفاده می کنیم - GITHUB_SHA در اینجا تفاوت های ظریفی نیز وجود دارد، اگر چنین ساخت هایی را نه تنها هنگام ادغام در Master ایجاد کنید، بلکه با توجه به ایجاد درخواست کشش رویداد، پس SHA ممکن است با هشی که در تاریخچه git میبینیم مطابقت نداشته باشد، زیرا اقدام actions/checkout هش منحصربهفرد خود را ایجاد میکند تا از اقدامات بنبست در روابط عمومی جلوگیری کند.
اگر همه چیز به خوبی انجام شد، سپس بخش بسته ها (https://github.com/antkorwin/github-actions/packages) را در مخزن باز کنید، یک تصویر داکر جدید خواهید دید:
در آنجا همچنین می توانید لیستی از نسخه های تصویر داکر را مشاهده کنید.
تنها چیزی که باقی می ماند این است که سرور خود را برای کار با این رجیستری پیکربندی کنیم و سرویس را مجدداً راه اندازی کنیم. احتمالاً زمان دیگری در مورد نحوه انجام این کار از طریق systemd صحبت خواهم کرد.
نظارت
بیایید به یک گزینه ساده در مورد نحوه انجام بررسی سلامت برنامه خود با استفاده از GitHub Actions نگاه کنیم. برنامه بوت ما یک محرک دارد، بنابراین حتی نیازی به نوشتن API برای بررسی وضعیت آن نداریم؛ ما قبلاً همه چیز را برای تنبل ها انجام داده ایم. شما فقط باید میزبان را بکشید: SERVER-URL:PORT/actuator/health
تنها چیزی که نیاز داریم این است که با استفاده از cron یک تسک بنویسیم تا سرور را بررسی کنیم و اگر ناگهان جواب ما را نداد، از طریق تلگرام اعلان ارسال می کنیم.
بیایید وضعیت سرور را به صورت دستی از طریق curl بررسی کنیم:
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
فراموش نکنید که در Secrets در Github بنویسید: URL برای سرور و توکن برای ربات تلگرام.
آهنگ جایزه - JIRA برای تنبل ها
قول دادم به جیرا برگردیم و برگشتیم. صدها بار من وضعیتی را در استند آپ ها مشاهده کرده ام که توسعه دهندگان یک ویژگی را ایجاد کردند، یک شاخه را ادغام کردند، اما فراموش کردند این مشکل را به JIRA بکشند. البته اگر همه اینها در یک مکان انجام می شد، راحت تر بود، اما در واقع ما کد را در IDE می نویسیم، شاخه ها را در bitbucket یا GitHub ادغام می کنیم و سپس وظایف را به Jira می کشیم، برای این کار باید پنجره های جدیدی را باز کنیم. ، گاهی اوقات دوباره وارد شوید و غیره. وقتی کاملاً به یاد بیاورید که چه کاری باید انجام دهید، دیگر هیچ فایده ای برای باز کردن مجدد تابلو ندارد. در نتیجه، صبح در یک استندآپ باید زمانی را صرف به روز رسانی صفحه کار کنید.
GitHub همچنین در این کار معمولی به ما کمک خواهد کرد؛ برای شروع، میتوانیم هنگام ارسال درخواست کشش، مسائل را بهطور خودکار به ستون code_review بکشیم. تنها کاری که باید انجام دهید این است که از قرارداد نامگذاری شاخه پیروی کنید:
[имя проекта]-[номер таска]-название
برای مثال، اگر کلید پروژه "GitHub Actions" GA باشد، پس GA-8-jira-bot می تواند شاخه ای برای اجرای وظیفه GA-8 باشد.
ادغام با JIRA از طریق اقدامات Atlassian انجام می شود، آنها کامل نیستند، باید بگویم که برخی از آنها اصلا برای من کار نکردند. اما ما فقط در مورد مواردی صحبت خواهیم کرد که قطعاً کار می کنند و به طور فعال مورد استفاده قرار می گیرند.
ابتدا باید با استفاده از اکشن: atlassian/gajira-login به JIRA وارد شوید
- 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 است که در بالا انجام دادیم.
به همین ترتیب، میتوانید هنگام ادغام در Master و سایر رویدادها را از گردش کار GitHub بکشید. به طور کلی، همه چیز به تخیل و تمایل شما برای خودکارسازی فرآیندهای معمول بستگی دارد.
یافته ها
اگر به نمودار کلاسیک DEVOPS نگاه کنید، ما همه مراحل را پوشش دادهایم، به جز احتمالاً عملیات، فکر میکنم اگر تلاش کنید، میتوانید اقداماتی را در بازار برای ادغام با سیستم Help-desk پیدا کنید، بنابراین فرض میکنیم که خط لوله برگشته است. کامل باشد و بر اساس استفاده از آن بتوان نتیجه گرفت.
مزایا:
بازار با اقدامات آماده برای همه موارد، این بسیار جالب است. در بسیاری از آنها، میتوانید به کد منبع نگاه کنید تا متوجه شوید که چگونه یک مشکل مشابه را حل کنید یا یک درخواست ویژگی را مستقیماً در مخزن GitHub برای نویسنده ارسال کنید.
انتخاب پلتفرم هدف برای مونتاژ: لینوکس، سیستم عامل مک، ویندوز یک ویژگی بسیار جالب است.
بستههای Github چیز بسیار خوبی است، نگه داشتن کل زیرساخت در یک مکان راحت است، لازم نیست در پنجرههای مختلف گشت و گذار کنید، همه چیز در شعاع یک یا دو کلیک ماوس است و کاملاً با GitHub Actions یکپارچه شده است. پشتیبانی از رجیستری Docker در نسخه رایگان نیز مزیت خوبی است.
GitHub اسرار را در لاگ های ساخت پنهان می کند، بنابراین استفاده از آن برای ذخیره رمزهای عبور و توکن ها چندان ترسناک نیست. در طول تمام آزمایشاتم، هرگز نتوانستم راز را به شکل خالص آن در کنسول ببینم.
رایگان برای پروژه های منبع باز
منفی:
YML، خوب، من او را دوست ندارم. هنگام کار با چنین جریانی، متداولترین پیام commitی که دارم این است که «فرمت yml را اصلاح کنید»، سپس فراموش میکنید یک برگه را در جایی قرار دهید یا آن را روی خط اشتباه مینویسید. به طور کلی، نشستن مقابل صفحه نمایش با نقاله و خط کش خوشایندترین تجربه نیست.
DEBUG، اشکال زدایی جریان با commit ها، اجرای بازسازی و خروجی به کنسول همیشه راحت نیست، اما بیشتر از دسته «شما زیاده روی کرده اید» است؛ زمانی که می توانید هر چیزی را اشکال زدایی کنید، عادت دارید با IDEA راحت کار کنید. .
اگر آن را در Docker بپیچید می توانید روی هر چیزی بنویسید، اما فقط جاوا اسکریپت به صورت بومی پشتیبانی می شود، البته این یک موضوع سلیقه ای است، اما من چیز دیگری را به جای js ترجیح می دهم.
هفته آینده با هم اجرا خواهم داشت گزارش در کنفرانس Heisenbug 2020 Piter. من نه تنها به شما می گویم که چگونه هنگام تهیه داده های آزمایشی از اشتباه جلوگیری کنید، بلکه اسرار کار با مجموعه داده ها در برنامه های جاوا را نیز به اشتراک می گذارم!