GitHub Actions: یه روش ساده و کم هزینه برای راه اندازی CI/CD

پروژه مون آمادست و میخوایم بفرستیمش روی سرور. چه روشهایی داریم؟ یه سرور بگیریم و نرم افزارا رو نصب و کانفیگ کنیم ( مثلا PHP, Ngnix, MySQL و ....)برای پروژه مون داکر بنویسیم و اونو روی یه سرور عادی یا روی بستر K8 بالا بیاریمجدا از اینکه کدوم روشو در پیش بگیریم ما به یه CI/CD نیاز داریم که وقتی تغییری توی کدمون میدیم و روی git می فرستیم فرایند پول شدن پروژه روی سرور و اجرای دستوراتی که باید خودکار انجام شه.خوب چطوری این automation رو انجام بدیم؟من هر چه دیدم دور و برم بچه های DevOps کار چنین روشی رو رفتن یه سرور گیت لب گرفتن ( حداقل منابع مورد نیاز ۴ کور CPU و 4 گیگ رم و حدود ۵-۷ روز تا آماده پروداکشن بشه - با تمام تنظیمات و امنیت و ... که باید لحاظ بشه این زمانو گفتم)توی سرور مقصد گیت لب رانر نصب و کانفیگ می کنن ( بیش از ۱ گیگ رم و حدود ۱ روز کاری زمان)حالا کانفیگ CI رو برای گیت لب می نویسن تا دستورات دلخواه اجرا شه ( اینم حدود ۱ روز طول میکشه)همینطور که می بینین ما به منابعی با بیش از ۴ کور CPU و ۵ گیگ رم و بیش از ۷ روز کاری زمان نیاز داریم. آیا این برای همه پروژه ها منطقیه؟اگر شما یه دولوپر فول استک هستین و دوست دارین تمام کاراتونو خودتون انجام بدین، از طرفی میخواین پروژه تون هزینه پایینی داشته باشه نیازه برین سراغ ....GitHub Actionsگیت هاب چند سالیه که امکان ساخت ریپو خصوصی رو فراهم کرده، دیگه هم مشکلی با ایرانی بودن نداره. پس اول از همه بهتره بریم سراغ گیت هاب. اینطوری هم پروژه های خصوصیمون و هم عمومی یک جا خواهد بود.از طرفی ابزاری معرفی کرده به نام GitHub Actions که به شما کمک میده بعد از پوش/پول هر برنچ دلخواه عملیاتی که شما میخواین انجام شه.چطوری اکشن برای گیت هاب بنویسیم؟تتوی گیت هاب یه سر برگ به نام Actions هست و اونجا میتونین از روی نمونه ها یا داکیومنت کامل پیش برین. اما اینجا من میخوام در یک زمان کوتاه یه روش ساده برای انجام کارتون رو یاد بگیرین. پس بریم:۱. توی ریپوزیتون یه پوشه به نام .github بسازین و درون اون یه پوشه دیگه به نام workflows می سازین. داخل این پوشه قراره تنظیمات اکشن رو بسازیم۲. اینجا میتونین یک یا چند فایل با پسوند yml بسازین و اکشن ها رو اونجا بنویسین. من دو تا فایل ساختمdevelop.yml: برای اکشن های محیط stagingmain.yml: اکشن های سرور پروداکشن۳. خوب حالا بریم برای نوشتن فایل اکشن ( که بهش workflow گفته میشه )name: Main Deployیه اسم برای ورک فلو تون انتخاب کنین. این اسم رو توی صفحه اکشن ها در آینده می بینین. من باز اسم محیط پروداکشن و تست رو متفاوت قرار دادم.name: Main Deployon: push: branches: [ &quotmain&quot ]خوب در ادامه event ای رو که در ازای اتفاق افتادنش میخوایم این ورک فلو اجرا بشه رو مشخص کردیم. همینطور که می بینین مشخص شده که در طی پوش به برنچ main اجرا بشه.name: Main Deployon: push: branches: [ &quotmain&quot ]jobs: api-main:خوب حالا برای این ورک فلو میتونین چندین جاب تعریف کنیم که همزمان اجرا بشن. ما در اینجا یه جاب تعریف می کنیم. در ابتدای امر برای اون جاب اسمی انتخاب می کنیم ( api-main ) اسمیه که من برای جاب گذاشتم.name: Main Deployon: push: branches: [ &quotmain&quot ]jobs: api-main: runs-on: ubuntu-latestخوب runs-on چی میگه؟ ببینید گیت هاب برای اجرای اکشن ها یه سری رانر خودش داره و اکشنی که شما تعریف می کنین رو توی اون محیط اجرا میکنه. به عنوان مثال من اینجا مشخص کردم که روی رانری که ubuntu نسخه آخر رو داره اجراش کن.name: Main Deployon: push: branches: [ &quotmain&quot ]jobs: api-main: runs-on: ubuntu-latest steps: - name: Connect to Server & Push Updateخوب حالا این جاب api-main یه سری مراحل باید داشته باشه دیگه. ما برای هر مرحله اسمی میتونیم بزاریم که حین اجرای اکشن توی گیت هاب مراحل لاگ انداخته میشه و اگر هر عملی دچار مشکل بشه متوجهش میشین. به عنوان مثال شکل زیر - name: Go to Project Folder run: sudo cd /home/project - name: Make new Folder run: sudo mkdir testاینجا دو مرحله تعریف شده. ( توجه کنین به تو رفتگی ها indent - این فایل Yaml هست و تو رفتگی ها بسیار مهمه)خوب برگردیم به مثال خودمون:name: Main Deployon: push: branches: [ &quotmain&quot ]jobs: api-main: runs-on: ubuntu-latest steps: - name: Connect to Server & Push Update uses: appleboy/ssh-action@masterمن اینجا میخوام بصورت SSH به سرور خودم وصل شم و دستورات دلخواهم رو انجام بدم. ما میتونیم یا مثل مثال بالا از عبارت run استفاده کنیم و یه دستوری رو اجرا کنیم یا از عبارت uses استفاده کنیم. اما این uses چی میگه؟شما ممکنه برای اتصال به سرور و نقطه مقصد نیاز به یه سری نرم افزار نصب شده و موارد این چنینی داشته باشین. طبعا اون نرم افزار روی رانر گیت هاب نصب نیست. پس شما اینجا توی uses یک ریپوزیتوری رو مشخص میکنین ( طبعا توی خود گیت هاب باید باشه ) که توی اون ریپوزیتوری فایل docker ای نوشته شده برای ساپورت نیاز شما. مثلا یه ریپوزیتوری برای اتصال به AWS خواهد بود. یکی دیگه برای Azure و ...از طریق مثالهای خود گیت هاب میتونین با موارد مختلف آشنا شین. اما یه ریپوزیتوری ک من میخواستم و توی گیت هاب ندیدمش. اتصال ssh و انجام دستورات. ریپوزیتوری appleboy/ssh-action برای این نیاز هست. پس ما در اینجا به همین دلیل uses رو با مقدار این ریپو مشخص کردیم.name: Main Deployon: push: branches: [ &quotmain&quot ]jobs: api-main: runs-on: ubuntu-latest steps: - name: Connect to Server & Push Update uses: appleboy/ssh-action@master with: host: ${{ secrets.HOST }} port: ${{ secrets.PORT }} username: ${{ secrets.USERNAME }} key: ${{ secrets.SSH_PRIVATE_KEY }}خوب این ریپو طوری نوشته شده که نیاز داره یه سری مقادیر رو براش مشخص کنین. پس از عبارت with استفاده می کنیم و با تو رفتگی بیشتر داخلش موارد فوق رو مشخص می کنیم، مثلا اینطوری host: 10.25.31.26اما چرا ما اینطوری نوشتیمش:host: ${{ secrets.HOST }}طبعا شما نمیخواین کسی که به ریپوی شما دسترسی داره ( مثلا یکی از برنامه نویسها ) یا حتی ریپو عمومی باشه بتونه این فایل رو بخونه و اطلاعات سرور رو شما رو متوجه بشه. پس از عبارت ${{ secrets.HOST }} استفاده کردیم تا این مقدار رو جای دیگه تعریف کنیم. اما اونجا کجاست؟توی بخش settings همین پروژه توی بخش secrets and variables یه زیر بخش به نام actions هست. همونطور که توی عکس مشخصه من مقادیر رو وارد کردم. ( اگر حتی کسی بیاد و ویرایش رو بزنه مقدار فعلی رو نمیتونه ببینه)خوب حالا اون داکری که ساخته میشه تا ssh بزنه میتونه به سرور ما وصل شه. اما با یک نکته. ما بایستی کلید خصوصی ssh سرور مقصدمون رو اینجا وارد کنیم. خوب چطوری اونو بدست میاریم؟توی سرور خودتون این دستور رو اجرا کنینssh-keygen -t rsa -b 4096 -C "mreza_golestan@live.com"بلافاصله سوالی پرسیده میشه که پیشنهاد میکنم در جوابش مقدار github-actions رو وارد کنین. تا کلیدی که ساخته میشه مجزا باشه و با همین نام. حالا دستور زیر رو اجرا کنین sudo cat ~/.ssh/github-actionsبا این دستور ما مقدار داخل فایل کلید خصوصی github-actions رو که درون پوشه .ssh ساخته شده خواهیم دید. این مقدار رو کپی کنین و داخل مقدار SSH_PRIVATE_KEY گیت هاب بزارینname: Main Deployon: push: branches: [ &quotmain&quot ]jobs: api-main: runs-on: ubuntu-latest steps: - name: Connect to Server & Push Update uses: appleboy/ssh-action@master with: host: ${{ secrets.HOST }} port: ${{ secrets.PORT }} username: ${{ secrets.USERNAME }} key: ${{ secrets.SSH_PRIVATE_KEY }} script: | cd /home/testapi git reset --hard && git pull origin master composer dump-autoload composer update php artisan storage:link php artisan migrate php artisan optimizeحالا در ادامه داخل عبارت script دستورات دلخواهتون رو قرار بدین.نمونه مثالی که من آوردم برای اجرای لاراول هست. یه توضیحی درباره اش میدم شاید کمک کننده باشه: در ابتدا وارد پوشه پروژه شدیمدستور git reset --hard && git pull origin master رو اجرا کردیم. قسمت اول باعث میشه اگر یه زمانی خدای نکرده. گوش شیطون کر رفتین یه فایل پروژه ( که البته جزو گیت باشه) رو ویرایش کردین دچار مشکل نشیم. چون در این صورت دستور git pull خطا میده. اما git reset --hard باعث میشه اول کدها به حالت آخرین کامیت در بیان و بعد git pull زده بشهدستور composer dump-autoload هم قبل از update زدم. چرا؟ اگر library جدیدی اضافه کرده باشین که نیاز بوده service provider اشو توی config/app.php بزارین. حین دستور update خطا میگیرین مگر dump-autoload کرده باشیندر نهایت هم که دستورات artisan خود لاراول رو زدمطبق تجربه خود من در کمتر از یک دقیقه نسخه جدید کد شما روی سرور با موفقیت قرار میگیره.یه نکته: گیت هاب اکشن تا ۲۰۰۰ دقیقه اجرا در ماه رایگانه. که حدود ۲ هزار پوش میشه. یعنی بیش از ۶۶ تا پوش در روز. ک بعید میدونم این تعداد پوش انجام بدین در روز. اما اگر هم احیانا براتون کم باشه. هر دقیقه ۰.۰۰۸ دلار هزینه داره یعنی اگر ۱۰۰۰ دقیقه اضافه تر هم استفاده کنین فقط ۸ دلار نیازه بپردازین.طبق تجربه من یه تیم ۱۰ نفره هم عموما به این محدودیت ۲۰۰۰ دقیقه نمیرسهامیدوارم این مطلب براتون مفید باشه. خوشحال میشم نظر بدین