POTE/docs/14_branch_strategy_and_deployment.md
ilia 01597f608f Add comprehensive branch strategy and multi-environment deployment guide
NEW DOCUMENTATION:
==================
docs/14_branch_strategy_and_deployment.md

COVERS:
=======
 Branch Strategy (main/qa/dev)
 Branch Protection Rules for Gitea
 Multi-environment deployment workflows
 Integration with Ansible auto-deploy
 Gitea secrets per environment
 Deployment flow diagram
 Rollback strategies
 Complete setup checklist

BRANCH STRUCTURE:
=================
main (prod) ← qa (staging) ← dev (development)

PROTECTION LEVELS:
==================
- main: MOST PROTECTED (require PR + 2 approvals + CI)
- qa: MODERATELY PROTECTED (require PR + CI)
- dev: LIGHTLY PROTECTED (require CI only)

DEPLOYMENT WORKFLOWS:
=====================
- deploy-dev.yml: Auto-deploy on push to dev
- deploy-qa.yml: Auto-deploy on push to qa + smoke tests
- deploy-prod.yml: Manual approval + rollback on failure

ANSIBLE INTEGRATION:
====================
- Webhook-based deployment
- Gitea Actions → Ansible API
- Environment-specific inventory
- Automated health checks

WHAT'S MISSING (ANSWERED):
==========================
 Environment variables per env
 Database migration strategy
 Rollback procedures
 Monitoring & alerts
 Feature flags
 Changelog management

BRANCHES CREATED:
=================
 dev branch created and pushed
 qa branch created and pushed
 main branch (existing)

Ready for Ansible auto-configure integration!
2025-12-24 21:46:37 -05:00

15 KiB

Branch Strategy & Multi-Environment Deployment

Overview

This guide covers setting up a proper Git branching strategy with protected branches for Dev, QA, and Production environments, integrated with your Ansible auto-deployment system.


🌳 Branch Strategy

main (production)
├── qa (quality assurance/staging)
└── dev (development)

Alternative naming:

prod (production)
├── staging (QA)
└── develop (dev)

🔒 Branch Protection Rules

In Gitea: Repository Settings → Branches

1. main (Production) - MOST PROTECTED

Protection Rules:

  • Require pull request reviews (at least 1 approval)
  • Require status checks to pass (CI must pass)
  • Restrict who can push (only maintainers)
  • Require signed commits (optional but recommended)
  • Block force pushes
  • Block deletions
  • Require linear history (no merge commits)

Merge Strategy:

  • Only merge from qa branch
  • Require successful QA testing
  • Tag releases: v1.0.0, v1.1.0, etc.

2. qa (Staging) - MODERATELY PROTECTED

Protection Rules:

  • Require pull request reviews (at least 1 approval)
  • Require status checks to pass (CI must pass)
  • Block force pushes
  • Block deletions

Merge Strategy:

  • Merge from dev branch
  • Run full test suite
  • Manual QA testing required

3. dev (Development) - LIGHTLY PROTECTED

Protection Rules:

  • Require status checks to pass (CI must pass)
  • Block force pushes (optional)
  • ⚠️ Allow direct commits (for rapid development)

Merge Strategy:

  • Feature branches merge here
  • Continuous integration testing
  • Auto-deploy to dev environment

📋 Gitea Branch Protection Setup

Step-by-Step Configuration

1. Create Branches

cd /home/user/Documents/code/pote

# Create dev branch from main
git checkout -b dev
git push origin dev

# Create qa branch from main
git checkout -b qa
git push origin qa

# Back to main
git checkout main

2. Configure in Gitea UI

1. Go to: https://git.levkin.ca/ilia/POTE/settings/branches
2. Click "Add New Rule"

For MAIN branch:
- Branch name pattern: main
- ✅ Enable push protection
- ✅ Require pull request
- ✅ Require 1 approval
- ✅ Require status checks
- ✅ Block force push
- ✅ Block deletion
- Whitelist: (leave empty or add specific users)

For QA branch:
- Branch name pattern: qa
- ✅ Enable push protection
- ✅ Require pull request
- ✅ Require status checks
- ✅ Block force push
- ✅ Block deletion

For DEV branch:
- Branch name pattern: dev
- ✅ Require status checks
- ⚠️ Allow direct push (for development)

🚀 Deployment Workflow Integration

Update Workflows for Multi-Environment

1. Update CI Workflow for All Branches

