TP12.2 - خط أنابيب CI/CD والنشر
أهداف التمرين
في هذا التمرين، سوف تقوم بـ:
- ✅ إنشاء سير عمل GitHub Actions كامل
- ✅ أتمتة الاختبارات والبناء والنشر على Docker
- ✅ النشر على Railway (أو بديل)
- ✅ تكوين النشر التلقائي
المدة المقدرة: 1 ساعة و30 دقيقة
المتطلبات المسبقة: إكمال TP12.1، حساب GitHub، حساب Railway
السياق
أنت تقوم بأتمتة نشر تطبيق Todo من TP12.1. كل دفع على main يؤدي إلى:
- اختبارات تلقائية
- بناء صورة Docker
- النشر على Docker Hub
- النشر على Railway
الجزء 1: التحضير
هيكل الملفات
.github/
└── workflows/
├── ci.yml # اختبارات على كل PR
├── cd.yml # بناء + نشر على main
└── docker-publish.yml # نشر Docker
إنشاء أسرار GitHub
الذهاب إلى: Repository → Settings → Secrets and variables → Actions
# Docker Hub
DOCKERHUB_USERNAME=اسم_المستخدم_الخاص_بك
DOCKERHUB_TOKEN=الرمز_الخاص_بك
# Railway
RAILWAY_TOKEN=الرمز_الخاص_بك
# (اختياري) Heroku
HEROKU_API_KEY=الرمز_الخاص_بك
HEROKU_APP_NAME=التطبيق_الخاص_بك
HEROKU_EMAIL=البريد_الإلكتروني_الخاص_بك
الجزء 2: سير عمل CI (الاختبارات)
.github/workflows/ci.yml
name: CI - Tests
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
name: Run Tests
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15-alpine
env:
POSTGRES_DB: testdb
POSTGRES_USER: test
POSTGRES_PASSWORD: test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
cache: 'maven'
- name: Run Unit Tests
run: mvn test -Dspring.profiles.active=test
- name: Run Integration Tests
run: mvn verify -Dspring.profiles.active=test
env:
SPRING_DATASOURCE_URL: jdbc:postgresql://localhost:5432/testdb
SPRING_DATASOURCE_USERNAME: test
SPRING_DATASOURCE_PASSWORD: test
- name: Upload Test Results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: target/surefire-reports/
- name: Generate Coverage Report
run: mvn jacoco:report
- name: Upload Coverage
uses: codecov/codecov-action@v3
with:
files: target/site/jacoco/jacoco.xml
fail_ci_if_error: false
الجزء 3: سير عمل CD (البناء والنشر)
.github/workflows/cd.yml
name: CD - Build and Deploy
on:
push:
branches: [main]
release:
types: [published]
env:
REGISTRY: docker.io
IMAGE_NAME: ${{ secrets.DOCKERHUB_USERNAME }}/todo-app
jobs:
# ===== JOB 1: Test =====
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
cache: 'maven'
- name: Run Tests
run: mvn test
# ===== JOB 2: Build Docker =====
build:
name: Build and Push Docker
runs-on: ubuntu-latest
needs: test
outputs:
image-tag: ${{ steps.meta.outputs.tags }}
version: ${{ steps.meta.outputs.version }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=sha,prefix=
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
- name: Build and push
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
- name: Print image info
run: |
echo "Image pushed: ${{ env.IMAGE_NAME }}"
echo "Tags: ${{ steps.meta.outputs.tags }}"
# ===== JOB 3: Deploy to Railway =====
deploy:
name: Deploy to Railway
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/main'
environment: production
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Railway CLI
run: npm i -g @railway/cli
- name: Deploy to Railway
run: railway up --detach
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
- name: Print deployment info
run: |
echo "✅ Deployed to Railway!"
echo "Image: ${{ needs.build.outputs.image-tag }}"
الجزء 4: تكوين Railway
إنشاء مشروع Railway
- الذهاب إلى railway.app
- "New Project" → "Empty Project"
- "Add Service" → "GitHub Repo" → اختيار المستودع الخاص بك
- "Add Database" → "PostgreSQL"
الحصول على رمز Railway
- Account Settings → Tokens
- "Create Token"
- نسخ الرمز إلى أسرار GitHub
متغيرات البيئة في Railway
في لوحة التحكم في Railway، تكوين:
SPRING_PROFILES_ACTIVE=prod
DATABASE_URL=${{Postgres.DATABASE_URL}}
# Railway يحقن تلقائيًا DATABASE_URL من PostgreSQL
railway.json (اختياري)
{
"$schema": "https://railway.app/railway.schema.json",
"build": {
"builder": "DOCKERFILE",
"dockerfilePath": "Dockerfile"
},
"deploy": {
"numReplicas": 1,
"healthcheckPath": "/actuator/health",
"healthcheckTimeout": 30,
"restartPolicyType": "ON_FAILURE",
"restartPolicyMaxRetries": 3
}
}
الجزء 5: بديل Heroku
.github/workflows/deploy-heroku.yml
name: Deploy to Heroku
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Deploy to Heroku
uses: akhileshns/heroku-deploy@v3.12.14
with:
heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
heroku_app_name: ${{ secrets.HEROKU_APP_NAME }}
heroku_email: ${{ secrets.HEROKU_EMAIL }}
usedocker: true
الملفات اللازمة لـ Heroku
heroku.yml:
build:
docker:
web: Dockerfile
run:
web: java -Dserver.port=$PORT -jar app.jar
الجزء 6: اختبار خط الأنابيب
1. الدفع الأولي
git add .
git commit -m "Add CI/CD pipeline"
git push origin main
2. التحقق من GitHub Actions
- الذهاب إلى علامة التبويب Actions
- التحقق من أن سير العمل يتم تنفيذه
- يجب أن يمر كل مهمة بنجاح ✅
3. التحقق من Docker Hub
- الذهاب إلى hub.docker.com
- التحقق من أن الصورة تم نشرها
- التحقق من العلامات
4. التحقق من النشر
# Railway
curl https://your-app.railway.app/actuator/health
# أو Heroku
curl https://your-app.herokuapp.com/actuator/health
الجزء 7: سير العمل مع الإشعارات
إشعارات Slack/Discord
notify:
name: Notify
runs-on: ubuntu-latest
needs: [deploy]
if: always()
steps:
- name: Send Slack notification
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
fields: repo,message,commit,author,action,eventName,ref,workflow
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
if: always()
الجزء 8: شارة الحالة
الإضافة إلى README.md
# تطبيق Todo


## الوصف
تطبيق إدارة المهام باستخدام Spring Boot.
## الروابط
- الإنتاج: https://your-app.railway.app
- وثائق API: https://your-app.railway.app/swagger-ui.html
التحقق النهائي
قائمة التحقق
- الدفع يؤدي إلى تشغيل سير العمل CI
- الاختبارات تمر في GitHub Actions
- صورة Docker منشورة على Docker Hub
- التطبيق منشور على Railway
-
/actuator/healthيعيد UP - API يعمل في الإنتاج
الروابط للتحقق
# فحص الصحة
curl https://your-app.railway.app/actuator/health
# API
curl https://your-app.railway.app/api/todos
# إنشاء مهمة في الإنتاج
curl -X POST https://your-app.railway.app/api/todos \
-H "Content-Type: application/json" \
-d '{"title": "اختبار في الإنتاج!"}'
🎯 الوحدة مكتملة!
تهانينا! لقد أكملت الوحدة 12 - النشر والإنتاج.
ملخص:
- الفصل 1: التحضير للإنتاج
- الفصل 2: Docker والتعبئة
- الفصل 3: CI/CD باستخدام GitHub Actions
- الفصل 4: النشر السحابي
- TP12.1: تعبئة كاملة باستخدام Docker
- TP12.2: خط أنابيب CI/CD
المهارات المكتسبة:
- ✅ ملفات تعريف Spring Boot (dev، prod، docker)
- ✅ Dockerfile متعدد المراحل المحسن
- ✅ Docker Compose مع PostgreSQL
- ✅ سير العمل في GitHub Actions
- ✅ النشر التلقائي على Railway
- ✅ المراقبة وفحوصات الصحة