|
1 |
| -name: Deploy to EC2 |
| 1 | +name: EC2 Deploy |
2 | 2 |
|
3 | 3 | on:
|
4 | 4 | push:
|
5 | 5 | branches:
|
6 | 6 | - devops/a3
|
7 | 7 | tags:
|
8 |
| - - 'deploy-*' # Matches tags like deploy-dev, deploy-qa, deploy-prod |
| 8 | + - deploy-dev |
| 9 | + - deploy-qa |
| 10 | + - deploy-prod |
| 11 | + |
9 | 12 | workflow_dispatch:
|
10 | 13 | inputs:
|
11 | 14 | stage:
|
12 |
| - description: 'Deployment stage (dev, qa, prod)' |
| 15 | + description: "Select stage to deploy" |
13 | 16 | required: true
|
14 |
| - default: 'dev' |
| 17 | + default: dev |
15 | 18 | type: choice
|
16 | 19 | options:
|
17 | 20 | - dev
|
|
20 | 23 |
|
21 | 24 | env:
|
22 | 25 | AWS_REGION: ap-south-1
|
| 26 | + TF_WORKING_DIR: ./terraform |
23 | 27 |
|
24 | 28 | jobs:
|
25 | 29 | deploy:
|
26 | 30 | runs-on: ubuntu-latest
|
27 | 31 |
|
28 | 32 | steps:
|
29 |
| - - name: Determine Stage |
30 |
| - id: set_stage |
31 |
| - run: | |
32 |
| - STAGE_INPUT="${{ github.event.inputs.stage }}" |
33 |
| - STAGE="" |
34 |
| -
|
35 |
| - if [[ "${GITHUB_REF}" == refs/tags/deploy-* ]]; then |
36 |
| - STAGE="${GITHUB_REF#refs/tags/deploy-}" |
37 |
| - echo "Tag trigger detected. Stage set to: $STAGE" |
38 |
| - elif [[ -n "$STAGE_INPUT" ]]; then |
39 |
| - STAGE="$STAGE_INPUT" |
40 |
| - echo "Manual trigger detected. Stage set to: $STAGE" |
41 |
| - else |
42 |
| - echo "Branch trigger detected (main). Defaulting stage to dev." |
43 |
| - STAGE="dev" |
44 |
| - fi |
45 |
| -
|
46 |
| - # Validate stage |
47 |
| - if [[ "$STAGE" != "dev" && "$STAGE" != "qa" && "$STAGE" != "prod" ]]; then |
48 |
| - echo "Invalid stage: $STAGE. Must be dev, qa, or prod." |
49 |
| - exit 1 |
50 |
| - fi |
51 |
| -
|
52 |
| - echo "STAGE=$STAGE" >> $GITHUB_ENV |
53 |
| -
|
54 |
| - # Checkout Code |
| 33 | + # Checkout Repository |
55 | 34 | - name: Checkout repository
|
56 | 35 | uses: actions/checkout@v4
|
57 | 36 |
|
58 | 37 | # Configure AWS Credentials
|
59 |
| - - name: Configure AWS Credentials |
60 |
| - uses: aws-actions/configure-aws-credentials@v4 |
| 38 | + - name: Configure AWS credentials |
| 39 | + uses: aws-actions/configure-aws-credentials@v2 |
61 | 40 | with:
|
62 | 41 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
63 | 42 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
64 | 43 | aws-region: ${{ env.AWS_REGION }}
|
| 44 | + aws-output: json |
| 45 | + |
| 46 | + # Install Terraform |
| 47 | + - name: Setup Terraform |
| 48 | + uses: hashicorp/setup-terraform@v3 |
| 49 | + |
| 50 | + # Determin Stage - dev/prod/qa defaults to dev |
| 51 | + # - name: Determine Stage |
| 52 | + # id: set_stage |
| 53 | + # run: | |
| 54 | + # if [[ "${GITHUB_REF}" == "refs/tags/deploy-dev" ]]; then |
| 55 | + # echo "STAGE=dev" >> $GITHUB_ENV |
| 56 | + # elif [[ "${GITHUB_REF}" == "refs/tags/deploy-qa" ]]; then |
| 57 | + # echo "STAGE=qa" >> $GITHUB_ENV |
| 58 | + # elif [[ "${GITHUB_REF}" == "refs/tags/deploy-prod" ]]; then |
| 59 | + # echo "STAGE=prod" >> $GITHUB_ENV |
| 60 | + # elif [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then |
| 61 | + # echo "STAGE=${{ github.event.inputs.stage }}" >> $GITHUB_ENV |
| 62 | + # else |
| 63 | + # echo "STAGE=dev" >> $GITHUB_ENV # default fallback |
| 64 | + # fi |
| 65 | + |
| 66 | + # echo "🛠️ Deployment stage: $STAGE" |
| 67 | + |
| 68 | + # Terraform Init & Workspace |
| 69 | + - name: Terraform Init & Workspace |
| 70 | + working-directory: ${{ env.TF_WORKING_DIR }} |
| 71 | + run: | |
| 72 | + terraform init |
| 73 | + terraform workspace select ${{ github.event.inputs.stage }} || terraform workspace new ${{ github.event.inputs.stage }} |
| 74 | +
|
| 75 | + # Terraform Apply |
| 76 | + - name: Terraform Apply |
| 77 | + working-directory: ${{ env.TF_WORKING_DIR }} |
| 78 | + run: | |
| 79 | + terraform apply -var-file="${{ github.event.inputs.stage }}_config.tfvars" -auto-approve \ |
| 80 | + -var "stage=${{ github.event.inputs.stage }}" |
65 | 81 |
|
66 |
| - # Install Dependencies |
67 |
| - - name: Install dependencies |
| 82 | + # Output and inject EC2 IPs & S3 Bucket name to Github Env |
| 83 | + - name: Get EC2s Public IPs & S3 Bucket Name |
| 84 | + working-directory: ${{ env.TF_WORKING_DIR }} |
68 | 85 | run: |
|
69 |
| - sudo apt update |
70 |
| - sudo apt install -y unzip curl terraform |
| 86 | + echo "Injecting terraform outputs to github environment" |
| 87 | + # echo "INSTANCE_IP=$(terraform output -raw instance_public_ip)" >> $GITHUB_ENV |
| 88 | + # echo "VERIFIER_IP=$(terraform output -raw verifier_instance_public_ip)" >> $GITHUB_ENV |
| 89 | + # echo "S3_BUCKET=$(terraform output -raw s3_log_bucket)" >> $GITHUB_ENV |
| 90 | + # Assign to local shell variables |
| 91 | + INSTANCE_IP=$(terraform output -raw instance_public_ip) |
| 92 | + VERIFIER_IP=$(terraform output -raw verifier_instance_public_ip) |
| 93 | + S3_BUCKET=$(terraform output -raw s3_log_bucket) |
71 | 94 |
|
72 |
| - # Setup SSH Private Key |
73 |
| - - name: Setup SSH Private Key |
| 95 | + # Write to GitHub Actions ENV for later steps |
| 96 | + echo "INSTANCE_IP=$INSTANCE_IP" >> $GITHUB_ENV |
| 97 | + echo "VERIFIER_IP=$VERIFIER_IP" >> $GITHUB_ENV |
| 98 | + echo "S3_BUCKET=$S3_BUCKET" >> $GITHUB_ENV |
| 99 | +
|
| 100 | + # Echo both for current step & confirmation |
| 101 | + echo "📦 App IP (Shell): $INSTANCE_IP" |
| 102 | + echo "🔑 Verifier IP (Shell): $VERIFIER_IP" |
| 103 | + echo "🪣 S3 Bucket (Shell): $S3_BUCKET" |
| 104 | +
|
| 105 | +
|
| 106 | + # Wait for App Initialization |
| 107 | + - name: Wait for App Initialization |
| 108 | + run: | |
| 109 | + echo "⏳ Waiting 90 seconds for EC2 instances to initialize..." |
| 110 | + sleep 90 |
| 111 | +
|
| 112 | + # Validate App Health |
| 113 | + - name: Validate App Health |
74 | 114 | run: |
|
75 |
| - echo "${{ secrets.SSH_PRIVATE_KEY }}" > ec2_key.pem |
76 |
| - chmod 400 ec2_key.pem |
| 115 | + echo "Checking app health at http://${{ env.INSTANCE_IP }}:80" |
| 116 | + for i in {1..10}; do |
| 117 | + STATUS=$(curl -o /dev/null -s -w "%{http_code}" http://$INSTANCE_IP:80) |
| 118 | + if [[ "$STATUS" == "200" ]]; then |
| 119 | + echo "✅ App is healthy (HTTP 200)" |
| 120 | + exit 0 |
| 121 | + else |
| 122 | + echo "Attempt $i: got HTTP $STATUS" |
| 123 | + sleep 10 |
| 124 | + fi |
| 125 | + done |
| 126 | + echo "❌ App failed health check" |
| 127 | + exit 1 |
77 | 128 |
|
78 |
| - # Make deploy.sh executable |
79 |
| - - name: Make deploy.sh executable |
80 |
| - run: chmod +x scripts/deploy.sh |
| 129 | + echo -e "\n📦 Full Response from App:\n" |
| 130 | + curl -s http://${{ env.INSTANCE_IP }}:80 || echo "❌ Failed to get response" |
| 131 | + echo -e "\n" |
| 132 | +
|
| 133 | + # Verify Logs in S3 |
| 134 | + - name: Verify Logs in S3 |
| 135 | + run: | |
| 136 | + echo "📦 Checking for logs in S3 bucket: $S3_BUCKET" |
| 137 | + aws s3 ls s3://$S3_BUCKET/system/cloud-init.log || { echo "❌ system logs missing"; exit 1; } |
| 138 | + aws s3 ls s3://$S3_BUCKET/app/my-app.log || { echo "❌ app logs missing"; exit 1; } |
| 139 | + echo "✅ Logs found in S3 bucket" |
| 140 | +
|
| 141 | + # Destroy (disabled by default) |
| 142 | + - name: Destroy infrastructure |
| 143 | + if: always() |
| 144 | + working-directory: ${{ env.TF_WORKING_DIR }} |
| 145 | + run: | |
| 146 | + echo "🗑️ Destroying infrastructure for stage: ${{ github.event.inputs.stage }}" |
| 147 | + sleep 60 |
| 148 | + terraform destroy -var-file="${{ github.event.inputs.stage }}_config.tfvars" -auto-approve \ |
| 149 | + -var "stage=${{ github.event.inputs.stage }}" |
81 | 150 |
|
82 |
| - # Run deploy.sh with detected stage |
83 |
| - - name: Run deploy.sh |
| 151 | + # Cleanup Terraform Workspace |
| 152 | + - name: Cleanup Terraform Workspace |
| 153 | + if: always() |
| 154 | + working-directory: ${{ env.TF_WORKING_DIR }} |
84 | 155 | run: |
|
85 |
| - export PRIVATE_KEY_PATH="./ec2_key.pem" |
86 |
| - ./scripts/deploy.sh $STAGE |
| 156 | + terraform workspace select default |
| 157 | + terraform workspace delete ${{ github.event.inputs.stage }} |
0 commit comments