Skip to content

delete(docs) remove infraestructura index duplicates #2

delete(docs) remove infraestructura index duplicates

delete(docs) remove infraestructura index duplicates #2

Workflow file for this run

name: Deploy
on:
push:
branches:
- main
tags:
- 'v*.*.*'
workflow_dispatch:
inputs:
environment:
description: 'Target environment'
required: true
default: 'staging'
type: choice
options:
- staging
- production
skip_tests:
description: 'Skip tests (NOT recommended for production)'
required: false
type: boolean
default: false
jobs:
pre-deployment-checks:
name: Pre-deployment Checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Determine target environment
id: env
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
echo "environment=${{ github.event.inputs.environment }}" >> $GITHUB_OUTPUT
elif [[ "${{ github.ref }}" == refs/tags/v* ]]; then
echo "environment=production" >> $GITHUB_OUTPUT
else
echo "environment=staging" >> $GITHUB_OUTPUT
fi
- name: Validate branch/tag
run: |
ENV=${{ steps.env.outputs.environment }}
if [ "$ENV" == "production" ]; then
if [[ ! "${{ github.ref }}" =~ ^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "ERROR: Production deployments require a version tag (v*.*.*))"
exit 1
fi
fi
echo "[PASS] Branch/tag validation passed"
- name: Check for IACT restrictions
run: |
echo "Validating IACT critical restrictions..."
# NO Redis check
if grep -r "redis" api/callcentersite/settings*.py; then
echo "ERROR: Redis detected. Prohibited by RNF-002"
exit 1
fi
# Session backend check
if ! grep -q "django.contrib.sessions.backends.db" api/callcentersite/settings*.py; then
echo "ERROR: SESSION_ENGINE must be django.contrib.sessions.backends.db"
exit 1
fi
echo "[PASS] IACT restrictions validated"
- name: Run pre-deployment validations
if: github.event.inputs.skip_tests != 'true'
run: |
if [ -f scripts/validate_critical_restrictions.sh ]; then
bash scripts/validate_critical_restrictions.sh
fi
outputs:
environment: ${{ steps.env.outputs.environment }}
run-tests:
name: Run Full Test Suite
runs-on: ubuntu-latest
needs: pre-deployment-checks
if: github.event.inputs.skip_tests != 'true'
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: testpass
MYSQL_DATABASE: test_iact
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping"
--health-interval=10s
--health-timeout=5s
--health-retries=3
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install -r api/requirements.txt
pip install pytest pytest-django pytest-cov
- name: Run tests with coverage
env:
DB_ENGINE: django.db.backends.mysql
DB_NAME: test_iact
DB_USER: root
DB_PASSWORD: testpass
DB_HOST: 127.0.0.1
DB_PORT: 3306
run: |
cd api/callcentersite
python manage.py migrate --run-syncdb
pytest --cov=callcentersite --cov-report=term --cov-fail-under=80
build-backend:
name: Build Backend
runs-on: ubuntu-latest
needs: [pre-deployment-checks, run-tests]
if: |
always() &&
needs.pre-deployment-checks.result == 'success' &&
(needs.run-tests.result == 'success' || needs.run-tests.result == 'skipped')
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
cd api
pip install -r requirements.txt
- name: Collect static files
run: |
cd api/callcentersite
python manage.py collectstatic --no-input
- name: Create deployment package
run: |
tar -czf backend-deployment.tar.gz api/
- name: Upload backend artifact
uses: actions/upload-artifact@v4
with:
name: backend-deployment
path: backend-deployment.tar.gz
retention-days: 7
build-frontend:
name: Build Frontend
runs-on: ubuntu-latest
needs: [pre-deployment-checks]
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
- name: Install dependencies
run: |
cd frontend
npm ci
- name: Build for production
env:
NODE_ENV: production
run: |
cd frontend
npm run build
- name: Create deployment package
run: |
tar -czf frontend-deployment.tar.gz frontend/build/
- name: Upload frontend artifact
uses: actions/upload-artifact@v4
with:
name: frontend-deployment
path: frontend-deployment.tar.gz
retention-days: 7
deploy-staging:
name: Deploy to Staging
runs-on: ubuntu-latest
needs: [pre-deployment-checks, build-backend, build-frontend]
if: needs.pre-deployment-checks.outputs.environment == 'staging'
environment:
name: staging
url: https://staging.iact.example.com
steps:
- uses: actions/checkout@v4
- name: Download backend artifact
uses: actions/download-artifact@v4
with:
name: backend-deployment
- name: Download frontend artifact
uses: actions/download-artifact@v4
with:
name: frontend-deployment
- name: Deploy to staging server
env:
SSH_PRIVATE_KEY: ${{ secrets.STAGING_SSH_KEY }}
STAGING_HOST: ${{ secrets.STAGING_HOST }}
STAGING_USER: ${{ secrets.STAGING_USER }}
run: |
echo "Deploying to staging environment..."
# Setup SSH
mkdir -p ~/.ssh
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H $STAGING_HOST >> ~/.ssh/known_hosts
# Upload deployment packages
scp backend-deployment.tar.gz $STAGING_USER@$STAGING_HOST:/tmp/
scp frontend-deployment.tar.gz $STAGING_USER@$STAGING_HOST:/tmp/
# Execute deployment script on remote server
ssh $STAGING_USER@$STAGING_HOST << 'ENDSSH'
set -e
# Backup current deployment
echo "Creating backup..."
sudo cp -r /var/www/iact /var/www/iact_backup_$(date +%Y%m%d_%H%M%S)
# Extract packages
echo "Extracting packages..."
cd /tmp
tar -xzf backend-deployment.tar.gz
tar -xzf frontend-deployment.tar.gz
# Deploy backend
echo "Deploying backend..."
sudo cp -r api/* /var/www/iact/api/
# Deploy frontend
echo "Deploying frontend..."
sudo cp -r frontend/build/* /var/www/iact/frontend/
# Run migrations
echo "Running migrations..."
cd /var/www/iact/api/callcentersite
sudo -u www-data python manage.py migrate --no-input
# Restart services
echo "Restarting services..."
sudo systemctl restart gunicorn-iact-staging
sudo systemctl reload nginx
# Health check
echo "Running health check..."
sleep 5
curl -f http://localhost/api/health || exit 1
echo "Deployment completed successfully!"
ENDSSH
- name: Verify deployment
run: |
echo "Verifying staging deployment..."
# Wait for service to stabilize
sleep 10
# Check health endpoint
curl -f https://staging.iact.example.com/api/health || exit 1
echo "[PASS] Staging deployment verified"
deploy-production:
name: Deploy to Production
runs-on: ubuntu-latest
needs: [pre-deployment-checks, build-backend, build-frontend]
if: needs.pre-deployment-checks.outputs.environment == 'production'
environment:
name: production
url: https://iact.example.com
steps:
- uses: actions/checkout@v4
- name: Download backend artifact
uses: actions/download-artifact@v4
with:
name: backend-deployment
- name: Download frontend artifact
uses: actions/download-artifact@v4
with:
name: frontend-deployment
- name: Create database backup
env:
SSH_PRIVATE_KEY: ${{ secrets.PRODUCTION_SSH_KEY }}
PRODUCTION_HOST: ${{ secrets.PRODUCTION_HOST }}
PRODUCTION_USER: ${{ secrets.PRODUCTION_USER }}
run: |
echo "Creating production database backup..."
mkdir -p ~/.ssh
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H $PRODUCTION_HOST >> ~/.ssh/known_hosts
ssh $PRODUCTION_USER@$PRODUCTION_HOST << 'ENDSSH'
mysqldump -u root -p$DB_PASSWORD iact_production > /backup/iact_production_$(date +%Y%m%d_%H%M%S).sql
echo "[PASS] Database backup created"
ENDSSH
- name: Blue-Green Deployment
env:
SSH_PRIVATE_KEY: ${{ secrets.PRODUCTION_SSH_KEY }}
PRODUCTION_HOST: ${{ secrets.PRODUCTION_HOST }}
PRODUCTION_USER: ${{ secrets.PRODUCTION_USER }}
run: |
echo "Executing blue-green deployment to production..."
# Upload deployment packages
scp backend-deployment.tar.gz $PRODUCTION_USER@$PRODUCTION_HOST:/tmp/
scp frontend-deployment.tar.gz $PRODUCTION_USER@$PRODUCTION_HOST:/tmp/
# Execute blue-green deployment
ssh $PRODUCTION_USER@$PRODUCTION_HOST << 'ENDSSH'
set -e
# Determine current and new environments
if [ -L /var/www/iact-current ] && [ "$(readlink /var/www/iact-current)" == "/var/www/iact-blue" ]; then
CURRENT="blue"
NEW="green"
else
CURRENT="green"
NEW="blue"
fi
echo "Current: $CURRENT, Deploying to: $NEW"
# Prepare new environment
echo "Preparing $NEW environment..."
sudo mkdir -p /var/www/iact-$NEW
cd /tmp
tar -xzf backend-deployment.tar.gz
tar -xzf frontend-deployment.tar.gz
sudo cp -r api/* /var/www/iact-$NEW/api/
sudo cp -r frontend/build/* /var/www/iact-$NEW/frontend/
# Run migrations on new environment
echo "Running migrations..."
cd /var/www/iact-$NEW/api/callcentersite
sudo -u www-data python manage.py migrate --no-input
# Start new environment
echo "Starting $NEW environment..."
sudo systemctl start gunicorn-iact-$NEW
# Health check on new environment
echo "Health check on $NEW environment..."
sleep 10
curl -f http://localhost:800$([[ "$NEW" == "green" ]] && echo 1 || echo 0)/api/health || exit 1
# Switch traffic to new environment
echo "Switching traffic to $NEW environment..."
sudo ln -sfn /var/www/iact-$NEW /var/www/iact-current
sudo systemctl reload nginx
# Final health check
sleep 5
curl -f http://localhost/api/health || exit 1
# Stop old environment (keep as fallback for 5 minutes)
echo "Keeping $CURRENT as fallback for 5 minutes..."
sleep 300
sudo systemctl stop gunicorn-iact-$CURRENT
echo "[PASS] Blue-green deployment completed successfully!"
ENDSSH
- name: Verify production deployment
run: |
echo "Verifying production deployment..."
# Wait for service to stabilize
sleep 15
# Check health endpoint
curl -f https://iact.example.com/api/health || exit 1
# Check session storage (MySQL)
echo "Verifying session storage..."
curl -f https://iact.example.com/api/session-check || exit 1
echo "[PASS] Production deployment verified"
- name: Create GitHub release (if tag push)
if: startsWith(github.ref, 'refs/tags/')
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
post-deployment-monitoring:
name: Post-deployment Monitoring
runs-on: ubuntu-latest
needs: [deploy-staging, deploy-production]
if: always() && (needs.deploy-staging.result == 'success' || needs.deploy-production.result == 'success')
steps:
- name: Monitor for 5 minutes
run: |
ENV=${{ needs.pre-deployment-checks.outputs.environment }}
URL=$([[ "$ENV" == "production" ]] && echo "https://iact.example.com" || echo "https://staging.iact.example.com")
echo "Monitoring $ENV for 5 minutes..."
for i in {1..30}; do
echo "Check $i/30..."
# Health check
if ! curl -f $URL/api/health; then
echo "[FAIL] Health check failed!"
exit 1
fi
# Check error rate
# (This would typically query a monitoring service)
sleep 10
done
echo "[PASS] Monitoring completed. No issues detected."
- name: Notify team
if: always()
run: |
STATUS=${{ job.status }}
ENV=${{ needs.pre-deployment-checks.outputs.environment }}
echo "Deployment to $ENV: $STATUS"
# Here you would send notification via Slack, Teams, or InternalMessage