CI/CD — GitHub Actions bilan avtomatik build

~20 daq · Docker · Production

Muammodan boshlaylik

Hozirgi deploy jarayoni:

  1. Kompyuterda docker build
  2. docker push (agar unutilmasa)
  3. Serverga SSH, docker compose pull && up -d

Muammolar: kimdir testlarni ishga tushirmay push qildi; Mac da arm64 image yasaldi (38-dars); yangi jamoa a'zosi tartibni bilmaydi; kimning kompyuteridagi qaysi o'zgarishlar image ga tushdi — noma'lum.

CI/CD — bularning hammasini avtomatlashtiradi: main ga push → testlar → build → registry → deploy. Har safar bir xil, insondan mustaqil.


GitHub Actions asoslari

.github/workflows/ papkasidagi YAML fayllar. GitHub ularni o'z serverlarida (runner) ishga tushiradi.

name: CI                        # nomi
on:                             # qachon
  push:
    branches: [main]
  pull_request:
jobs:                           # nima
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: echo "Salom"

1-qadam: testlar

# .github/workflows/docker.yml
name: Docker

on:
  push:
    branches: [main]
    tags: ["v*"]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-buildx-action@v3

      - name: Test image ni yasash
        uses: docker/build-push-action@v6
        with:
          context: .
          target: dev
          load: true
          tags: dokon-api:test
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Testlar
        run: docker run --rm dokon-api:test npm test
  • target: dev — dev bog'liqliklari bor bosqich (testlar uchun)
  • load: true — image ni runner ning lokal Docker iga yuklash
  • cache-from/to: type=gha — qatlam keshini GitHub Actions keshida saqlash. Busiz har bir run noldan build — 5 daqiqa; kesh bilan — 30 soniya

Baza kerak bo'lgan integratsion testlar uchun: docker compose -f compose.test.yaml up --abort-on-container-exit --exit-code-from api.


2-qadam: build va GHCR ga push

  build:
    needs: test                       # testlar o'tgandan keyingina
    if: github.event_name == 'push'   # PR larda push yo'q
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write                 # GHCR ga yozish
    outputs:
      tag: ${{ steps.meta.outputs.version }}
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3

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

      - id: meta
        uses: docker/metadata-action@v5
        with:
          images: ghcr.io/${{ github.repository }}
          tags: |
            type=sha,prefix=sha-
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=raw,value=latest,enable={{is_default_branch}}

      - uses: docker/build-push-action@v6
        with:
          context: .
          target: production
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
  • GITHUB_TOKEN — GitHub avtomatik beradi, alohida token yaratish shart emas; packages: write ruxsati yetarli
  • metadata-action — 38-darsdagi teglash strategiyasi avtomatik:
    • main ga push → sha-a3f9c2b, latest
    • v1.4.2 tegi → 1.4.2, 1.4
  • platforms — amd64 + arm64 (QEMU orqali)

Versiya chiqarish:

git tag v1.4.2
git push origin v1.4.2

3-qadam: xavfsizlik skaneri

      - name: Trivy skaner
        uses: aquasecurity/trivy-action@0.28.0
        with:
          image-ref: ghcr.io/${{ github.repository }}:sha-${{ github.sha }}
          severity: CRITICAL,HIGH
          exit-code: "1"
          ignore-unfixed: true

CRITICAL zaiflik bo'lsa — pipeline to'xtaydi, deploy bo'lmaydi (39-dars).

[!INFO] sha-${{ github.sha }} — to'liq SHA; metadata-action esa standart holatda qisqa SHA yasaydi. Skaner uchun steps.meta.outputs.tags dagi birinchi tegni ishlating yoki metadata-action da type=sha,format=long ni qo'shing.


4-qadam: serverga deploy

  deploy:
    needs: build
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: production            # GitHub da qo'lda tasdiqlash qo'shish mumkin
    steps:
      - uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: deploy
          key: ${{ secrets.SERVER_SSH_KEY }}
          script: |
            cd /opt/dokon
            export API_TAG=${{ needs.build.outputs.tag }}
            docker compose pull api
            docker compose up -d api
            docker image prune -f

Serverdagi compose.yaml da:

services:
  api:
    image: ghcr.io/firdavsdev07/dokon-api:${API_TAG:-latest}

Repo Settings → Secrets and variables → Actions da: SERVER_HOST, SERVER_SSH_KEY (faqat deploy uchun alohida kalit, alohida cheklangan deploy foydalanuvchisi bilan).

Server tayyorlash va deploy tafsilotlari — 42-dars.


Butun oqim

git push main
     │
     ▼
 [ test ]  dev image → npm test
     │ ✓
     ▼
 [ build ]  amd64+arm64 → ghcr.io/...:sha-a3f9c2b, latest
     │ ✓        └→ Trivy: CRITICAL yo'q
     ▼
 [ deploy ]  SSH → compose pull → up -d
     │
     ▼
  Production 🎉

PR da — faqat test. main da — hammasi. v* teg — versiyali image.


Nima uchun shunday?

Nima uchun avtomatlashtirish shunchalik muhim — qo'lda ehtiyotkorlik bilan qilsak bo'lmaydimi?

Chunki odamlar izchil emas: charchaydi, shoshiladi, qadamni unutadi, "kichik o'zgarish, test shart emas" deydi. CI/CD — jarayonni kodga aylantiradi: har bir deploy bir xil qadamlardan o'tadi, testdan o'tmagan kod production ga yetmaydi, har bir image qaysi commit dan yasalgani aniq (sha- teg), va jarayonning o'zi Git da — ko'rib chiqiladi va yaxshilanadi. Natija paradoksal: avtomatlashtirilgan deploy tez-tez va kam qo'rquv bilan qilinadi — kichik o'zgarishlar, kam xavf.


Xulosa

Eslab qoling:

  • .github/workflows/*.yml: on → jobs → steps
  • docker/setup-buildx-action, login-action, metadata-action, build-push-action
  • Kesh: cache-from/to: type=gha — build tezligi uchun muhim
  • GHCR: GITHUB_TOKEN + permissions: packages: write
  • Teglar avtomatik: sha-, semver, latest
  • needs: — test → build → deploy zanjiri; PR da faqat test
  • Trivy — CRITICAL da to'xtatish
  • Deploy — SSH + compose pull + up -d; sirlar — GitHub Secrets da

Keyingi dars

42-dars: Serverga deploy — VPS da Compose bilan ishga tushirish