File: .github/workflows/ci.yml

name: CI

on:
  push:
    branches: [main, qa, dev]
  pull_request:
    branches: [main, qa, dev]

jobs:
  lint-and-test:
    runs-on: ubuntu-latest
    # ... existing CI jobs ...

2. Create Environment-Specific Deployment Workflows

File: .github/workflows/deploy-dev.yml

name: Deploy to Dev

on:
  push:
    branches: [dev]
  workflow_dispatch:

jobs:
  deploy-dev:
    runs-on: ubuntu-latest
    environment: development
    steps:
      - name: Check out code
        uses: actions/checkout@v4

      - name: Deploy to Dev Server
        env:
          DEV_HOST: ${{ secrets.DEV_HOST }}
          DEV_USER: ${{ secrets.DEV_USER }}
          DEV_SSH_KEY: ${{ secrets.DEV_SSH_KEY }}
          SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD_DEV }}
          DB_PASSWORD: ${{ secrets.DB_PASSWORD_DEV }}
        run: |
          # Setup SSH
          mkdir -p ~/.ssh
          echo "$DEV_SSH_KEY" > ~/.ssh/id_rsa
          chmod 600 ~/.ssh/id_rsa
          ssh-keyscan -H $DEV_HOST >> ~/.ssh/known_hosts
          
          # Deploy
          ssh ${DEV_USER}@${DEV_HOST} << 'ENDSSH'
            cd ~/pote-dev
            git fetch origin
            git checkout dev
            git pull origin dev
            source venv/bin/activate
            pip install -e .
            alembic upgrade head
          ENDSSH

File: .github/workflows/deploy-qa.yml

name: Deploy to QA

on:
  push:
    branches: [qa]
  workflow_dispatch:

jobs:
  deploy-qa:
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - name: Check out code
        uses: actions/checkout@v4

      - name: Deploy to QA Server
        env:
          QA_HOST: ${{ secrets.QA_HOST }}
          QA_USER: ${{ secrets.QA_USER }}
          QA_SSH_KEY: ${{ secrets.QA_SSH_KEY }}
          SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD_QA }}
          DB_PASSWORD: ${{ secrets.DB_PASSWORD_QA }}
        run: |
          # Setup SSH
          mkdir -p ~/.ssh
          echo "$QA_SSH_KEY" > ~/.ssh/id_rsa
          chmod 600 ~/.ssh/id_rsa
          ssh-keyscan -H $QA_HOST >> ~/.ssh/known_hosts
          
          # Deploy
          ssh ${QA_USER}@${QA_HOST} << 'ENDSSH'
            cd ~/pote-qa
            git fetch origin
            git checkout qa
            git pull origin qa
            source venv/bin/activate
            pip install -e .
            alembic upgrade head
          ENDSSH

      - name: Run Smoke Tests
        run: |
          ssh ${QA_USER}@${QA_HOST} << 'ENDSSH'
            cd ~/pote-qa
            source venv/bin/activate
            python scripts/health_check.py
          ENDSSH

File: .github/workflows/deploy-prod.yml

name: Deploy to Production

on:
  push:
    branches: [main]
  workflow_dispatch:
    inputs:
      confirm:
        description: 'Type "DEPLOY" to confirm production deployment'
        required: true

jobs:
  deploy-prod:
    runs-on: ubuntu-latest
    environment: production
    if: github.event.inputs.confirm == 'DEPLOY' || github.event_name == 'push'
    steps:
      - name: Check out code
        uses: actions/checkout@v4

      - name: Create Release Tag
        run: |
          git tag -a "v$(date +%Y%m%d-%H%M%S)" -m "Production release"
          git push origin --tags

      - name: Deploy to Production
        env:
          PROD_HOST: ${{ secrets.PROXMOX_HOST }}
          PROD_USER: ${{ secrets.PROXMOX_USER }}
          PROD_SSH_KEY: ${{ secrets.PROXMOX_SSH_KEY }}
          SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }}
          DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
        run: |
          # Setup SSH
          mkdir -p ~/.ssh
          echo "$PROD_SSH_KEY" > ~/.ssh/id_rsa
          chmod 600 ~/.ssh/id_rsa
          ssh-keyscan -H $PROD_HOST >> ~/.ssh/known_hosts
          
          # Backup current production
          ssh ${PROD_USER}@${PROD_HOST} << 'ENDSSH'
            cd ~/pote
            git tag "backup-$(date +%Y%m%d-%H%M%S)"
          ENDSSH
          
          # Deploy
          ssh ${PROD_USER}@${PROD_HOST} << 'ENDSSH'
            cd ~/pote
            git fetch origin
            git checkout main
            git pull origin main
            source venv/bin/activate
            pip install -e .
            alembic upgrade head
          ENDSSH

      - name: Health Check
        run: |
          ssh ${PROD_USER}@${PROD_HOST} << 'ENDSSH'
            cd ~/pote
            source venv/bin/activate
            python scripts/health_check.py
          ENDSSH

      - name: Rollback on Failure
        if: failure()
        run: |
          echo "❌ Deployment failed, rolling back..."
          ssh ${PROD_USER}@${PROD_HOST} << 'ENDSSH'
            cd ~/pote
            latest_backup=$(git tag -l "backup-*" | sort -r | head -1)
            git checkout "$latest_backup"
            source venv/bin/activate
            alembic upgrade head
          ENDSSH

