گیتلب و CI/CD: یک راهنمای ساده - قسمت اول

مقدمه

برای این که یک برنامه رو دیپلوی کنیم و به کاربران عرضه کنیم فقط نوشتن کدهای برنامه کافی نیست و لازمه استراتژی مناسبی برای این که چجوری و در چه زمان‌هایی دیپلوی کنیم هم داشته‌ باشیم. یکی از روش‌های مرسوم CI/CD هست که در این مطلب قصد داریم به اهمیت اون و معرفی Gitlab CI بپردازیم. قصدم بر اینه که طی چند نوشته با مفاهیم ابتدایی تا نسبتا پیشرفته در Gitlab CI آشنا بشیم و کار کنیم.

در این نوشته لازمه که با دستورات در شل لینوکس آشنایی داشته باشید. هم‌چنین داشتن اطلاعات در مورد کانتینرها و داکر هم مفیده.


مفهوم و ابزارهای CI/CD

این عبارت مخفف Continuous Integration Continuous Delivery یا Deployment هست. همون طور که مشخصه از دو بخش تشکیل میشه؛ بخش اول مربوط به تست و بیلد برنامه‌ها و بخش دوم مربوط به دیپلوی کردن هست. یک عبارت مهم هم در جفتشون هست که به استمرار زمانی اشاره داره. ما در این روش به کمک ابزارهایی به طور پیوسته کدهامون رو بیلد، تست و دیپلوی می‌کنیم.

گفتیم ابزارهایی برای این کار لازمه. ابزاری که همیشه استفاده میشه گیت هست. در اصل این پیوستگی با استفاده از پوش کردن در یک سرور گیت رخ میده.‌ با انجام تنظیماتی می‌تونیم بگیم هر وقت به برنچ خاصی پوش شد اون کد رو بیلد، تست و دیپلوی کن. کنار گیت یک سری ابزار دیگه هم باید باشن که یک pipeline رو برای ما تشکیل بدن تا این پیوستگی رو داشته باشیم. خیلی دوست داریم که هر چه بیشتر این ابزارهای لازم توی خود گیت سرور باشن تا ما دردسرهای کمتری داشته باشیم. خبر خوب اینه که چنین چیزی وجود داره و اون هم گیتلب (Gitlab) هست. گیتلب یک گیت سرور هست که هم سایتش به آدرس gitlab.com موجوده و به شکل open source در اختیار ما قرار داره و می‌تونیم ازش به عنوان گیت سروری که مجموعه‌ی ابزارهای CI/CD رو داره استفاده کنیم.


گیتلب و CI/CD

فارغ از این که از gitlab.com استفاده کنیم یا خودمون بالا بیاریمش، یک سری عبارت هستن که ازش استفاده می‌کنیم. تو این قسمت می‌خوایم به اونا بپردازیم.

برای این که برای یک repo در گیتلب CI/CD داشته باشیم یک فایل به نام gitlab-ci.yml. داخل پوشه اصلی پروژه می‌ذاریم. داخل این فایل کارهایی که برای CI/CD لازمه رو می‌نویسیم که در ادامه به اون هم می‌رسیم.

وقتی ما می‌خوایم عملیات بیلد، تست و دیپلوی رو انجام بدیم ابزاری باید باشه که این‌ها رو اجرا کنه. این ابزار یک نرم‌افزار هست که می‌تونه کارهایی که تو gitlab-ci.yml. نوشته شده رو انجام بده. به این‌ نرم‌افزار گیتلب رانر (gitlab runner) میگیم. سایت گیتلب رانرهایی داره که میشه از اون‌ها استفاده کرد. خودمون هم می‌تونیم رانر بالا بیاریم و به گیتلب معرفی کنیم تا pipeline توسط اون انجام بشه. به رانری که همه‌ی پروژه‌های موجود در یک instance گیتلب می‌تونن روش pipeline اجرا کنن میگیم shared runner. منظورم از instance همون گیتلب هست که جایی بالا اومده. حالا می‌تونه همون gitlab.com باشه یا روی سرور خودمون.

حالا گیتلب رانر رو کجا بالا بیاریم؟ هر محیطی که بشه توش گیتلب رانر رو اجرا کرد می‌تونه باشه. مثلا لینوکس روی ماشین مجازی یا یه کانتینر.

گیتلب رانر رو یه جایی اجرا کردم. دستورهایی که بهش میدم رو چجوری و کجا اجرا می‌کنه؟ به اون میگیم executor. مثلا ممکنه بخوام داخل shell این کارو کنه برام. یا مثلا داخل کانتینر. این رو موقعی که به گیتلب معرفیش می‌کنم باید تعیین کنم.

برای این آموزش از دارکوب استفاده می‌کنم که یکی از سرویس‌های شرکت هم‌روش هست و به ما کمک می‌کنه برنامه‌های خودمون رو به راحتی دیپلوی کنیم. دارکوب pipeline رو داخل کانتینر داکر و به کمک کوبرنتیز اجرا می‌کنه. برای گیت هم از هم‌گیت استفاده می‌کنم که سرویس گیتلب هم‌روش هست و به شکل رایگان در دسترسه.


ثبت رانر در هم‌گیت

برای ثبت یک رانر در گیتلب باید به Settings -> CI/CD و بعد به بخش Runners بریم و رانر رو ثبت کنیم. در این بحث نمیخوام راجع به رانرها زیاد صحبت کنم به همین دلیل از رانر هم‌گیت استفاده می‌کنم. در هم‌گیت لازم نیست رانر رو ثبت کنیم؛ چون خودش ثبت می‌کنه. فقط باید به همونجا بریم و دکمه "Enable shared runners" رو بزنیم که دکمه سبز رنگ در تصویر زیر است:

