# 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 ### Recommended Branch Structure ``` 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 ```bash 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` ```yaml 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` ```yaml 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` ```yaml 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` ```yaml 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` ```yaml --- - 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 ``` 3. **Ansible Inventory:** `inventory.yml` ```yaml 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` ```yaml 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** ```bash # 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** ```bash # Git rollback git checkout # 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: ```python # In config.py FEATURE_NEW_ANALYTICS = os.getenv("FEATURE_NEW_ANALYTICS", "false") == "true" ``` ### 6. **Changelog & Release Notes** Maintain `CHANGELOG.md`: ```markdown ## [1.2.0] - 2025-12-15 ### Added - Email reporting system - Gitea secrets integration ### Fixed - Database connection timeout ### Changed - Improved error handling ``` --- ## 📚 Quick Reference Commands ```bash # 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" ``` --- ## 🎯 Recommended Next Steps 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!** 🚀