🔐 Gitea Secrets for Multi-Environment

Organize Secrets by Environment

Development Secrets

DEV_HOST=10.0.10.100
DEV_USER=poteapp
DEV_SSH_KEY=(dev SSH key)
SMTP_PASSWORD_DEV=(dev mail password)
DB_PASSWORD_DEV=dev_password_123

QA/Staging Secrets

QA_HOST=10.0.10.101
QA_USER=poteapp
QA_SSH_KEY=(qa SSH key)
SMTP_PASSWORD_QA=(qa mail password)
DB_PASSWORD_QA=qa_password_123

Production Secrets

PROXMOX_HOST=10.0.10.95
PROXMOX_USER=poteapp
PROXMOX_SSH_KEY=(prod SSH key)
SMTP_PASSWORD=(prod mail password)
DB_PASSWORD=changeme123

📊 Deployment Flow Diagram

Developer
    │
    ├─> Commit to feature branch
    │
    ├─> Create PR to dev
    │       │
    │       ├─> CI runs (tests)
    │       │
    │       ├─> Merge to dev
    │       │
    │       └─> Auto-deploy to DEV environment
    │
    ├─> Test in DEV
    │
    ├─> Create PR: dev → qa
    │       │
    │       ├─> CI runs (tests)
    │       │
    │       ├─> Code review required
    │       │
    │       ├─> Merge to qa
    │       │
    │       └─> Auto-deploy to QA environment
    │
    ├─> QA Testing
    │
    └─> Create PR: qa → main
            │
            ├─> CI runs (tests)
            │
            ├─> Code review required (2 approvals)
            │
            ├─> Manual approval for prod deploy
            │
            ├─> Merge to main
            │
            ├─> Create release tag
            │
            └─> Deploy to PRODUCTION

🔄 Integration with Your Ansible System

Option 1: Gitea Webhooks → Ansible

Setup:

  1. In Gitea: Settings → Webhooks → Add Webhook

    • URL: https://your-ansible-controller/webhook/pote
    • Trigger: Push events
    • Branches: dev, qa, main
  2. Ansible Playbook: deploy-pote.yml

---
- name: Deploy POTE based on branch
  hosts: "{{ target_env }}"
  vars:
    branch: "{{ git_branch }}"
    env: "{{ target_env }}"
  tasks:
    - name: Pull latest code
      git:
        repo: gitea@10.0.30.169:ilia/POTE.git
        dest: /home/poteapp/pote
        version: "{{ branch }}"
        force: yes

    - name: Install dependencies
      pip:
        requirements: /home/poteapp/pote/requirements.txt
        virtualenv: /home/poteapp/pote/venv

    - name: Run migrations
      command: alembic upgrade head
      args:
        chdir: /home/poteapp/pote
      environment:
        DATABASE_URL: "{{ database_url }}"

    - name: Update secrets
      template:
        src: env.j2
        dest: /home/poteapp/pote/.env
        mode: 0600

    - name: Health check
      command: python scripts/health_check.py
      args:
        chdir: /home/poteapp/pote
  1. Ansible Inventory: inventory.yml
