Next.js: CI/CD مع GitHub Actions
آخر تحديث: 2026-08-26
CI/CD يشبه "الطيار الآلي" لفرق التطوير — كل commit يمر تلقائيا عبر بوابة الجودة، ولا يصل إلى بيئة الإنتاج إلا الكود الذي يجتاز الاختبارات.
1. ما ستتعلمه
- تصميم سير عمل GitHub Actions كامل: فحص الكود ← الاختبار ← البناء ← النشر
- تشغيل الاختبارات بالتوازي على Node.js 18 و 20 و 22 باستخدام استراتيجية المصفوفة المتوازية
- النشر التلقائي إلى Vercel عبر
vercel-action - كتابة Dockerfile متعدد المراحل لبناء صورة مستقلة بحجم 358MB
- إدارة متغيرات البيئة في GitHub Secrets ونشر معاينات PR
2. قصة حقيقية لمدير تقني
(1) نقطة الألم: النشر اليدوي — ما زلت تحدق في الطرفية في الثالثة صباحا
بوب هو المدير التقني لفريق TaskFlow، المكون من خمسة أعضاء يديرون منصة SaaS تخدم أكثر من 10,000 مستخدم. عملية الإصدار كل يوم جمعة تسير هكذا:
"أليس تدمج PR ← تبلغ بوب ← بوب يشغل الاختبارات محليا ← ينقر يدويا على
vercel deploy --prodبعد نجاح الاختبارات ← يحدق في الطرفية لمدة 10 دقائق ← يؤكد نجاح النشر ← يرسل رسالة للفريق"
الأسبوع الماضي، نشر بوب نسخة قديمة بالخطأ لأنه نسي سحب آخر كود قبل npm run build. بعد خمس دقائق، لم يتمكن المستخدمون من تسجيل الدخول، واستغرق الأمر 15 دقيقة أخرى للتراجع عن التغييرات. تلقى قسم خدمة العملاء أكثر من 100 شكوى.
| نقاط الألم | التأثير |
|---|---|
| النشر اليدوي | معدل خطأ بشري مرتفع (30% من الإصدارات بها مشاكل) |
| لا يوجد اختبار آلي للتحكم في الوصول | الكود المعيب قد يصل إلى الإنتاج |
| عدم تطابق البيئة | يعمل محليا، لكنه يرمي خطأ في الإنتاج |
| لا توجد معاينة PR | لا يمكنك رؤية النتائج قبل الدمج |
(2) حل GitHub Actions
صمم بوب ثلاثة خطوط تجميع آلية:
# كل مرة PR ← فحص تلقائي + اختبار + بناء
# الدمج في main ← بناء تلقائي + نشر إلى Vercel
# كل يوم عند الفجر ← بناء تلقائي لصورة Docker
(3) النتائج
| البعد | النشر اليدوي | أتمتة CI/CD |
|---|---|---|
| وقت النشر | 30 دقيقة | 8 دقائق |
| الخطأ البشري | 30% | < 1% |
| كفاءة مراجعة PR | الكود فقط | الكود + رابط المعاينة |
| تكرار النشر | مرة أسبوعيا | 5 مرات يوميا |
3. أساسيات GitHub Actions
Actions هي منصة CI/CD المدمجة في GitHub تستخدم ملفات YAML لتعريف سير العمل.
graph LR
A[git push] --> B[GitHub Actions]
B --> C[المشغلات Events]
C --> D[المهام Jobs متوازية/متسلسلة]
D --> E[الخطوات Steps]
E --> F[مكونات سوق Actions]
style B fill:#cce5ff
style D fill:#d4edda
| المفهوم | الوصف | مثال |
|---|---|---|
| Workflow | ملف YAML واحد = عملية أتمتة واحدة | .github/workflows/test.yml |
| Event | الحدث الذي يشغل سير العمل | push، pull_request، schedule |
| Job | مجموعة من الخطوات (قد تكون متوازية أو تابعة) | lint ← test ← deploy |
| Step | أمر واحد أو Action | npm run lint، actions/checkout |
| Runner | بيئة التنفيذ | ubuntu-latest، windows-latest |
(1) هيكل ملف Workflow
# .github/workflows/ci.yml
name: CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
NODE_VERSION: '20'
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- run: npm ci
- run: npm run lint
test:
needs: [lint]
runs-on: ubuntu-latest
strategy:
matrix:
node-version: ['18', '20', '22']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test
- run: npm run test:coverage
- uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
build:
needs: [test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- run: npm ci
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: build-output
path: .next/
4. test.yml: اختبار المصفوفة المتوازية
graph TB
A[Git Push / PR] --> B[lint]
B --> C[test 18.x]
B --> D[test 20.x]
B --> E[test 22.x]
C --> F[build]
D --> F
E --> F
F --> G[رفع مخرجات البناء]
style A fill:#cce5ff
style C fill:#d4edda
style D fill:#d4edda
style E fill:#d4edda
(1) ملف test.yml الكامل
# .github/workflows/test.yml
name: Test Suite
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
lint:
name: Lint Check
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: TypeScript type check
run: npx tsc --noEmit
- name: ESLint check
run: npm run lint
- name: Prettier check
run: npx prettier --check "src/**/*.{ts,tsx}"
unit-and-integration:
name: Unit & Integration Tests
needs: [lint]
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
matrix:
node-version: ['18', '20', '22']
fail-fast: false
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: testdb
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Generate Prisma client
run: npx prisma generate
- name: Run database migrations
run: npx prisma migrate deploy
env:
DATABASE_URL: postgresql://test:test@localhost:5432/testdb
- name: Run unit tests
run: npm run test
env:
DATABASE_URL: postgresql://test:test@localhost:5432/testdb
- name: Run integration tests
run: npm run test:integration
env:
DATABASE_URL: postgresql://test:test@localhost:5432/testdb
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: unittests
name: codecov-node-${{ matrix.node-version }}
e2e:
name: E2E Tests
needs: [lint]
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Install Playwright browsers
run: npx playwright install --with-deps chromium
- name: Run E2E tests
run: npx playwright test --project=chromium
env:
TEST_DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }}
- uses: actions/upload-artifact@v4
if: failure()
with:
name: playwright-report
path: playwright-report/
retention-days: 7
build:
name: Build Check
needs: [unit-and-integration]
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: next-build
path: .next/
retention-days: 1
▶ مثال: نتائج اختبار المصفوفة المتوازية
# مخرجات وحدة تحكم GitHub Actions
Job: unit-and-integration (node-version: 18.x) ✓ 3m 12s
Job: unit-and-integration (node-version: 20.x) ✓ 2m 58s
Job: unit-and-integration (node-version: 22.x) ✓ 3m 05s
Summary:
✓ lint (1 job) 0m 45s
✓ unit-and-integration (3 jobs) 3m 12s
✓ e2e (1 job) 4m 30s
✓ build (1 job) 1m 20s
5. deploy.yml: النشر التلقائي إلى Vercel
| بيئة النشر | شروط التشغيل | الهدف |
|---|---|---|
| Preview | إنشاء/تحديث PR | النشر إلى فرع المعاينة |
| Production | الدمج في main | تحديث بيئة الإنتاج |
| Staging | وسم release | التحقق قبل الإصدار |
(1) إعدادات نشر Vercel
# .github/workflows/deploy.yml
name: Deploy to Vercel
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
jobs:
deploy-preview:
name: Deploy Preview
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- name: Install Vercel CLI
run: npm install --global vercel@latest
- name: Pull Vercel Environment
run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}
- name: Build Project Artifacts
run: vercel build --token=${{ secrets.VERCEL_TOKEN }}
- name: Deploy to Vercel Preview
run: |
vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} > deployment-url.txt
echo "PREVIEW_URL=$(cat deployment-url.txt)" >> $GITHUB_ENV
- name: Comment Preview URL on PR
uses: thollander/actions-comment-pull-request@v2
with:
message: |
🚀 **Preview Deployment Ready**
| Environment | URL |
|:-----------|:----|
| Preview | ${{ env.PREVIEW_URL }} |
| Branch | ${{ github.head_ref }} |
_This comment is automatically updated on each push._
deploy-production:
name: Deploy Production
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: [deploy-preview]
runs-on: ubuntu-latest
timeout-minutes: 15
environment: production
steps:
- uses: actions/checkout@v4
- name: Install Vercel CLI
run: npm install --global vercel@latest
- name: Pull Vercel Environment
run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
- name: Build Project Artifacts
run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
- name: Deploy to Vercel Production
run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}
- name: Notify deployment success
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "✅ Production deployment completed: ${{ github.repository }}@${{ github.sha }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
6. بناء صورة Docker (متعدد المراحل، 358 MB)
للنشر الذاتي (self-hosting)، تحتاج إلى بناء صور Docker تلقائيا في CI.
(1) Dockerfile متعدد المراحل
# Dockerfile — Next.js 16 standalone بناء صورة
# المرحلة 1: تثبيت التبعيات (باستخدام طبقة التخزين المؤقت)
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production && \
npm cache clean --force
# المرحلة 2: البناء (توليد مخرجات .next)
FROM node:20-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build
# المرحلة 3: التشغيل (صورة مصغرة ~358MB)
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs
COPY --from=build /app/public ./public
COPY --from=build --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=build --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]
(2) Docker Build Action
# .github/workflows/docker.yml
name: Docker Build & Push
on:
push:
tags: ['v*']
schedule:
- cron: '0 2 * * 0' # الأحد المبكر الساعة 2 صباحا
jobs:
docker:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,format=short
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
▶ مثال: مخرجات بناء صورة Docker
# سجل البناء
#1 [deps 1/1] RUN npm ci --only=production
#1 DONE 15.2s
#2 [build 1/4] COPY --from=deps /app/node_modules ./node_modules
#2 DONE 0.1s
#3 [build 2/4] COPY . .
#3 DONE 0.3s
#4 [build 3/4] RUN npm run build
#4 DONE 28.5s
#5 [runner 1/6] COPY --from=build /app/public ./public
#5 DONE 0.1s
#6 Exporting layers
#6 DONE 3.2s
# تحليل حجم الصورة
ghcr.io/myorg/taskflow:latest 358 MB
7. متغيرات البيئة وإدارة الأسرار
graph TB
A[GitHub Secrets] --> B[بيئة تشغيل Actions]
B --> C[Vercel Token]
B --> D[رابط قاعدة البيانات]
B --> E[مفاتيح API]
B --> F[Slack Webhook]
C --> G[النشر إلى Vercel]
D --> H[تشغيل الاختبار]
E --> I[الحقن أثناء البناء]
F --> J[إشعار النشر]
style A fill:#cce5ff
style B fill:#d4edda
| اسم متغير البيئة | الغرض | المصدر |
|---|---|---|
VERCEL_TOKEN |
مصادقة Vercel API | GitHub Secrets |
VERCEL_ORG_ID |
معرف فريق Vercel | لوحة تحكم Vercel |
VERCEL_PROJECT_ID |
معرف مشروع Vercel | لوحة تحكم Vercel |
DATABASE_URL |
اتصال قاعدة البيانات | GitHub Secrets |
CODECOV_TOKEN |
رفع تغطية الاختبار | موقع Codecov |
SLACK_WEBHOOK_URL |
إشعار النشر | إعدادات تطبيق Slack |
(1) إعداد GitHub Secrets
# في مستودع GitHub ← Settings → Secrets and variables → Actions ← Add
gh secret set VERCEL_TOKEN --body "your-vercel-token"
gh secret set DATABASE_URL --body "postgresql://user:pass@host:5432/db"
gh secret set SLACK_WEBHOOK_URL --body "https://hooks.slack.com/services/..."
(2) استراتيجية عزل البيئات
# تجاوز المتغيرات في البيئات المختلفة
jobs:
test:
env:
DATABASE_URL: postgresql://test:test@localhost:5432/testdb
NODE_ENV: test
deploy-preview:
environment: preview
env:
DATABASE_URL: ${{ secrets.PREVIEW_DATABASE_URL }}
NEXT_PUBLIC_API_URL: ${{ vars.PREVIEW_API_URL }}
deploy-production:
environment: production
env:
DATABASE_URL: ${{ secrets.PROD_DATABASE_URL }}
NEXT_PUBLIC_API_URL: https://api.taskflow.io
8. سير عمل نشر معاينة PR
تتيح معاينة PR للمطورين معاينة تأثير تغييراتهم قبل الدمج.
graph TB
A[المطور ينشئ PR] --> B[Actions تشغل deploy-preview]
B --> C[Vercel تنشئ نشر معاينة]
C --> D[توليد رابط المعاينة]
D --> E[البوت يعلق على PR برابط]
E --> F[المراجع يتحقق من المعاينة]
F -->|موافقة| G[الدمج في main]
G --> H[Actions تشغل deploy-production]
style A fill:#cce5ff
style F fill:#fff3cd
style H fill:#d4edda
▶ مثال: سير عمل معاينة PR كامل + التنظيف
المخرجات:
احفظ إعدادات YAML أعلاه في مسار الملف المحدد. ستصبح الإعدادات سارية عند إعادة تشغيل الخادم التالية.
# .github/workflows/preview.yml
name: PR Preview
on:
pull_request:
types: [opened, synchronize, closed]
jobs:
preview:
if: github.event.action != 'closed'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to Vercel Preview
id: deploy
run: |
npx vercel --token=${{ secrets.VERCEL_TOKEN }} \
--scope=${{ secrets.VERCEL_ORG_ID }} \
--confirm > preview-url.txt
echo "url=$(cat preview-url.txt)" >> $GITHUB_OUTPUT
- name: Comment URL
uses: actions/github-script@v7
with:
script: |
const url = '${{ steps.deploy.outputs.url }}'
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `🚀 **Preview deployed**\n\n${url}\n\n_Commit: ${context.sha}_`
})
cleanup:
if: github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- name: Remove Vercel Preview
run: |
npx vercel remove \
taskflow-git-${GITHUB_HEAD_REF//\//-} \
--token=${{ secrets.VERCEL_TOKEN }} \
--yes --scope=${{ secrets.VERCEL_ORG_ID }} || true
المخرجات:
Sections: name, on, jobs.
9. مثال كامل: خط تجميع CI/CD الكامل لـ TaskFlow
# .github/workflows/full-pipeline.yml
# ============================================
# خط تجميع CI/CD الكامل لـ TaskFlow
# ============================================
name: TaskFlow Full Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
release:
types: [published]
env:
NODE_VERSION: '20'
PNPM_VERSION: '9'
jobs:
# === المرحلة 1: بوابة الجودة ===
quality-gate:
name: Quality Gate
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- name: TypeScript check
run: pnpm typecheck
- name: ESLint + Prettier
run: pnpm lint && pnpm format:check
- name: Unit tests with coverage
run: pnpm test:coverage
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false
# === المرحلة 2: اختبار التكامل ===
integration:
name: Integration Tests
needs: [quality-gate]
runs-on: ubuntu-latest
timeout-minutes: 20
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_USER: taskflow
POSTGRES_PASSWORD: taskflow
POSTGRES_DB: taskflow_test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: npx prisma generate
- run: npx prisma migrate deploy
env:
DATABASE_URL: postgresql://taskflow:taskflow@localhost:5432/taskflow_test
- name: Integration tests
run: pnpm test:integration
env:
DATABASE_URL: postgresql://taskflow:taskflow@localhost:5432/taskflow_test
- name: E2E tests
run: npx playwright install --with-deps chromium && pnpm test:e2e
env:
DATABASE_URL: postgresql://taskflow:taskflow@localhost:5432/taskflow_test
# === المرحلة 3: البناء ===
build:
name: Build Application
needs: [integration]
runs-on: ubuntu-latest
timeout-minutes: 15
outputs:
image-tag: ${{ steps.meta.outputs.tags }}
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: pnpm build
- name: Build Docker image
if: github.event_name == 'push'
uses: docker/build-push-action@v5
with:
context: .
load: true
tags: taskflow:ci-${{ github.sha }}
- name: Save build outputs
uses: actions/upload-artifact@v4
with:
name: build-artifacts
path: |
.next/
public/
package.json
# === المرحلة 4: النشر ===
deploy:
name: Deploy
needs: [build]
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- name: Deploy to Vercel
run: |
npx vercel deploy --prod \
--token=${{ secrets.VERCEL_TOKEN }} \
--scope=${{ secrets.VERCEL_ORG_ID }}
- name: Notify Slack
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "✅ TaskFlow deployed to production\nCommit: ${{ github.sha }}\nBy: ${{ github.actor }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
- name: Run Lighthouse CI
run: npx lhci autorun
env:
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_TOKEN }}
❓ أسئلة شائعة
vercel-action أم Vercel CLI؟vercel-action (amondnet/vercel-action) يغلف عمليات CLI الشائعة، لكن التحديثات قد تتأخر. نوصي باستخدام Vercel CLI (npm install -g vercel) مباشرة؛ استخدام run: vercel deploy --prod --token=... في Actions يوفر مرونة أكبر ويضمن حصولك على أحدث إصدار.actions/secrets-scanning لاكتشاف commits العرضية.actions/cache لتخزين node_modules و .next/cache مؤقتا؛ (2) شغل المهام المستقلة بالتوازي؛ (3) استخدم fail-fast: false لمنع فشل إصدار واحد من إلغاء خط التجميع بأكمله؛ (4) استخدم pnpm بدلا من npm (لتثبيت أسرع)؛ (5) استضف runner ذاتيا (إذا كان المستودع كبيرا).📖 ملخص
- تتكون سير عمل GitHub Actions من هيكل ثلاثي المستويات: Event ← Jobs ← Steps. توجد ملفات YAML تحت
.github/workflows/. strategy.matrixتنفذ اختبارا متوازيا لـ Node 18/20/22 للتحقق من التوافق عبر إصدارات LTS المتعددة في وقت واحد- يمكن دمج أمر
vercel deploy --prodفي Actions لتمكين النشر التلقائي؛ ويمكن الوصول إلى معاينة PR عبر تعليق الرابط باستخدامactions/github-script - بناء Docker متعدد المراحل (deps ← build ← runner) يحافظ على حجم الصورة عند ~358MB؛ و
output: 'standalone'شرط أساسي. - GitHub Secrets تخزن المتغيرات الحساسة بأمان، وحقل
environmentيتيح عزل البيئات للتطوير والمعاينة والإنتاج - ثلاث استراتيجيات رئيسية لتحسين CI: التخزين المؤقت للتبعيات، توازي المهام، واستخدام pnpm بدلا من npm
📝 تمارين
-
مسألة أساسية (⭐): أنشئ
.github/workflows/ci.ymlيحتوي على ثلاث مهام متسلسلة — Lint و Test و Build — وشغلها عند كلpushإلىmain. -
تمرين متقدم (⭐⭐): أعد خط تجميع نشر Vercel التلقائي الكامل لمشروعك: (1) اضبط
VERCEL_TOKENفي GitHub Secrets؛ (2) اكتبdeploy.ymlلتنفيذ معاينة PR ونشر الإنتاج؛ (3) تحقق من ظهور رابط المعاينة في تعليقات PR. -
تحد (⭐⭐⭐): نفذ خط تجميع CI/CD متعدد البيئات (dev ← staging ← production): (1) لكل بيئة قاعدة بياناتها وأسرارها الخاصة؛ (2) فرع dev ينشر تلقائيا إلى بيئة dev؛ (3) فرع main ينشر تلقائيا إلى staging؛ (4) النشر إلى production يتطلب موافقة يدوية؛ (5) أبلغ قناة Slack عبر webhook بعد نجاح النشر.