GitHub Actions ليست الخيار الوحيد
كل الدروس السابقة في هذا المسار بُنيت على GitHub Actions لأنها الأكثر انتشاراً لمشاريع GitHub، لكن لو كان مشروعك مستضافاً على GitLab (سواء GitLab.com أو نسخة ذاتية الاستضافة)، فالأداة المدمجة هي GitLab CI/CD — والمفاهيم الأساسية متقاربة جداً، فمعرفتك بـ CI/CD من الدروس السابقة تنتقل مباشرة.
ملف .gitlab-ci.yml
بدل مجلد .github/workflows/ مع عدة ملفات، GitLab يستخدم ملف YAML واحد في جذر المستودع اسمه .gitlab-ci.yml.
build-job:
stage: build
script:
- npm ci
- npm run build
test-job:
stage: test
script:
- npm test
deploy-job:
stage: deploy
script:
- echo "نشر الفرع $CI_COMMIT_BRANCH"
environment: production
only:
- main
Stages وJobs: نفس الفكرة، تسمية مختلفة
المفهوم يقابل تماماً jobs في GitHub Actions لكن بترتيب مختلف قليلاً:
- Stage (مرحلة): مجموعة من الوظائف تُنفَّذ بالتتابع — لا تبدأ مرحلة إلا بعد نجاح كل وظائف المرحلة السابقة
- Job (وظيفة): وحدة العمل الفعلية، تحتوي
script(الأوامر المُنفَّذة). كل الوظائف داخل نفس المرحلة تعمل بالتوازي تلقائياً
في المثال أعلاه: build-job تشتغل أولاً، وبعد نجاحها فقط تشتغل test-job، وبعدها deploy-job. لو أضفنا وظيفة أخرى بنفس stage: test، كانت ستشتغل بالتوازي مع test-job.
متغيرات مدمجة (Predefined Variables)
مثل github.sha وgithub.ref في GitHub Actions، GitLab يوفر متغيرات جاهزة داخل كل pipeline:
| المتغير | المعادل في GitHub Actions | الوصف |
|---|---|---|
$CI_COMMIT_BRANCH | github.ref_name | اسم الفرع الحالي |
$CI_COMMIT_SHA | github.sha | هاش الـ commit |
$CI_PROJECT_NAME | github.repository | اسم المشروع |
$CI_PIPELINE_ID | github.run_id | معرّف التشغيلة |
Runners: من يُنفّذ الوظائف فعلياً
الـ Runner هو العملية (agent) التي تُنفّذ أوامر script فعلياً — يقابل مفهوم runs-on في GitHub Actions لكنه أكثر مرونة في إدارته. GitLab.com يوفر runners جاهزة مشتركة (shared runners)، أو يمكنك تسجيل runner خاص بك (self-hosted) على خادمك، بأنواع تنفيذ (executor) مختلفة مثل shell أو docker.
test-job:
stage: test
tags:
- docker # يحدد أي runner (بهذا الـ tag) يُنفّذ الوظيفة
script:
- npm test
مثال: Pipeline مع Docker ونشر شرطي
stages:
- build
- test
- deploy
build:
stage: build
image: node:20
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 week
test:
stage: test
image: node:20
script:
- npm test
deploy:
stage: deploy
image: node:20
script:
- echo "نشر ناتج البناء"
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
imageيحدد صورة Docker التي تشتغل فيها الوظيفة — لا حاجة لخطوة تسجيل دخول منفصلة كما في GitHub Actionsartifactsهنا مفهوم مدمج في نفس بنية الـ job (وليس action منفصل مثلupload-artifact)، ويُمرَّر تلقائياً للمراحل التاليةrulesتتحكم بشرط تشغيل الوظيفة — أشبه بـifعلى مستوى الخطوة في GitHub Actions
⚠️ لا يوجد
needsإلزامي بين المراحل لأن الترتيب التسلسلي بين الـ stages مضمون تلقائياً؛ استخدمneedsفقط إذا أردت كسر هذا الترتيب الافتراضي وتشغيل وظيفة أبكر (DAG pipelines).
إدارة الأسرار في .gitlab-ci.yml
المعادل المباشر لـ GitHub Actions secrets هو CI/CD Variables — قيم تُضبط من إعدادات المشروع (Settings → CI/CD → Variables)، وتُعلَّم كـ Masked لإخفائها من سجلّات التشغيل، وProtected لحصرها على الفروع/الوسوم المحمية فقط. هذه هي البداية الافتراضية لأي سر بسيط، تماماً كما شرحنا الأسرار على مستوى المستودع في درس أمن خط الأنابيب لـ GitHub Actions.
لأسرار تُدار خارج GitLab نفسه (مثل HashiCorp Vault أو مدير أسرار سحابي)، توفّر الكلمة المفتاحية secrets: على مستوى الوظيفة طريقة لسحب القيمة وقت التشغيل بدل نسخها كـ CI/CD Variable ثابتة:
deploy:
stage: deploy
secrets:
DATABASE_PASSWORD:
vault: production/db/password@secret # يُسحب من HashiCorp Vault وقت التشغيل
script:
- deploy --password "$DATABASE_PASSWORD"
- افتراضياً تصل القيمة كملف مؤقت، والمتغيّر نفسه يحمل مسار ذلك الملف لا القيمة مباشرة — تقليل احتمال تسرّبها في سجلّات أو subprocesses تطبع متغيرات البيئة بالكامل
- لو كان تطبيقك يقرأ القيمة كمتغيّر بيئة عادي فقط (لا كملف)، أضف
file: falseصراحة
في أغسطس 2026 (إصدار GitLab 19.3)، أصبح GitLab Secrets Manager — مدير الأسرار المدمج في GitLab نفسه بدل مزوّد خارجي — متاحاً عاماً كإضافة مدفوعة على GitLab.com (بعد فترة تجريبية public beta)، بنفس بنية secrets: لكن بمزوّد مختلف:
deploy:
secrets:
DATABASE_PASSWORD:
gitlab_secrets_manager:
name: db-password # اسم السر داخل GitLab Secrets Manager
script:
- deploy --password "$DATABASE_PASSWORD"
⚠️
gitlab_secrets_managerإضافة مدفوعة بتوفّر محدود لحساب كتابة هذا الدرس — تحقق من خطتك وتوفّرها في منطقتك قبل الاعتماد عليها. أماvaultوaws_secrets_managerوazure_key_vaultفمتاحة منذ وقت أطول ولا تتطلب إضافة مدفوعة إضافية بحد ذاتها (تحتاج فقط اشتراكك بالخدمة الخارجية نفسها).
متى تفضّل GitLab CI/CD؟
- مشروعك مستضاف أصلاً على GitLab (أو تحتاج نسخة self-hosted كاملة من منصة DevOps)
- تريد Container Registry وIssue Tracking وCI/CD في نفس المنصة المتكاملة بدل ربط أدوات متعددة
- لو مشروعك على GitHub، لا داعي للتبديل — كل ما تعلمته عن GitHub Actions بهذا المسار يبقى الخيار الأنسب
🎯 التالي: أمان GitHub Actions: Pwn Requests و persist-credentials