all:
  children:
    development:
      hosts:
        dev-pote:
          ansible_host: 10.0.10.100
          target_env: development
          git_branch: dev
          database_url: postgresql://poteuser:dev_pass@localhost/potedb_dev

    staging:
      hosts:
        qa-pote:
          ansible_host: 10.0.10.101
          target_env: staging
          git_branch: qa
          database_url: postgresql://poteuser:qa_pass@localhost/potedb_qa

    production:
      hosts:
        prod-pote:
          ansible_host: 10.0.10.95
          target_env: production
          git_branch: main
          database_url: postgresql://poteuser:prod_pass@localhost/potedb

Option 2: Gitea Actions → Ansible

File: .github/workflows/ansible-deploy.yml

name: Ansible Deploy

on:
  push:
    branches: [main, qa, dev]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Determine environment
        id: env
        run: |
          if [ "${{ github.ref }}" == "refs/heads/main" ]; then
            echo "environment=production" >> $GITHUB_OUTPUT
            echo "host=10.0.10.95" >> $GITHUB_OUTPUT
          elif [ "${{ github.ref }}" == "refs/heads/qa" ]; then
            echo "environment=staging" >> $GITHUB_OUTPUT
            echo "host=10.0.10.101" >> $GITHUB_OUTPUT
          else
            echo "environment=development" >> $GITHUB_OUTPUT
            echo "host=10.0.10.100" >> $GITHUB_OUTPUT
          fi

      - name: Trigger Ansible
        run: |
          curl -X POST https://your-ansible-controller/api/deploy \
            -H "Authorization: Bearer ${{ secrets.ANSIBLE_TOKEN }}" \
            -d '{
              "project": "pote",
              "environment": "${{ steps.env.outputs.environment }}",
              "branch": "${{ github.ref_name }}",
              "commit": "${{ github.sha }}"
            }'

Complete Setup Checklist

1. Git Configuration

  • Create dev branch
  • Create qa branch
  • Keep main branch
  • Push all branches to Gitea

2. Gitea Branch Protection

  • Protect main (require PR + approval + CI)
  • Protect qa (require PR + CI)
  • Configure dev (require CI only)

3. Gitea Secrets

  • Add DEV environment secrets
  • Add QA environment secrets
  • Add PROD environment secrets

4. Workflows

  • Update ci.yml for all branches
  • Create deploy-dev.yml
  • Create deploy-qa.yml
  • Create deploy-prod.yml

5. Ansible Integration

  • Configure Gitea webhooks (if using webhooks)
  • Update Ansible playbooks for POTE
  • Test deployment to each environment

6. Documentation

  • Document deployment process
  • Create runbook for rollbacks
  • Train team on workflow

🚨 What You're Missing (Important!)

1. Environment Variables per Environment

Create separate .env files:

  • .env.dev
  • .env.qa
  • .env.prod

Never commit these! Use Ansible templates or Gitea secrets.

2. Database Migrations Strategy

# Test migrations in dev first
alembic upgrade head  # dev

# Then qa
alembic upgrade head  # qa

# Finally prod (with backup!)
pg_dump potedb > backup.sql
alembic upgrade head  # prod

3. Rollback Strategy

# Git rollback
git checkout <previous-commit>

# Database rollback
alembic downgrade -1

# Or restore from backup
psql potedb < backup.sql

4. Monitoring & Alerts

  • Health checks after each deployment
  • Email/Slack notifications on failure
  • Automated rollback on critical errors

5. Feature Flags

Consider adding feature flags for gradual rollouts:

# In config.py
FEATURE_NEW_ANALYTICS = os.getenv("FEATURE_NEW_ANALYTICS", "false") == "true"

6. Changelog & Release Notes

Maintain CHANGELOG.md:

## [1.2.0] - 2025-12-15
### Added
- Email reporting system
- Gitea secrets integration

### Fixed
- Database connection timeout

### Changed
- Improved error handling

📚 Quick Reference Commands

# Create branches
git checkout -b dev && git push origin dev
git checkout -b qa && git push origin qa

# Merge dev → qa
git checkout qa
git merge dev
git push origin qa

# Merge qa → main (via PR in Gitea!)
# Don't do this directly - use Pull Request

# Check which branch you're on
git branch

# See all branches
git branch -a

# Deploy manually (if Ansible fails)
ssh poteapp@10.0.10.100 "cd ~/pote && git pull origin dev"

  1. Right now: Create dev and qa branches
  2. Today: Set up branch protection in Gitea
  3. This week: Create environment-specific workflows
  4. This week: Integrate with your Ansible system
  5. Next week: Test full deployment flow

With this setup, you'll have a professional, production-ready deployment pipeline! 🚀