CI/CD — GitHub Actions bilan avtomatik deploy

~20 daq · Next.js · Deployment va DevOps

Muammodan boshlaylik

Jamoada 4 dasturchi. Har kim o'z kompyuterida test qiladi (yoki qilmaydi). Juma kuni kimdir TypeScript xatosi bor kodni main ga qo'shdi — build yiqildi. Boshqa safar testlar o'tmaydigan o'zgarish production ga chiqdi. Deploy esa — 68-darsdagi 6 ta buyruqni qo'lda, tartibni adashtirmasdan bajarish.


CI/CD nima?

Ma'nosi
CI (Continuous Integration) Har bir push va Pull Request da avtomatik: lint, tur tekshiruvi, test, build
CD (Continuous Deployment) main ga qo'shilgan va tekshiruvlardan o'tgan kod avtomatik production ga
push / PR ──▶ lint ──▶ typecheck ──▶ test ──▶ build ──▶ (main) deploy
                ✗ xato — to'xtaydi, merge va deploy yo'q

Hayotiy o'xshatma

Aeroportdagi parvoz oldi tekshiruvi. Har bir samolyot — uchuvchi qanchalik tajribali bo'lmasin — bir xil ro'yxat bo'yicha tekshiriladi: yoqilg'i, dvigatel, rul. Birorta band bajarilmasa — parvoz yo'q. Tekshiruvni inson emas, tartib boshqaradi.


CI workflow

# .github/workflows/ci.yml
name: CI

on:
  pull_request:
  push:
    branches: [main]

concurrency:
  group: ci-${{ github.ref }}
  cancel-in-progress: true

jobs:
  tekshirish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm

      - run: npm ci

      - name: Lint
        run: npm run lint

      - name: TypeScript
        run: npx tsc --noEmit

      - name: Unit testlar
        run: npx vitest run

      - uses: actions/cache@v4
        with:
          path: .next/cache
          key: nextjs-${{ hashFiles('package-lock.json') }}-${{ hashFiles('**/*.ts', '**/*.tsx') }}
          restore-keys: nextjs-${{ hashFiles('package-lock.json') }}-

      - name: Build
        run: npm run build
        env:
          DATABASE_URL: postgresql://fake:fake@localhost:5432/fake
          AUTH_SECRET: ci-uchun-soxta-maxfiy-kalit-kamida-32-belgi
          NEXT_TELEMETRY_DISABLED: 1
  • concurrency — yangi push kelsa, eski ishga tushirish bekor qilinadi
  • cache: npm va .next/cache — keyingi build lar ancha tez (kesh build dan oldin tiklanadi)
  • Build uchun soxta env qiymatlari — haqiqiy kalitlar CI ga kerak emas (agar build vaqtida bazaga murojaat qilinmasa)

E2E — alohida job

  e2e:
    runs-on: ubuntu-latest
    needs: tekshirish
    services:
      postgres:
        image: postgres:17-alpine
        env:
          POSTGRES_PASSWORD: test
          POSTGRES_DB: dokon_test
        ports: ["5432:5432"]
        options: --health-cmd pg_isready --health-interval 5s --health-retries 10
    env:
      DATABASE_URL: postgresql://postgres:test@localhost:5432/dokon_test
      AUTH_SECRET: ${{ secrets.E2E_AUTH_SECRET }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22, cache: npm }
      - run: npm ci
      - run: npx prisma migrate deploy && npx prisma db seed
      - run: npx playwright install --with-deps chromium
      - run: npx playwright test
      - uses: actions/upload-artifact@v4
        if: ${{ !cancelled() }}
        with: { name: playwright-report, path: playwright-report/ }

Branch protection

GitHub → Settings → Branches → Add rule (main):

  • ✅ Require a pull request before merging
  • ✅ Require status checks to pass — tekshirish, e2e
  • ✅ Require branches to be up to date

Endi CI o'tmagan kod main ga tushmaydi.


CD — Vercel

Vercel GitHub bilan ulangan bo'lsa (66-dars), deploy avtomatik — alohida workflow shart emas. CI faqat sifatni tekshiradi; branch protection tufayli main ga faqat tekshiruvdan o'tgan kod tushadi va production deploy ham faqat shu koddan bo'ladi.


CD — o'z server (VPS)

# .github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    concurrency: production
    steps:
      - name: Serverga deploy
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_KEY }}
          script: |
            set -e
            cd /var/www/dokon
            git pull --ff-only
            npm ci
            npx prisma migrate deploy
            npm run build
            pm2 reload dokon

environment: production — GitHub da Environments → production → "Required reviewers": deploy bitta tugma bilan tasdiqlangandan keyin boshlanadi (ixtiyoriy).

Docker image bilan — yaxshiroq

Build ni CI da qilib, tayyor image ni serverga yuborish — serverning resurslari band bo'lmaydi va har bir versiya aniq belgilangan:

      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - uses: docker/build-push-action@v6
        with:
          push: true
          tags: ghcr.io/${{ github.repository }}:${{ github.sha }}
          build-args: NEXT_PUBLIC_SITE_URL=https://dokon.uz
          cache-from: type=gha
          cache-to: type=gha,mode=max

Serverda: docker compose pull web && docker compose up -d web. Rollback — oldingi sha tag iga qaytish.

[!WARNING] SSH kalit va boshqa maxfiy qiymatlar — faqat Settings → Secrets and variables → Actions da. Ularni workflow fayliga yoki loglarga hech qachon yozmang. Deploy uchun alohida, cheklangan huquqli foydalanuvchi va alohida SSH kalit yarating.


Migratsiyalar xavfsizligi

Deploy paytida bir lahza eski kod va yangi baza (yoki aksincha) birga ishlaydi. Migratsiyalarni orqaga mos yozing:

  1. Avval ustun qo'shiladi (ixtiyoriy) — eski kod uni e'tiborsiz qoldiradi
  2. Yangi kod deploy qilinadi
  3. Keyingi deploy da eski ustun o'chiriladi

Ustunni bitta deploy da o'chirib, nomini o'zgartirish — deploy davomida xatolar.

[!TIP] Dependabot yoki Renovate ni yoqing — ular bog'liqliklar yangilanishi uchun avtomatik Pull Request ochadi, CI esa yangilanish hech narsani buzmaganini tekshiradi. Xavfsizlik yamoqlari (masalan, Next.js zaifliklari — 42-dars) kechikmaydi.


Tez-tez uchraydigan xatolar

1. CI da haqiqiy production kalitlari

Kerak emas va xavfli. Build uchun soxta qiymatlar; E2E uchun test kalitlari.

2. Build vaqtida bazaga murojaat

Statik sahifa generateStaticParams da bazadan o'qisa — CI da baza kerak. Bunday sahifalar uchun CI da test bazasi yoki dinamik render.

3. set -e siz deploy skripti

npm run build xato berdi, lekin skript davom etib pm2 reload qildi — sayt buzilgan holatda.


Xulosa

CI: har PR/push da lint → tsc → vitest → build; e2e — alohida job, test baza bilan
concurrency, npm va .next/cache keshi — tezlik
Branch protection — CI o'tmasa merge yo'q
Vercel — CD avtomatik; VPS — ssh-action yoki Docker image (ghcr.io + sha tag)
Secrets — GitHub Secrets; environment: production — tasdiqlash
set -e; migratsiyalar orqaga mos

Keyingi bo'lim

70-dars: Internationalization — next-intl bilan ko'p tilli ilova

Ilg'or mavzular: o'zbek, rus va ingliz tillarida sayt — URL, SEO va server komponentlar bilan.