Skip to content

Stage-Based Logs and Parameterized Multi-Stage Deployment with Secure Public/Private Config Management #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 213 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
name: EC2 Deploy

on:
push:
branches:
- devops/a4
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"

# Clone private repo for prod config
- name: Clone Private Repo for Prod Config
if: env.STAGE == 'prod'
run: |
echo "🔒 Cloning private repo for prod configuration..."
git clone https://${{ secrets.PRIVATE_REPO_KEY }}@${{ secrets.PRIVATE_REPO }} private-config
echo "✅ Cloned private config repo"

# Terraform Init
- name: Terraform Init
working-directory: ${{ env.TF_WORKING_DIR }}
run: terraform init

# Terraform Apply (Full Infra)
- name: Terraform Apply
working-directory: ${{ env.TF_WORKING_DIR }}
run: |
if [ "${STAGE}" == "prod" ]; then
echo "Applying Terraform with private prod configuration..."
terraform apply -var-file=../private-config/prod_config.tfvars -auto-approve
else
echo "Applying Terraform with public dev configuration..."
terraform apply -var-file="${STAGE}_config.tfvars" -auto-approve
fi

# 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

# 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/ssh-agent@v0.8.0
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"

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

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"

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

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"

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"

# Destroy Infrastructure
- name: Destroy Infrastructure
if: always()
working-directory: ${{ env.TF_WORKING_DIR }}
run: |
echo "🗑️ Destroying infrastructure for stage: ${STAGE}"
if [ "${STAGE}" == "prod" ]; then
terraform destroy -var-file=../private-config/prod_config.tfvars -auto-approve
else
terraform destroy -var-file="${STAGE}_config.tfvars" -auto-approve
fi
Loading