GitLab CI/CD چیست و چرا در توسعه نرمافزار مهم است؟
در توسعهی نرمافزار مدرن، فقط نوشتن کد کافی نیست. هر تغییری که در کد ایجاد میشود باید تست شود، بررسی شود و بهصورت امن و قابل اعتماد منتشر شود. انجام این مراحل بهصورت دستی نهتنها زمانبر است، بلکه احتمال خطا را هم بهشدت افزایش میدهد.
اینجاست که مفهوم CI/CD و ابزارهایی مثل GitLab CI/CD وارد بازی میشوند.
GitLab CI/CD یکی از قابلیتهای اصلی GitLab است که به تیمهای توسعه کمک میکند فرآیندهای ساخت (Build)، تست (Test) و انتشار (Deploy) نرمافزار را بهصورت خودکار انجام دهند.
CI/CD یعنی چه؟
Continuous Integration (CI)
به معنی «یکپارچهسازی مداوم» است. فرض کنید در یک تیم نرم افزاری کار میکنید و چندین توسعه دهنده در حال کدنویسی روی بخش های مختلف پروژه هستند. هر بار که کار یکی از این توسعه دهنده ها تمام میشود، تغییراتی که ایجاد کرده باید با کد قبلی پروژه ادغام شوند. برای این که مطمئن شویم تغییرات جدید، ایرادات و باگ های جدید به پروژه اضافه نمیکند، باید مکانیزمی وجود داشته باشد که فرآیند build پروژه را به صورت اتوماتیک انجام دهد. یعنی شرایط لازم برای اجرای برنامه را ایجاد کند. سپس باید تست های پروژه اجرا شوند تا اطمینان حاصل شود که همگی به درستی pass میشوند. در نهایت اگر مشکلی بود بتوان آن را به آسانی شناسایی کرد. این فرآیند همان بخش CI است.
یعنی در CI، هر بار که کدی به مخزن (Repository) اضافه میشود:
-
کد بهصورت خودکار build میشود
-
تستها اجرا میشوند
-
مشکلات خیلی زود شناسایی میشوند
هدف CI این است که خطاها در همان ابتدای مسیر توسعه کشف شوند، نه بعد از رفتن به محیط production. زیرا در این صورت کاربران نهایی پروژه با مشکل روبرو میشوند و این مشکلات منجر به اتفاقات بزرگتر مثل از بین رفتن اعتماد کاربران یا حتی خسارتهای مالی میشود.
Continuous Delivery / Deployment (CD)
CD ادامهی مسیر CI است. پس از اینکه اطمینان حاصل کردیم که تغییرات جدید ایمن هستند و پروژه با وجود این تغییرات جدید به درستی کار میکند، باید ادامهی فرآیند را پیش ببریم و تغییرات جدید را به دست کاربران برسانیم. به این مکان که کاربران نهایی پروژه با آن تعامل دارند، اصطلاحا production گفته میشود.
مرحله CD دو مدل مختلف دارد:
-
Continuous Delivery: کد همیشه آمادهی انتشار است.
-
Continuous Deployment: کد بهصورت خودکار وارد محیط production میشود.
GitLab CI/CD از هر دو مدل پشتیبانی میکند.
تعریف GitLab CI/CD
GitLab CI/CD یک سیستم یکپارچه برای اجرای تمام مراحلی هست که تا به اینجا در مورد آنها صحبت کردیم. این مراحل که باید به ترتیب و پشت سر هم اجرا شوند، pipeline نامیده میشوند. جالب است بدانید که برای استفاده از Gitlab CI/CD نیاز به هیچ ابزار جانبی ندارید و این قابلیت مستقیما در داخل Gitlab قرار دارد. تنها کافیست تا یک فایل با این نام در دایرکتوری اصلی پروژه خود ایجاد کنید و عملیات مورد نیاز را در داخل آن تعریف کنید:
.gitlab-ci.yml
پس از ایجاد و پیکرهبندی این فایل، هر بار که یک کامیت جدید میسازید یا یک merge request باز میکنید یا یک tag جدید میسازید، GitLab میتواند بهصورت خودکار pipeline شما را اجرا کند.
Pipeline در GitLab CI/CD چیست؟
اگر بخواهیم بیشتر در مورد Pipeline بدانیم، در واقع مجموعهای از مرحلهها (Stages) است که در هر مرحله یک سری وظایف (Jobs) باید اجرا شوند. نکته مهم این است که مراحلی که تعریف میکنیم، به ترتیب اجرا میشوند. مثلا یک فایل .gitlab-ci.yml فرضی را در نظر بگیرید. این فایل یک کلید root به نام stages دارد که مراحل را تعیین میکند. این کلید معمولا در ابتدای فایل قرار میگیرد.
stages:
- build
- test
- deploy
همانطور که در مثال بالا مشاهده میشود، این فایل سه مرحله برای پایپلاین تعریف میکند که از بالا به پایین اجرا خواهند شد و خروجی تعریف بالا، این ساختار را در گیتلب به وجود میآورد:

