263 lines
7.4 KiB
YAML
263 lines
7.4 KiB
YAML
name: CI/CD Pipeline
|
|
|
|
on:
|
|
push:
|
|
branches: [ main, develop ]
|
|
tags: [ 'v*' ]
|
|
pull_request:
|
|
branches: [ main, develop ]
|
|
|
|
env:
|
|
POSTGRES_DB: platform_test
|
|
POSTGRES_USER: platform_user
|
|
POSTGRES_PASSWORD: test_password
|
|
DATABASE_URL: "postgresql://platform_user:test_password@localhost:5432/platform_test"
|
|
REDIS_URL: "redis://localhost:6379/0"
|
|
|
|
jobs:
|
|
# Backend тесты
|
|
test-backend:
|
|
runs-on: ubuntu-latest
|
|
|
|
services:
|
|
postgres:
|
|
image: postgres:16-alpine
|
|
env:
|
|
POSTGRES_DB: ${{ env.POSTGRES_DB }}
|
|
POSTGRES_USER: ${{ env.POSTGRES_USER }}
|
|
POSTGRES_PASSWORD: ${{ env.POSTGRES_PASSWORD }}
|
|
ports:
|
|
- 5432:5432
|
|
options: >-
|
|
--health-cmd pg_isready
|
|
--health-interval 10s
|
|
--health-timeout 5s
|
|
--health-retries 5
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
ports:
|
|
- 6379:6379
|
|
options: >-
|
|
--health-cmd "redis-cli ping"
|
|
--health-interval 10s
|
|
--health-timeout 5s
|
|
--health-retries 5
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Python 3.11
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: '3.11'
|
|
cache: 'pip'
|
|
|
|
- name: Install dependencies
|
|
working-directory: ./backend
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
pip install -r requirements.txt
|
|
|
|
- name: Run Django checks
|
|
working-directory: ./backend
|
|
env:
|
|
DJANGO_SETTINGS_MODULE: config.settings
|
|
SECRET_KEY: test-secret-key-for-ci
|
|
DEBUG: False
|
|
ALLOWED_HOSTS: "*"
|
|
run: python manage.py check
|
|
|
|
- name: Run tests with coverage
|
|
working-directory: ./backend
|
|
env:
|
|
DJANGO_SETTINGS_MODULE: config.settings
|
|
SECRET_KEY: test-secret-key-for-ci
|
|
DEBUG: False
|
|
ALLOWED_HOSTS: "*"
|
|
run: |
|
|
pytest --cov=apps --cov-report=xml --cov-report=html --cov-report=term-missing
|
|
|
|
- name: Upload coverage reports
|
|
uses: codecov/codecov-action@v3
|
|
with:
|
|
file: ./backend/coverage.xml
|
|
flags: backend
|
|
name: backend-coverage
|
|
|
|
# Backend linting
|
|
lint-backend:
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Python 3.11
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: '3.11'
|
|
|
|
- name: Install linting tools
|
|
run: pip install flake8 black isort
|
|
|
|
- name: Run flake8
|
|
working-directory: ./backend
|
|
run: flake8 apps config --max-line-length=120 --exclude=migrations,__pycache__
|
|
|
|
- name: Run black
|
|
working-directory: ./backend
|
|
run: black --check apps config --exclude migrations
|
|
|
|
- name: Run isort
|
|
working-directory: ./backend
|
|
run: isort --check-only apps config --skip migrations
|
|
|
|
# Frontend тесты
|
|
test-frontend:
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Node.js 18
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '18'
|
|
cache: 'npm'
|
|
cache-dependency-path: frontend/package-lock.json
|
|
|
|
- name: Install dependencies
|
|
working-directory: ./frontend
|
|
run: npm ci
|
|
|
|
- name: Run linting
|
|
working-directory: ./frontend
|
|
run: npm run lint
|
|
|
|
- name: Run type checking
|
|
working-directory: ./frontend
|
|
run: npm run type-check || true
|
|
|
|
- name: Build
|
|
working-directory: ./frontend
|
|
run: npm run build
|
|
|
|
# Security проверки
|
|
security-backend:
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Python 3.11
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: '3.11'
|
|
|
|
- name: Install security tools
|
|
run: pip install safety bandit
|
|
|
|
- name: Run safety check
|
|
working-directory: ./backend
|
|
run: safety check --json || true
|
|
|
|
- name: Run bandit
|
|
working-directory: ./backend
|
|
run: bandit -r apps config -ll || true
|
|
|
|
# Сборка Docker образов
|
|
build:
|
|
needs: [test-backend, test-frontend, lint-backend]
|
|
runs-on: ubuntu-latest
|
|
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/tags/v'))
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@v3
|
|
with:
|
|
username: ${{ secrets.DOCKER_USERNAME }}
|
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
|
|
|
- name: Extract metadata
|
|
id: meta
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: |
|
|
${{ secrets.DOCKER_USERNAME }}/platform-backend
|
|
${{ secrets.DOCKER_USERNAME }}/platform-frontend
|
|
|
|
- name: Build and push Backend image
|
|
uses: docker/build-push-action@v5
|
|
with:
|
|
context: ./backend
|
|
push: true
|
|
tags: ${{ secrets.DOCKER_USERNAME }}/platform-backend:${{ github.ref_name }}
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
|
|
- name: Build and push Frontend image
|
|
uses: docker/build-push-action@v5
|
|
with:
|
|
context: ./frontend
|
|
push: true
|
|
tags: ${{ secrets.DOCKER_USERNAME }}/platform-frontend:${{ github.ref_name }}
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
|
|
# Deploy на Staging
|
|
deploy-staging:
|
|
needs: [build]
|
|
runs-on: ubuntu-latest
|
|
if: github.ref == 'refs/heads/develop'
|
|
environment:
|
|
name: staging
|
|
url: https://staging.platform.example.com
|
|
|
|
steps:
|
|
- name: Deploy to Staging
|
|
uses: appleboy/ssh-action@v1.0.0
|
|
with:
|
|
host: ${{ secrets.STAGING_HOST }}
|
|
username: ${{ secrets.STAGING_USER }}
|
|
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
|
script: |
|
|
cd /opt/platform
|
|
docker compose pull
|
|
docker compose up -d
|
|
|
|
# Deploy на Production
|
|
deploy-production:
|
|
needs: [build]
|
|
runs-on: ubuntu-latest
|
|
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
|
|
environment:
|
|
name: production
|
|
url: https://platform.example.com
|
|
|
|
steps:
|
|
- name: Deploy to Production
|
|
uses: appleboy/ssh-action@v1.0.0
|
|
with:
|
|
host: ${{ secrets.PRODUCTION_HOST }}
|
|
username: ${{ secrets.PRODUCTION_USER }}
|
|
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
|
script: |
|
|
cd /opt/platform
|
|
docker compose pull
|
|
docker compose up -d
|
|
|
|
- name: Notify deployment
|
|
if: always()
|
|
run: echo "Deployment completed with status ${{ job.status }}"
|
|
|