سورس کد خودمون رو که به هم‌گیت پوش کردیم به سراغ دارکوب میریم. اول یک اپ جدید می‌سازیم:

"منبع گیت" رو انتخاب می‌کنیم. با این کار ما به دارکوب میگیم که کد ما رو از رو هم‌گیت بخونه. با زدن "انتخاب ریپو" بهش آدرس پروژه رو میدیم:

بقیه مراحل هم طی می‌کنیم تا اپ تکمیل بشه. بعد از این هر وقت به برنچ master پوش کنیم یک فرایندی رو خود دارکوب با darkube-cli انجام میده که یک ایمیج می‌سازه و اون رو دیپلوی می‌کنه. اما اگر بخوایم خودمون این فرایند رو با گیتلب CI انجام بدیم لازم هست یه کاری کنیم. دارکوب برای این که بیلد و دیپلوی رو انجام بده میاد یک webhook برای پروژه‌ی ما تنظیم می‌کنه. به قسمت Settings -> Webhooks در پروژه‌تون برید. پایین صفحه یه دونه webhook در بخش Project webhooks می‌بینید:

جلوش delete رو بزنید تا دیگه دارکوب خودش برنامه رو بیلد و دیپلوی نکنه و ما خودمون این فرایند رو به دست بگیریم.


اجرای یک pipeline ساده

برای این که بتونیم با نوشتن gitlab-ci.yml. آشنا بشیم به سبک زبان‌های برنامه‌نویسی یه hello world انجام میدیم. یعنی فقط یک متن ساده رو چاپ می‌کنه برامون.‌ یک سری مفاهیم هستن که خوبه قبل از نوشتن بدونیم.

اولیش stage هست. می‌تونیم مرحله ترجمه‌اش کنیم. در هر stage تعدادی کار انجام میشه که به اون‌ها job میگیم. هر stage یک هدفی رو دنبال می‌کنه؛ مثلا یک stage برای بیلد قرار میدیم. می‌تونیم چندین کار مختلف تعریف کنیم تا به این هدف برسیم. stage‌ها به همون ترتیبی که ما تعیین کردیم اجرا میشن. به طور پیش فرض سه تا stage در گیتلب داریم که به ترتیب deploy, test, build هستن.‌

همون طور که گفته شد یک stage از تعدادی job تشکیل شده و کارهایی هست که ما به گیتلب رانر میگیم انجام بده. مثلا در یک job من برنامه رو کامپایل می‌کنم و از روش ایمیج جدید می‌سازم. توجه کنید که jobهای یک stage همزمان اجرا میشن. اگر یک job دچار مشکل بشه دیگه stageهای بعدی اجرا نمیشن ولی jobهای همون stage اجرا میشن.

حالا که این مفاهیم رو به شکل نظری دیدیم بیاید یک gitlab-ci.yml. ساده بنویسیم. ابتدا یک job می‌نویسیم و یک اسم برای job انتخاب می‌کنیم:

اسمی که انتخاب کردم hello-world است. جلوی اسم دو نقطه می‌ذارم و به توصیف اون می‌پردازم. یک بخش خیلی مهم در هر job دستوراتی هست که قراره اجرا بشه. اون رو با script مشخص می‌کنیم:

بعد از script یک لیست از دستورات نوشته میشه که به ترتیب اجرا میشن. من این‌جا یک دستور فقط دارم که hello world from Hamravesh رو چاپ می‌کنه. برای تمرین اسم خودتون رو به جای Hamravesh بذارید! دقت کنید این یک لیسته و با - اجزای مختلفش مشخص میشه. بعدش stage هست که میگه این job در چه stageی هست:

اگر این رو نذاریم stage رو test در نظر می‌گیره. البته چون ما فقط یک job داریم stage اهمیتی نداره. ولی حالا گذاشتم. شما هم بذارید! در اینجا image هم لازم هست که همیشه لازم نمیشه و به محیطی که executor داره بستگی داره. در مورد دارکوب به این احتیاج داریم چون از داکر استفاده می‌کنه (اگر ندیم خودش ایمیج پیشفرض رو اجرا می‌کنه که ubuntu:16.04 هست):

ایمیج انتخابی من ubuntu:20.04 هست. من این فایل رو دستی در هم‌گیت ایجاد کردم و خودش یک commit درست کرد. بعدش هم شروع به اجرای فرایند CI/CD می‌کنه و علامتش رو میشه کنار commit hash دید:

اگر در حال اجرا باشه علامت آبی رنگ میده. اگر خطا داشته باشه قرمز. اگر موفق باشه سبز و اگر منتظر اجرا شدن باشه نارنجی رنگ میشه. روش کلیک می‌کنم و به این صفحه میرم:

می‌تونستم از پنل روی CI/CD -> Pipelines بزنم و بعد به pipeline دلخواه برم و به همین صفحه می‌رسم. تو این صفحه stageها و jobهای هر مرحله رو می‌بینم. من فقط یه stage و یه job داشتم. حالا روی اون job کلیک می‌کنم تا لاگ‌هاش رو ببینم:

و به این شکل این اولین pipeline رو به زیبایی اجرا کردیم.


جمع بندی

در این قسمت با CI/CD و Gitlab CI آشنا شدیم. بعدش مفاهیم ابتدایی در Gitlab CI رو دیدیم. در بخش آخر هم یک pipeline ساده رو اجرا کردیم. امیدوارم این مطلب براتون مفید بوده باشه. اگر سوال یا نظری دارید این پایین بنویسید.