البته هنوز نمیتوان به خروجی تصویر بالا رسید. نیاز هست تا برای هر مرحله وظایف مربوط به آن را تعریف کنیم. پس مرحله بعدی تعیین وظایف(job) برای هر مرحله است. برای اینکار باید برای هر stage، یک کلید root ایجاد کنیم.
stages:
- build
- test
- deploy
build-app:
stage: build
test-job:
stage: test
deploy-ops:
stage: deploy
به بخش های اضافه شده به فایل .gitlab-ci.yml دقت کنید. سه کلید top-level برای تعریف ۳ وظیفه اضافه شده اند. دقت کنید که هر کلید اضافه شده در سطح بالای فایل یا همان root معرف یک job است اگر جزو کلمات کلیدی gitlab-ci نباشد. لیست کلمات کلیدی gitlab-ci به شرح زیر است:
stages:
variables:
workflow:
default:
include:
image:
services:
cache:
before_script:
after_script:
اولین مورد از کلمات کلیدی را شناخیتم که برای تعریف مراحل پایپلاین استفاده میشود. بقیه موارد را فعلا فقط به خاطر بسپارید. بعدا در مورد تمامشان صحبت میکنیم و کارکرد هر کدام را بررسی میکنیم.
به تعریف job برگردیم. اولین نکته ای که در مورد هر job وجود دارد، این است که مربوط به کدام stage میشود. پس داخل هر job باید یک کلید stage قرار دهیم و مرحله اجرای job را تعیین کنیم. نکته ی بعدی در مورد job این است که هر job باید کاری انجام دهد. مثلا دستوری را اجرا کند. پس نیاز به یک کلید به نام script داریم که بگوییم job باید چه کاری/هایی انجام دهد. به نمونه کامل تر شدهی فایل دقت کنید:
stages:
- build
- test
- deploy
build-app:
stage: build
script:
- echo "Building the app"
- echo "Build finished"
test-job:
stage: test
script:
- echo "Testing the app"
deploy-ops:
stage: deploy
script:
- echo "Deploying the app"
کلید script در اصل یک آرایه هست و هیچ محدودیتی در تعداد دستوراتی که داخلش قرار میدهیم وجود ندارد. اما گاهی اوقات ممکن است مجموعه دستوراتی که در یک job نیاز داریم خیلی زیاد شوند و طولانی شدن این کلید، خوانایی فایل را کاهش دهد. در چنین وضعیتی میتوان آن مجموعه دستورات را در یک فایل bash قرار داد و سپس در کلید script فقط دستور اجرای آن فایل را ثبت کرد.
script:
- ./ci/build.sh
حالا سوال اصلی که مطرح میشود این است که دستوراتی که تعیین کردیم، بر روی کدی که داریم، در چه محیطی اجرا میشود؟ جواب کوتاه این است که این عملیات در یک محیط ایزوله مثلا یک Docker Container اجرا میشود. اما اینکه این Container از چه image ای ساخته شده کاملا بستگی به این دارد که gitlab محیط پیشفرض را چگونه تعریف کرده باشد. اما بهتر است خودمان تعیین کنیم که دستورات job در چه محیطی روی کدهایمان اجرا شوند. این کار با اضافه کردن کلید image به job امکانپذیر است. مثلاً اگر بخواهیم که همین پیغام های ساده حتما در محیطی با سیستمعامل ubuntu چاپ شوند می توانیم فایل .gitlab-ci.yml را به صورت زیر تغییر دهیم:
stages:
- build
- test
- deploy
build-app:
stage: build
image: ubuntu:20.04
script:
- echo "Building the app"
- cat /etc/os-release
- echo "Build finished"
test-job:
stage: test
image: ubuntu:22.04
script:
- echo "Testing the app"
- cat /etc/os-release
deploy-ops:
stage: deploy
image: ubuntu:24.04
script:
- echo "Deploying the app"
- cat /etc/os-release
در مثال بالا در سه مرحله با نسخه های مختلف ubuntu پیامی را چاپ کردیم و برای اطمینان بیشتر، در هر محیط نسخه سیستم عامل مورد استفاده را بعد از نمایش پیام، چاپ کردیم. حالا پایپلاین ما بصورت زیر اجرا میشود:

برای مثال اگر لاگ مرحله test را ببینیم، چنین خروجیای دریافت میکنیم:

همانطور که در فایل gitlab-ci هم تعریف کرده بودیم، مرحله test باید در محیطی با سیستم عامل ubuntu نسخه ۲۲.۰۴ اجرا میشد که در تصویر بالا هم قابل مشاهده است.
موفق و پیروز باشید