#deploy-to-prod #66
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Deploy Docker to EC2 | |
| on: | |
| push: | |
| branches: | |
| - main # This will trigger on any push to the main branch | |
| jobs: | |
| build_and_push: | |
| if: github.event.head_commit.message == '#deploy-to-prod' # Check for commit message | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v2 | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@v2 | |
| with: | |
| aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| aws-region: us-east-1 | |
| - name: Build and Push Docker image | |
| run: | | |
| docker compose -f production.yml build django | |
| docker tag failures_production_django:latest ${{ secrets.AWS_ECR_REPOSITORY_URL }}:latest | |
| aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin ${{ secrets.AWS_ECR_REPOSITORY_URL }} | |
| docker push ${{ secrets.AWS_ECR_REPOSITORY_URL }}:latest | |
| deploy_to_ec2: | |
| if: github.event.head_commit.message == '#deploy-to-prod' # Check for commit message | |
| needs: build_and_push | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Start SSH agent and add EC2 private key | |
| run: | | |
| echo "${{ secrets.EC2_PRIVATE_KEY }}" > ec2-key.pem | |
| chmod 600 ec2-key.pem | |
| eval "$(ssh-agent -s)" | |
| ssh-add ec2-key.pem | |
| - name: SSH into EC2 and restart Docker | |
| run: | | |
| ssh -o StrictHostKeyChecking=no -i ec2-key.pem ec2-user@ec2-${{ secrets.AWS_EC2_PUBLIC_IP_WITH_DASHES }}.compute-1.amazonaws.com << 'EOF' | |
| # Stop and remove everything | |
| docker stop $(docker ps -aq) | |
| docker rm $(docker ps -aq) | |
| # Setup environment variables | |
| export DJANGO_ALLOWED_HOSTS="softwarefailures.com,$(ifconfig enX0 | grep 'inet ' | awk '{print $2}'),$(curl -s http://checkip.amazonaws.com)" | |
| export REDIS_URL=redis://redis:6379/0 | |
| export CELERY_BROKER_URL="${REDIS_URL}" | |
| export $(aws secretsmanager get-secret-value --secret-id prod/failure/postgres --region us-east-1 --query SecretString --output text | jq -r '. as $secret | "POSTGRES_HOST=\($secret | .host)\nPOSTGRES_PORT=5432\nPOSTGRES_DB=\($secret | .dbname)\nPOSTGRES_USER=\($secret | .username)\nPOSTGRES_PASSWORD=\($secret | .password)\nDATABASE_URL=postgres://\($secret | .username):\($secret | .password)@\($secret | .host):5432/\($secret | .dbname)"') | |
| export OPENAI_API_KEY='${{ secrets.OPENAI_API_KEY }}' | |
| export CHAINLIT_DB_URI="${DATABASE_URL}" | |
| export CHAINLIT_DATABASE_URL="${DATABASE_URL/postgres:\/\//postgresql://}" | |
| export DJANGO_SECRET_KEY='test' | |
| export DJANGO_ADMIN_URL='admin/' | |
| export CHAINLIT_AUTH_SECRET="0,uZEoYlN7auIrSf1F%7mm/6@n9:ubHDb36Z31L9vhY^2uzr4eiZGzQpMpK:%K,I" | |
| export FAILBOT_REDIRECT_URL='${{ secrets.FAILBOT_REDIRECT_URL }}' | |
| # Pull the latest image | |
| aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin ${{ secrets.AWS_ECR_REPOSITORY_URL }} | |
| docker pull ${{ secrets.AWS_ECR_REPOSITORY_URL }}:latest | |
| # Start the container with the new image | |
| docker network create failures-prod || true | |
| docker volume create failures_chroma_data || true | |
| docker run -d --name redis --network failures-prod -p 6379:6379 redis:alpine | |
| docker run -d --name chroma --network failures-prod -p 8001:8001 -v failures_chroma_data:/var/lib/chroma/data ghcr.io/chroma-core/chroma:1.0.9 run --host 0.0.0.0 --port 8001 --path /var/lib/chroma/data | |
| docker run -d --name django-prod --network failures-prod -p 80:80 -e POSTGRES_HOST -e POSTGRES_PORT -e POSTGRES_DB -e POSTGRES_USER -e POSTGRES_PASSWORD -e DATABASE_URL -e REDIS_URL -e CELERY_BROKER_URL -e DJANGO_ALLOWED_HOSTS -e DJANGO_SECRET_KEY -e DJANGO_ADMIN_URL -e FAILBOT_REDIRECT_URL -e OPENAI_API_KEY -e DJANGO_SETTINGS_MODULE=config.settings.production ${{ secrets.AWS_ECR_REPOSITORY_URL }}:latest /start | |
| # Initial backfill only when collection is empty | |
| sleep 10 | |
| CHROMA_COUNT=$(docker exec django-prod /bin/sh -lc 'python -c "import sys,pysqlite3; sys.modules[\"sqlite3\"]=sys.modules.pop(\"pysqlite3\"); import chromadb; c=chromadb.HttpClient(host=\"chroma\", port=8001); col=c.get_or_create_collection(\"articlesVDB\"); print(col.count())"') | |
| if [ "$CHROMA_COUNT" = "0" ]; then | |
| docker exec django-prod python -m failures backfillchroma | |
| fi | |
| # Start Chainlit after backfill to avoid stale collection handles | |
| docker run -d --name chainlit-prod --network failures-prod --cpus 1.0 --memory 2g --memory-swap 2g -w /app/failbot -p 8501:8501 -e POSTGRES_HOST -e POSTGRES_PORT -e POSTGRES_DB -e POSTGRES_USER -e POSTGRES_PASSWORD -e DATABASE_URL="${CHAINLIT_DATABASE_URL}" -e REDIS_URL -e CELERY_BROKER_URL -e DJANGO_SECRET_KEY -e DJANGO_ADMIN_URL -e CHAINLIT_DB_URI="${CHAINLIT_DATABASE_URL}" -e CHAINLIT_AUTH_SECRET -e OPENAI_API_KEY -e DJANGO_SETTINGS_MODULE=config.settings.production -e PYTHONPATH=/app ${{ secrets.AWS_ECR_REPOSITORY_URL }}:latest chainlit run failbotUI.py --port 8501 --host 0.0.0.0 | |
| # Clean up | |
| docker image prune -f --all | |
| docker network prune -f | |
| EOF |