Skip to main content

CI/CD Pipeline

Current State

No automated CI/CD pipeline is configured yet. Deployment is done manually via SSH.

This document defines the target pipeline to implement.


Manual Deployment (Current)

# SSH to production server
ssh [email protected]

# Pull and rebuild
cd /opt/platform-v2
git pull origin main
docker-compose -f docker-compose.prod.yml up -d --build

# Run migrations (always before starting new backend)
docker-compose -f docker-compose.prod.yml exec backend alembic upgrade head

# Verify
docker-compose -f docker-compose.prod.yml logs -f backend

Target Pipeline (GitLab CI)

Pipeline Stages

lint → test → build → deploy

On Merge Request

1. Lint
- Python: flake8 / ruff on backend/
- Frontend: ESLint on frontend/

2. Tests
- Python: pytest backend/ (when tests exist)
- Migration check: alembic upgrade head → alembic downgrade -1 → alembic upgrade head

On Merge to Main

3. Build
- docker build backend image
- docker build frontend image (npm run build inside)

4. Deploy to Production
- SSH to 77.42.82.4
- git pull
- docker-compose -f docker-compose.prod.yml up -d --build
- alembic upgrade head (migrations before restart)
- Health check: curl https://mvp-api.zafarsaidov.uz/health

Environment Variables in CI

VariablePurpose
PROD_SSH_KEYPrivate key for SSH to 77.42.82.4
PROD_SERVER_HOST77.42.82.4
PROD_SERVER_USERroot

Store sensitive values as masked CI variables (never in .gitlab-ci.yml).


Docker Images

backend/Dockerfile        # Multi-stage: python:3.11 base → final image
frontend/Dockerfile # Multi-stage: node:20 build → nginx serve
nginx/Dockerfile # nginx with custom config
docker-compose.prod.yml # Production compose (postgres, redis, backend, frontend, nginx)

Frontend VITE_API_URL is set in frontend/.env.production (committed to repo) and baked in at build time — no CI variable needed.


Rules

  1. Migrations run before deploy — never embedded in application startup
  2. Build once, deploy the artifact — don't rebuild images on the server
  3. Rollback = previous image tag — keep :latest and :sha tags
  4. Health check after deploy — verify backend responds before closing pipeline
  5. Never push secrets — use CI masked variables for credentials