النشر التلقائي مع GitHub Actions: إعداد CI/CD Pipeline
إنشاء CI/CD pipelines مع GitHub Actions: بناء ونشر Docker، النشر على الخادم عبر SSH، أتمتة الاختبارات، إدارة الأسرار وتحسين سير العمل.
جدول المحتويات
النشر التلقائي مع GitHub Actions: إعداد CI/CD Pipeline
GitHub Actions منصة CI/CD قوية تختبر تغييرات الكود تلقائياً وتبنيها وتنشرها على الخادم. في هذا الدليل سنبني pipeline جاهزاً للإنتاج من الصفر.
ما هو GitHub Actions؟
GitHub Actions منصة أتمتة مدمجة في مستودعات GitHub:
- يستجيب لأحداث مثل push وPR والجدولة
- يشغّل سير عمل متوازية ومتسلسلة
- 2,000 دقيقة/شهر مجاناً (غير محدود للمستودعات العامة)
- قابل للتوسع بآلاف الـ actions الجاهزة
تُخزَّن ملفات سير عمل GitHub Actions بتنسيق YAML في مجلد .github/workflows/.
هيكل سير العمل الأساسي
# .github/workflows/deploy.yml
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: إعداد Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: تثبيت التبعيات
run: npm ci
- name: تشغيل الاختبارات
run: npm test
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: النشر
run: echo "خطوات النشر هنا"
هيكل on / jobs / steps
المحفزات (on)
on:
# Push إلى فرع
push:
branches: [main, develop]
paths:
- 'src/**'
- 'package.json'
# Pull request
pull_request:
branches: [main]
types: [opened, synchronize, reopened]
# تشغيل مجدول (cron)
schedule:
- cron: '0 2 * * *' # كل ليلة الساعة 02:00
# تشغيل يدوي
workflow_dispatch:
inputs:
environment:
description: 'بيئة النشر'
required: true
default: 'staging'
type: choice
options: [staging, production]
# عند اكتمال سير عمل آخر
workflow_run:
workflows: ["Build"]
types: [completed]
تكوين المهمة
jobs:
build:
runs-on: ubuntu-latest
env:
NODE_ENV: test
timeout-minutes: 30
strategy:
matrix:
node-version: [18, 20, 22]
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
بناء ونشر Docker
النشر إلى Docker Hub
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: بيانات Docker الوصفية
id: meta
uses: docker/metadata-action@v5
with:
images: username/myapp
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=sha,prefix=sha-
- name: إعداد Docker Buildx
uses: docker/setup-buildx-action@v3
- name: تسجيل الدخول إلى Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: البناء والنشر
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
GitHub Container Registry (GHCR)
- name: تسجيل الدخول إلى GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: البناء والنشر (GHCR)
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ghcr.io/${{ github.repository }}:latest
النشر على الخادم عبر SSH
استخدام appleboy/ssh-action
deploy:
needs: docker
runs-on: ubuntu-latest
environment: production
steps:
- name: النشر عبر SSH
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: ${{ secrets.SERVER_PORT }}
script: |
cd /root/myapp
git pull origin main
docker compose pull
docker compose up -d --remove-orphans
docker image prune -f
echo "اكتمل النشر: $(date)"
النشر مع Docker Compose
- name: نشر Docker Compose
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
# سحب الصورة الجديدة
docker pull ghcr.io/${{ github.repository }}:latest
# نشر بدون توقف
docker compose -f /root/app/docker-compose.yml up -d \
--no-deps \
--build \
--remove-orphans
# تنظيف الصور القديمة
docker image prune -af --filter "until=24h"
# فحص الصحة
sleep 10
curl -f http://localhost:3000/health || exit 1
إدارة الأسرار
يخزّن GitHub Secrets المعلومات الحساسة بأمان:
steps:
- name: تكوين التطبيق
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}
API_KEY: ${{ secrets.API_KEY }}
run: |
echo "تم تحميل التكوين"
# لا تُطبع الأسرار في السجلات، تُخفى تلقائياً
الأسرار المطلوبة:
SERVER_HOST: عنوان IP للخادمSERVER_USER: اسم مستخدم SSHSSH_PRIVATE_KEY: المفتاح الخاص لـ SSHDOCKERHUB_USERNAME: اسم مستخدم Docker HubDOCKERHUB_TOKEN: رمز وصول Docker Hub
استخدام التخزين المؤقت
- name: تخزين تبعيات Node.js مؤقتاً
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: npm ci (مع التخزين المؤقت)
run: npm ci
# تخزين طبقات Docker مؤقتاً
- name: البناء والنشر
uses: docker/build-push-action@v5
with:
cache-from: type=gha
cache-to: type=gha,mode=max
Matrix Builds
jobs:
test:
strategy:
fail-fast: false
matrix:
node: [18, 20]
os: [ubuntu-latest, macos-latest]
include:
- node: 20
os: ubuntu-latest
coverage: true
exclude:
- node: 18
os: macos-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- run: npm ci
- run: npm test
- name: تقرير التغطية
if: matrix.coverage
run: npm run coverage
قواعد حماية البيئة
jobs:
deploy-production:
runs-on: ubuntu-latest
environment:
name: production
url: https://example.com
steps:
- name: نشر الإنتاج
run: echo "النشر إلى الإنتاج"
في GitHub تحت Settings > Environments > production:
- Required reviewers (يتطلب موافقة)
- Wait timer (وقت الانتظار)
- Deployment branches (main فقط)
مثال كامل لـ CI/CD Pipeline
name: Full CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm test -- --coverage
- name: رفع التغطية
uses: codecov/codecov-action@v4
build:
needs: test
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- uses: docker/build-push-action@v5
with:
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
environment:
name: production
url: https://example.com
steps:
- uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main
docker compose -f /root/app/docker-compose.yml up -d
docker image prune -f
الخلاصة
بإعداد CI/CD pipeline مؤتمت بالكامل مع GitHub Actions، يمكنك تحسين جودة الكود وتقليل أخطاء النشر وتسريع عملية التطوير. مع إدارة الأسرار وتحسين التخزين المؤقت وقواعد حماية البيئة، ستحصل على pipeline بمستوى الإنتاج.
مقالات ذات صلة
دليل Docker Compose: إدارة تطبيقات متعددة الحاويات
تعريف وإدارة التطبيقات متعددة الحاويات باستخدام Docker Compose: تبعيات الخدمات، متغيرات البيئة، فحوصات الصحة، التوسع والنشر في بيئة الإنتاج. دليل شامل.
أتمتة الخوادم مع Ansible: البنية التحتية كرمز
تثبيت Ansible، ملف الجرد، كتابة playbook، هيكل الأدوار، المتغيرات، vault المشفر، أوامر ad-hoc وأتمتة تكوين الخادم. دليل خطوة بخطوة.
إعداد خادم ويب Caddy: HTTPS تلقائي وبروكسي عكسي
تثبيت خادم ويب Caddy، تكوين Caddyfile، SSL تلقائي من Let's Encrypt، بروكسي عكسي، استضافة المواقع الثابتة، تكامل PHP-FPM وإعدادات الأداء.