CI/CD Pipeline Guide

This guide explains the Continuous Integration and Continuous Deployment (CI/CD) setup for the NSGG Backend project.

Overview

Our CI/CD pipeline uses GitHub Actions to automate: - Code quality checks - Testing - Building Docker images - Deployment to staging/production

Pipeline Structure

.github/
└── workflows/
    ├── ci.yml        # Main CI pipeline
    ├── deploy.yml    # Deployment pipeline
    └── release.yml   # Release automation

CI Pipeline

1. Main CI Workflow

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

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main, develop ]

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:14-alpine
        env:
          POSTGRES_USER: nsgg_test
          POSTGRES_PASSWORD: nsgg_test
          POSTGRES_DB: nsgg_test
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
    - uses: actions/checkout@v3

    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: '3.11'

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements/testing.txt

    - name: Run tests
      env:
        DATABASE_URL: postgresql://nsgg_test:nsgg_test@localhost:5432/nsgg_test
        DJANGO_SETTINGS_MODULE: config.settings.test
      run: |
        python manage.py test

    - name: Upload coverage
      uses: codecov/codecov-action@v3
      with:
        file: ./coverage.xml
        fail_ci_if_error: true

  lint:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: '3.11'

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install black flake8 isort mypy

    - name: Run linters
      run: |
        black --check .
        flake8 .
        isort --check-only .
        mypy .

  security:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Security scan
      uses: snyk/actions/python@master
      env:
        SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
      with:
        args: --severity-threshold=high

2. Deployment Workflow

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

on:
  push:
    branches: [ main ]
    tags: [ 'v*' ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v2

    - name: Login to Docker Hub
      uses: docker/login-action@v2
      with:
        username: ${{ secrets.DOCKERHUB_USERNAME }}
        password: ${{ secrets.DOCKERHUB_TOKEN }}

    - name: Build and push
      uses: docker/build-push-action@v4
      with:
        push: true
        tags: nonstopgg/backend:latest
        cache-from: type=registry,ref=nonstopgg/backend:buildcache
        cache-to: type=registry,ref=nonstopgg/backend:buildcache,mode=max

  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
    - name: Deploy to production
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.PROD_HOST }}
        username: ${{ secrets.PROD_USERNAME }}
        key: ${{ secrets.PROD_SSH_KEY }}
        script: |
          cd /opt/nsgg-backend
          docker-compose -f docker-compose.prod.yml pull
          docker-compose -f docker-compose.prod.yml up -d
          docker-compose -f docker-compose.prod.yml exec -T web python manage.py migrate
          docker-compose -f docker-compose.prod.yml exec -T web python manage.py collectstatic --noinput

3. Release Workflow

# .github/workflows/release.yml
name: Release

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
      with:
        fetch-depth: 0

    - name: Generate changelog
      id: changelog
      uses: metcalfc/changelog-generator@v4.0.1
      with:
        myToken: ${{ secrets.GITHUB_TOKEN }}

    - name: Create Release
      uses: actions/create-release@v1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        tag_name: ${{ github.ref }}
        release_name: Release ${{ github.ref }}
        body: ${{ steps.changelog.outputs.changelog }}
        draft: false
        prerelease: false

Environment Setup

1. Required Secrets

Set these secrets in GitHub repository settings:

# Docker Hub
DOCKERHUB_USERNAME
DOCKERHUB_TOKEN

# Production Server
PROD_HOST
PROD_USERNAME
PROD_SSH_KEY

# Code Quality
SNYK_TOKEN
CODECOV_TOKEN

2. Environment Variables

# .env.ci
DEBUG=0
SECRET_KEY=test-key
DJANGO_ALLOWED_HOSTS=localhost
DATABASE_URL=postgresql://nsgg_test:nsgg_test@localhost:5432/nsgg_test

Deployment Process

1. Development Flow

  1. Create feature branch from develop
  2. Make changes and commit
  3. Create PR to develop
  4. CI runs tests and checks
  5. Review and merge PR
  6. Automatic deployment to staging

2. Release Flow

  1. Merge develop to main
  2. Tag release version
  3. CI builds and deploys to production
  4. Release notes generated automatically

Quality Gates

1. Code Quality

  • Black formatting
  • Flake8 linting
  • isort import sorting
  • MyPy type checking
  • Test coverage > 80%

2. Security

  • Snyk vulnerability scanning
  • Dependencies audit
  • SAST scanning
  • Secret scanning

3. Performance

  • Load testing thresholds
  • Response time limits
  • Resource usage limits

Monitoring

1. CI/CD Metrics

  • Build success rate
  • Deployment frequency
  • Lead time for changes
  • Mean time to recovery

2. Alerts

# .github/workflows/alerts.yml
name: Alerts

on:
  workflow_run:
    workflows: ["CI", "Deploy"]
    types:
      - completed

jobs:
  alert:
    runs-on: ubuntu-latest
    if: ${{ github.event.workflow_run.conclusion == 'failure' }}
    steps:
    - name: Send Slack notification
      uses: 8398a7/action-slack@v3
      with:
        status: ${{ github.event.workflow_run.conclusion }}
        fields: repo,message,commit,author,action,workflow
      env:
        SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

Best Practices

1. Branch Protection

# Branch protection rules
main:
  - Require pull request reviews
  - Require status checks to pass
  - Require linear history
  - No force pushes

develop:
  - Require pull request reviews
  - Require status checks to pass

2. Commit Guidelines

# Conventional Commits
<type>(<scope>): <description>

Types:
- feat: New feature
- fix: Bug fix
- docs: Documentation
- style: Formatting
- refactor: Code restructure
- test: Testing
- chore: Maintenance

3. Review Process

  1. Automated checks must pass
  2. Code review required
  3. Security review for sensitive changes
  4. Performance review for critical paths

Rollback Procedures

1. Quick Rollback

# Revert to previous version
docker-compose -f docker-compose.prod.yml pull nonstopgg/backend:previous-tag
docker-compose -f docker-compose.prod.yml up -d

2. Database Rollback

# Revert last migration
python manage.py migrate app_name previous_migration

3. Emergency Procedures

  1. Identify issue source
  2. Disable affected feature flags
  3. Roll back to last stable version
  4. Notify stakeholders
  5. Post-mortem analysis

Documentation

1. Release Notes

  • Features added
  • Bugs fixed
  • Breaking changes
  • Migration instructions
  • Performance improvements

2. Deployment Logs

  • Deployment timestamp
  • Version deployed
  • Configuration changes
  • Migration status
  • Health check results

Future Improvements

  1. Automated Testing
  2. Integration test coverage
  3. E2E testing
  4. Performance testing

  5. Infrastructure as Code

  6. Terraform configurations
  7. Kubernetes manifests
  8. Helm charts

  9. Monitoring

  10. APM integration
  11. Metrics collection
  12. Log aggregation
  13. Alerting rules