Asosiy kontentga o‘tish

Maqolalar

Darslik · 2026-08-16 · ~6 daqiqa o‘qiladi · o'rta

push → test → deploy: shu saytning o'zi qanday chiqib turibdi

#devops #ci-cd #github #deploy

Mundarija

Bu maqolaning o'zi — mavzuning jonli isboti. Men uni yozib git push qildim, keyin hech narsa qilmadim: GitHub Actions testlarni o'tkazdi, serverga yukladi, xizmatni yangiladi va Telegram kanalimga e'lonni ham o'zi yuborib qo'ydi. Qo'lda deploy degan tushuncha bu loyihada birinchi haftadan keyin yo'qolgan. Bugun shu zanjirni boshidan oxirigacha, haqiqiy fayllar bilan ko'rsataman — bularning hammasi saytning ochiq repositoriysida turibdi, solishtirib borishingiz mumkin.

Umumiy manzara#

git push (main)
    │
    ▼
[checks] ruff → format → migratsiya tekshiruvi → pytest
    │ hammasi yashil bo'lsa
    ▼
[deploy] rsync bilan serverga → uv sync → collectstatic → migrate
    │      → systemctl restart → yangi maqolalarni kanalga e'lon qilish
    ▼
sayt jonli, kanalda post

Eng muhim tamoyil shu chizmaning o'zida: deploy testlardan keyin turadi. Buzuq kod serverga yetib bora olmaydi, chunki unga yo'l testlar orqali o'tadi.

checks: qo'riqchi job#

Workflow fayli .github/workflows/ci.ymlda yashaydi. Birinchi job to'rt qatlamli tekshiruv:

# .github/workflows/ci.yml (qisqartirilgan, mohiyati saqlangan)
name: CI
on: push

jobs:
  checks:
    runs-on: ubuntu-latest
    services:
      postgres:               # testlar haqiqiy Postgres bilan yuradi
        image: postgres:16
        env:
          POSTGRES_PASSWORD: test
        ports: ["5432:5432"]
    steps:
      - uses: actions/checkout@v7
      - uses: astral-sh/setup-uv@v10.0.1
      - run: uv sync
      - run: uv run ruff check .                # lint xatolari
      - run: uv run ruff format --check .       # formatlash buzilmaganmi
      - run: uv run python manage.py makemigrations --check --dry-run
      - run: uv run pytest -W error             # testlar, warning ham xato

Ikkita qadam alohida izohga arziydi. makemigrations --check — modelni o'zgartirib, migratsiya yaratishni unutgan holatni ushlaydi; bu xato lokalda sezilmaydi-yu, production'da birinchi so'rovda portlaydi. pytest -W error esa har warning'ni xatoga aylantiradi — kutubxonalar "bu funksiya keyingi versiyada o'chadi" deb ogohlantirsa, siz buni deploy'dan oldin eshitasiz, yarim yildan keyin sinib emas.

deploy: faqat main, faqat yashildan keyin#

  deploy:
    needs: checks                    # checks yiqilsa, bu job boshlanmaydi
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - name: SSH kalitni tayyorlash
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.DEPLOY_SSH_KEY }}" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          ssh-keyscan SERVER_IP >> ~/.ssh/known_hosts
      - name: Deploy
        run: DEPLOY_KEY=~/.ssh/deploy_key ./scripts/deploy.sh deploy@SERVER_IP

needs: checks va if: sharti birga ishlaydi: pull request'lar va boshqa branch'lar faqat tekshiruvdan o'tadi, serverga esa faqat main'dagi yashil push boradi.

Deploy kaliti: alohida va faqat shu ish uchun#

Serverga kirish uchun Actions'ga SSH kalit kerak. Bu yerda bitta qat'iy qoida bor: shaxsiy kalitingizni bermang — deploy uchun alohida kalit yasaladi:

# o'z kompyuteringizda:
ssh-keygen -t ed25519 -f deploy_key -C "github-actions deploy" -N ""

