fix: Resolve burst limit false positives and execution lock deadlock #48
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 to AWS ECS | |
| on: | |
| push: | |
| branches: [ main ] | |
| workflow_dispatch: # Allow manual trigger | |
| env: | |
| AWS_REGION: us-east-2 | |
| ECR_REPOSITORY: pythonide-backend | |
| ECS_SERVICE: pythonide-service | |
| ECS_CLUSTER: pythonide-cluster | |
| ECS_TASK_DEFINITION: .github/ecs-task-definition.json | |
| jobs: | |
| deploy: | |
| name: Deploy | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@v4 | |
| with: | |
| aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| aws-region: ${{ env.AWS_REGION }} | |
| - name: Login to Amazon ECR | |
| id: login-ecr | |
| uses: aws-actions/amazon-ecr-login@v2 | |
| - name: Build, tag, and push image to Amazon ECR | |
| id: build-image | |
| env: | |
| ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} | |
| IMAGE_TAG: ${{ github.sha }} | |
| run: | | |
| # Build Docker image for linux/amd64 platform | |
| docker build --platform linux/amd64 -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . | |
| docker build --platform linux/amd64 -t $ECR_REGISTRY/$ECR_REPOSITORY:latest . | |
| # Push both tags | |
| docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG | |
| docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest | |
| echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT | |
| - name: Fill in the new image ID in the Amazon ECS task definition | |
| id: task-def | |
| uses: aws-actions/amazon-ecs-render-task-definition@v1 | |
| with: | |
| task-definition: ${{ env.ECS_TASK_DEFINITION }} | |
| container-name: pythonide-backend | |
| image: ${{ steps.build-image.outputs.image }} | |
| - name: Deploy Amazon ECS task definition | |
| uses: aws-actions/amazon-ecs-deploy-task-definition@v1 | |
| with: | |
| task-definition: ${{ steps.task-def.outputs.task-definition }} | |
| service: ${{ env.ECS_SERVICE }} | |
| cluster: ${{ env.ECS_CLUSTER }} | |
| wait-for-service-stability: true | |
| - name: Ensure Auto-Scaling Configuration | |
| run: | | |
| echo "🎯 Verifying and maintaining auto-scaling configuration..." | |
| # Check if auto-scaling target exists | |
| SCALING_TARGET=$(aws application-autoscaling describe-scalable-targets \ | |
| --service-namespace ecs \ | |
| --resource-ids "service/${{ env.ECS_CLUSTER }}/${{ env.ECS_SERVICE }}" \ | |
| --region ${{ env.AWS_REGION }} \ | |
| --query 'ScalableTargets[0].ResourceId' \ | |
| --output text 2>/dev/null) || SCALING_TARGET="None" | |
| if [ "$SCALING_TARGET" = "None" ] || [ "$SCALING_TARGET" = "" ]; then | |
| echo "⚠️ Auto-scaling not configured. Setting up now..." | |
| # Register scalable target | |
| aws application-autoscaling register-scalable-target \ | |
| --service-namespace ecs \ | |
| --resource-id "service/${{ env.ECS_CLUSTER }}/${{ env.ECS_SERVICE }}" \ | |
| --scalable-dimension ecs:service:DesiredCount \ | |
| --min-capacity 2 \ | |
| --max-capacity 6 \ | |
| --region ${{ env.AWS_REGION }} | |
| echo "✅ Scalable target registered: 2-6 tasks" | |
| # Create scaling policy | |
| aws application-autoscaling put-scaling-policy \ | |
| --policy-name "pythonide-cpu-scaling-policy" \ | |
| --service-namespace ecs \ | |
| --resource-id "service/${{ env.ECS_CLUSTER }}/${{ env.ECS_SERVICE }}" \ | |
| --scalable-dimension ecs:service:DesiredCount \ | |
| --policy-type TargetTrackingScaling \ | |
| --target-tracking-scaling-policy-configuration '{ | |
| "TargetValue": 45.0, | |
| "PredefinedMetricSpecification": { | |
| "PredefinedMetricType": "ECSServiceAverageCPUUtilization" | |
| }, | |
| "ScaleOutCooldown": 300, | |
| "ScaleInCooldown": 300 | |
| }' \ | |
| --region ${{ env.AWS_REGION }} | |
| echo "✅ Auto-scaling policy created: CPU target 45%" | |
| else | |
| echo "✅ Auto-scaling configuration already exists" | |
| fi | |
| # Ensure minimum 2 tasks are running (for high availability) | |
| CURRENT_DESIRED=$(aws ecs describe-services \ | |
| --cluster ${{ env.ECS_CLUSTER }} \ | |
| --services ${{ env.ECS_SERVICE }} \ | |
| --region ${{ env.AWS_REGION }} \ | |
| --query 'services[0].desiredCount' \ | |
| --output text) | |
| if [ "$CURRENT_DESIRED" -lt "2" ]; then | |
| echo "⚠️ Desired count is $CURRENT_DESIRED, updating to minimum 2 tasks..." | |
| aws ecs update-service \ | |
| --cluster ${{ env.ECS_CLUSTER }} \ | |
| --service ${{ env.ECS_SERVICE }} \ | |
| --desired-count 2 \ | |
| --region ${{ env.AWS_REGION }} | |
| echo "✅ Service updated to run minimum 2 tasks" | |
| else | |
| echo "✅ Service already running $CURRENT_DESIRED tasks" | |
| fi | |
| - name: Verify Deployment and Auto-Scaling | |
| run: | | |
| echo "🔍 Final verification of deployment and auto-scaling..." | |
| # Get service status | |
| SERVICE_INFO=$(aws ecs describe-services \ | |
| --cluster ${{ env.ECS_CLUSTER }} \ | |
| --services ${{ env.ECS_SERVICE }} \ | |
| --region ${{ env.AWS_REGION }} \ | |
| --query 'services[0].{RunningCount:runningCount,DesiredCount:desiredCount,TaskDefinition:taskDefinition}') | |
| echo "Service Status:" | |
| echo "$SERVICE_INFO" | |
| # Get task resources | |
| TASK_DEF=$(echo "$SERVICE_INFO" | python3 -c "import sys,json; print(json.load(sys.stdin)['TaskDefinition'])" 2>/dev/null) | |
| TASK_RESOURCES=$(aws ecs describe-task-definition \ | |
| --task-definition "$TASK_DEF" \ | |
| --region ${{ env.AWS_REGION }} \ | |
| --query 'taskDefinition.{CPU:cpu,Memory:memory}') | |
| echo "Task Resources:" | |
| echo "$TASK_RESOURCES" | |
| # Get auto-scaling config | |
| SCALING_CONFIG=$(aws application-autoscaling describe-scalable-targets \ | |
| --service-namespace ecs \ | |
| --resource-ids "service/${{ env.ECS_CLUSTER }}/${{ env.ECS_SERVICE }}" \ | |
| --region ${{ env.AWS_REGION }} \ | |
| --query 'ScalableTargets[0].{MinCapacity:MinCapacity,MaxCapacity:MaxCapacity}') | |
| echo "Auto-Scaling Configuration:" | |
| echo "$SCALING_CONFIG" | |
| # Calculate estimated capacity from service info | |
| RUNNING_TASKS=$(echo "$SERVICE_INFO" | grep -o '"RunningCount":[0-9]*' | cut -d: -f2) | |
| CPU=$(echo "$TASK_RESOURCES" | grep -o '"CPU":"[0-9]*"' | cut -d\" -f4) | |
| if [ "$CPU" = "2048" ]; then | |
| ESTIMATED_CAPACITY=$((RUNNING_TASKS * 20)) | |
| echo "✅ Deployment successful! Estimated capacity: ~$ESTIMATED_CAPACITY concurrent students" | |
| echo "🎯 Auto-scaling active: Scales 2-6 tasks based on CPU > 45%" | |
| else | |
| echo "⚠️ Task resources may need updating to 2048 CPU for optimal performance" | |
| fi | |
| - name: Post-Deployment Summary | |
| run: | | |
| echo "🎉 DEPLOYMENT SUMMARY" | |
| echo "====================" | |
| echo "✅ New Docker image deployed successfully" | |
| echo "✅ Auto-scaling configuration verified/updated" | |
| echo "✅ Service running with high availability (min 2 tasks)" | |
| echo "✅ Ready to handle 60+ concurrent students" | |
| echo "" | |
| echo "🔗 Monitor your service:" | |
| echo " • ECS Console: https://console.aws.amazon.com/ecs/home?region=${{ env.AWS_REGION }}#/clusters/${{ env.ECS_CLUSTER }}/services" | |
| echo " • Application: http://pythonide-classroom.tech/editor" | |
| echo "" | |
| echo "💰 Current configuration supports automatic scaling based on demand" | |
| echo " with cost-effective resource management." |