project demonstration #54
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: EC2 Deploy | |
on: | |
push: | |
branches: | |
- devops/a3 | |
tags: | |
- deploy-dev | |
- deploy-prod | |
workflow_dispatch: | |
inputs: | |
stage: | |
description: "Select stage to deploy" | |
required: true | |
default: dev | |
type: choice | |
options: | |
- dev | |
- prod | |
env: | |
AWS_REGION: ap-south-1 | |
TF_WORKING_DIR: ./terraform | |
jobs: | |
deploy: | |
runs-on: ubuntu-latest | |
steps: | |
# Checkout Repository | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
# Configure AWS Credentials | |
- 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: ${{ env.AWS_REGION }} | |
# Install Terraform | |
- name: Setup Terraform | |
uses: hashicorp/setup-terraform@v3 | |
# Determine Stage - dev/prod defaults to dev | |
- name: Determine Stage | |
id: set_stage | |
run: | | |
if [[ "${GITHUB_REF}" == "refs/tags/deploy-dev" ]]; then | |
echo "STAGE=dev" >> $GITHUB_ENV | |
elif [[ "${GITHUB_REF}" == "refs/tags/deploy-prod" ]]; then | |
echo "STAGE=prod" >> $GITHUB_ENV | |
elif [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then | |
echo "STAGE=${{ github.event.inputs.stage }}" >> $GITHUB_ENV | |
else | |
echo "STAGE=dev" >> $GITHUB_ENV # fallback | |
fi | |
echo "π οΈ Deployment stage: $STAGE" | |
# Terraform Init & Workspace | |
- name: Terraform Init & Workspace | |
working-directory: ${{ env.TF_WORKING_DIR }} | |
run: | | |
terraform init | |
terraform workspace select ${STAGE} || terraform workspace new ${STAGE} | |
# Terraform Apply (Full Infra) | |
- name: Terraform Apply | |
working-directory: ${{ env.TF_WORKING_DIR }} | |
run: | | |
terraform apply -var-file="${STAGE}_config.tfvars" -auto-approve \ | |
-var "stage=${STAGE}" | |
# Get Outputs: App IP, Verifier IP, S3 Bucket | |
- name: Get Terraform Outputs | |
working-directory: ${{ env.TF_WORKING_DIR }} | |
run: | | |
INSTANCE_IP=$(terraform output -raw instance_public_ip) | |
S3_BUCKET=$(terraform output -raw s3_log_bucket) | |
echo "INSTANCE_IP=$INSTANCE_IP" >> $GITHUB_ENV | |
echo "S3_BUCKET=$S3_BUCKET" >> $GITHUB_ENV | |
echo "π¦ App IP: $INSTANCE_IP" | |
echo "πͺ£ S3 Bucket: $S3_BUCKET" | |
# Wait for App Initialization | |
- name: Wait for App Initialization | |
run: | | |
echo "β³ Waiting 90 seconds for app EC2 to initialize..." | |
sleep 90 | |
# Validate App Health | |
- name: Validate App Health | |
run: | | |
echo -e "\nπ¦ Full Response from App:\n" | |
curl -s http://${{ env.INSTANCE_IP }}:80 || echo "β Failed to get response" | |
echo -e "\n" | |
echo "Checking app health at http://${{ env.INSTANCE_IP }}:80" | |
for i in {1..10}; do | |
STATUS=$(curl -o /dev/null -s -w "%{http_code}" http://${{ env.INSTANCE_IP }}:80) | |
if [[ "$STATUS" == "200" ]]; then | |
echo "β App is healthy (HTTP 200)" | |
exit 0 | |
else | |
echo "Attempt $i: got HTTP $STATUS" | |
sleep 10 | |
fi | |
done | |
echo "β App failed health check" | |
exit 1 | |
# Provision Verifier EC2 | |
- name: Terraform Apply Verifier EC2 | |
working-directory: ${{ env.TF_WORKING_DIR }} | |
run: | | |
terraform apply -var-file="${STAGE}_config.tfvars" \ | |
-target=aws_instance.log_verifier -auto-approve \ | |
-var "stage=${STAGE}" | |
# Get Verifier IP | |
- name: Get Verifier IP | |
working-directory: ${{ env.TF_WORKING_DIR }} | |
run: | | |
VERIFIER_IP=$(terraform output -raw verifier_instance_public_ip) | |
echo "VERIFIER_IP=$VERIFIER_IP" >> $GITHUB_ENV | |
echo "π Verifier IP: $VERIFIER_IP" | |
# Setup SSH Key for EC2 Access | |
- name: Setup SSH Key for EC2 Access | |
uses: webfactory/[email protected] | |
with: | |
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} | |
# Wait for Verifier EC2 Initialization | |
- name: Wait for Verifier EC2 Initialization | |
run: | | |
echo "β³ Waiting 60 seconds for verifier EC2 to initialize..." | |
sleep 60 | |
# SSH into Verifier EC2 and Validate Logs | |
- name: Validate Logs from Verifier EC2 | |
run: | | |
echo "π Validating logs in S3 from verifier EC2" | |
# Retry SSH if EC2 not yet ready | |
for attempt in {1..5}; do | |
ssh -o StrictHostKeyChecking=no ubuntu@${VERIFIER_IP} "echo 'β SSH to verifier successful'" && break | |
echo "β³ Verifier not ready, retrying SSH (attempt $attempt)..." | |
sleep 15 | |
done | |
# Validate logs in S3 | |
for log in system/cloud-init.log app/my-app.log; do | |
ssh -o StrictHostKeyChecking=no ubuntu@${VERIFIER_IP} \ | |
"if aws s3 ls s3://${S3_BUCKET}/${STAGE}/$log > /dev/null 2>&1; then | |
echo 'β Found: $log'; | |
else | |
echo 'β Missing: $log'; exit 1; | |
fi" | |
done | |
echo "π All required logs are present in S3" | |
# Print Logs from Verifier EC2 | |
- name: Print Logs from Verifier EC2 | |
run: | | |
echo "π Fetching logs from /mylogs/${STAGE} on verifier EC2" | |
# Retry SSH if EC2 not yet ready | |
for attempt in {1..5}; do | |
ssh -o StrictHostKeyChecking=no ubuntu@${VERIFIER_IP} "echo 'β SSH to verifier successful for log fetch'" && break | |
echo "β³ Verifier not ready for log fetch, retrying SSH (attempt $attempt)..." | |
sleep 15 | |
done | |
# Print system log | |
ssh -o StrictHostKeyChecking=no ubuntu@${VERIFIER_IP} \ | |
"if [ -f /mylogs/${STAGE}/system/cloud-init.log ]; then | |
echo 'π ====== system/cloud-init.log ======' | |
cat /mylogs/${STAGE}/system/cloud-init.log | tail -n 20 | |
else | |
echo 'β system/cloud-init.log not found' | |
fi" | |
# Print app log | |
ssh -o StrictHostKeyChecking=no ubuntu@${VERIFIER_IP} \ | |
"if [ -f /mylogs/${STAGE}/app/my-app.log ]; then | |
echo 'π ====== app/my-app.log ======' | |
cat /mylogs/${STAGE}/app/my-app.log | tail -n 20 | |
else | |
echo 'β app/my-app.log not found' | |
fi" | |
echo "β Printed last 20 lines of logs from verifier EC2" | |
# # Verify Logs in S3 using AWS CLI | |
# - name: Verify Logs in S3 | |
# run: | | |
# echo "π¦ Checking for logs in S3 bucket: $S3_BUCKET" | |
# aws s3 ls s3://$S3_BUCKET/${STAGE}/system/cloud-init.log || { echo "β system logs missing"; exit 1; } | |
# aws s3 ls s3://$S3_BUCKET/${STAGE}/app/my-app.log || { echo "β app logs missing"; exit 1; } | |
# echo "β Logs found in S3 bucket" | |
# Destroy Infrastructure | |
- name: Destroy Infrastructure | |
if: always() | |
working-directory: ${{ env.TF_WORKING_DIR }} | |
run: | | |
echo "ποΈ Destroying infrastructure for stage: ${STAGE}" | |
terraform destroy -var-file="${STAGE}_config.tfvars" -auto-approve \ | |
-var "stage=${STAGE}" | |
# Cleanup Terraform Workspace | |
- name: Cleanup Terraform Workspace | |
if: always() | |
working-directory: ${{ env.TF_WORKING_DIR }} | |
run: | | |
terraform workspace select default | |
terraform workspace delete ${STAGE} |