# ochiq qismini serverdagi deploy foydalanuvchisiga qo'shamiz:
ssh-copy-id -i deploy_key.pub deploy@SERVER_IP

# maxfiy qismini GitHub'ga: repo → Settings → Secrets → DEPLOY_SSH_KEY
cat deploy_key   # shu matnni secret qilib saqlaysiz, faylni o'chirasiz

Secret — repo'ga emas, Secrets'ga

Kalit, token, parol — bular hech qachon repositoriy ichiga tushmasligi kerak, hatto private repo bo'lsa ham. GitHub Secrets aynan shu uchun: workflow o'qiy oladi, loglarda avtomatik yashiriladi, tarixda qolmaydi. Kalit tasodifan commit bo'lib ketsa, uni "o'chirish" yetmaydi — tarixda qoladi, almashtirish shart.

scripts/deploy.sh: serverda nima bo'ladi#

Deploy skripti — pipeline'ning serverga tegadigan qo'li. Mohiyati o'n qator:

#!/usr/bin/env bash
# scripts/deploy.sh (soddalashtirilgan)
set -euo pipefail
HOST=$1

# kodni serverga ko'chiramiz — .git, .venv, .env va var/ tegilmaydi
rsync -az --delete \
  --exclude .git --exclude .venv --exclude .env --exclude var \
  -e "ssh -i $DEPLOY_KEY" ./ "$HOST":/opt/mysite/

ssh -i "$DEPLOY_KEY" "$HOST" bash -s <<'REMOTE'
cd /opt/mysite
uv sync --frozen                          # bog'liqliklar lock fayl bo'yicha
.venv/bin/python manage.py collectstatic --noinput
.venv/bin/python manage.py migrate --noinput
sudo systemctl restart mysite-web         # yoki reload — 2-qismda farqini ko'rgandik
.venv/bin/python manage.py announce_posts || true   # yangi maqola bo'lsa kanalga
REMOTE

Oxirgi qatordagi || truega e'tibor bering: kanalga e'lon yuborish — qo'shimcha qulaylik, deploy'ning sharti emas. Telegram API yotgan bo'lsa ham sayt yangilanishi to'xtamasligi kerak.

Env drift: .env'ni rsync ko'chirmaydi

Skript .envni ataylab chetlab o'tadi — serverdagi sirlar repo'dan kelmaydi. Buning teskari tomoni ham bor: kodga yangi muhit o'zgaruvchisi qo'shsangiz, serverdagi .envga uni qo'lda yozib qo'yish kerak. Men buni bir marta unutib, "lokalda ishlaydi, jonlida ishlamaydi" degan klassik holatga tushganman — o'shandan beri yangi o'zgaruvchi qo'shish checklist'imda alohida band turadi.

Ishlayotganini qanday bilaman#

Push'dan keyin ikki daqiqa ichida hammasi tugaydi. Kuzatish uchun terminaldan chiqish shart emas:

gh run watch          # joriy run'ni jonli ko'rsatadi
gh run list --limit 5 # oxirgi natijalar

Yiqilgan deploy qo'rqinchli emas — u serverga yetmagan deploy. needs: checks tufayli xato har doim serverdan oldin, GitHub'ning o'zida to'xtaydi. Mening tajribamda eng ko'p yiqiladigan qadam — ruff format --check: lokalda formatlashni unutib push qilasiz, CI eslatib qo'yadi.

Yakun#

CI/CD sirli narsa emas: bitta YAML fayl, bitta bash skript, bitta maxsus SSH kalit. Lekin bergan narsasi katta — har push serverga yetguncha to'rt tekshiruvdan o'tadi, deploy esa odamning kayfiyatiga emas, testlarning rangiga bog'liq bo'lib qoladi. Shu maqolani o'qib turganingizning o'zi pipeline ishlayotganining isboti.

Keyingi qismda muammo qidirish tomoniga o'tamiz: journalctl bilan loglarni o'qish — xizmat yiqilganda qayerdan boshlash va nimalarga qarash.