Skip to content

chore: Remove outdated documentation files for EC2 setup, Docker setu… #136

chore: Remove outdated documentation files for EC2 setup, Docker setu…

chore: Remove outdated documentation files for EC2 setup, Docker setu… #136

Workflow file for this run

name: Deploy to Production
on:
push:
branches: [main, devOps] # Added devOps branch
workflow_dispatch:
env:
AWS_REGION: ap-southeast-1
ECR_FRONTEND: ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.us-east-1.amazonaws.com/myblog/frontend
ECR_BACKEND: ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.us-east-1.amazonaws.com/myblog/backend
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
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: us-east-1
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
# --- ADDED STEP ---
# This step ensures the AWS CLI is installed and available.
# It handles the case where it might already be present.
- name: Ensure AWS CLI is installed and in PATH
run: |
if ! command -v aws &> /dev/null; then
echo "AWS CLI not found, installing..."
curl -sL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
else
echo "AWS CLI is already installed."
# If already installed, ensure the path is correct for this step's shell
export PATH="/usr/local/aws-cli/v2/current/bin:$PATH"
fi
aws --version # Verify installation and availability in this step
# --- END OF ADDED STEP ---
- name: Build and push backend image
run: |
docker build -f apps/backend/Dockerfile -t $ECR_BACKEND:$GITHUB_SHA .
docker tag $ECR_BACKEND:$GITHUB_SHA $ECR_BACKEND:latest
docker push $ECR_BACKEND:$GITHUB_SHA
docker push $ECR_BACKEND:latest
- name: Build and push frontend image
run: |
docker build -f apps/frontend/Dockerfile \
--build-arg NEXT_PUBLIC_BACKEND_BASE_URL=https://${{ secrets.DOMAIN_NAME }} \
--build-arg NEXT_PUBLIC_GOOGLE_CLIENT_ID=${{ secrets.GOOGLE_CLIENT_ID }} \
--build-arg NEXT_PUBLIC_TINYMCE_API_KEY=${{ secrets.TINYMCE_API_KEY }} \
--build-arg NEXT_PUBLIC_PROFILE_IMAGE_URL=${{ vars.PROFILE_IMAGE_URL }} \
--build-arg NEXT_PUBLIC_CONTACT_WHATSAPP=${{ vars.CONTACT_WHATSAPP }} \
--build-arg NEXT_PUBLIC_CONTACT_GITHUB=${{ vars.CONTACT_GITHUB }} \
--build-arg NEXT_PUBLIC_CONTACT_LINKEDIN=${{ vars.CONTACT_LINKEDIN }} \
--build-arg NEXT_PUBLIC_CONTACT_FIVERR=${{ vars.CONTACT_FIVERR }} \
--build-arg NEXT_PUBLIC_CONTACT_EMAIL=${{ vars.CONTACT_EMAIL }} \
-t $ECR_FRONTEND:$GITHUB_SHA .
docker tag $ECR_FRONTEND:$GITHUB_SHA $ECR_FRONTEND:latest
docker push $ECR_FRONTEND:$GITHUB_SHA
docker push $ECR_FRONTEND:latest
- name: Deploy to EC2 via SSM
run: |
aws ssm send-command \
--instance-ids ${{ secrets.EC2_INSTANCE_ID }} \
--document-name "AWS-RunShellScript" \
--parameters commands="[
\"set -e\",
\"echo '========================================'\",
\"echo 'Starting deployment at \$(date)...'\",
\"echo '========================================'\",
\"cd /home/ubuntu\",
\"echo '[1/10] Installing AWS CLI...'\",
\"sudo apt-get update -qq\",
\"sudo apt-get install -y snapd > /dev/null 2>&1\",
\"sudo snap install aws-cli --classic > /dev/null 2>&1\",
\"export PATH=/snap/bin:\$PATH\",
\"echo '[2/10] Checking disk space...'\",
\"DISK_USAGE=\$(df / | awk 'NR==2 {print \$5}' | sed 's/%//')\",
\"echo 'Current disk usage: \${DISK_USAGE}%'\",
\"echo '[3/10] Cleaning up system resources...'\",
\"sudo apt-get autoremove -y > /dev/null 2>&1\",
\"sudo apt-get autoclean -y > /dev/null 2>&1\",
\"sudo rm -rf /var/lib/apt/lists/* > /dev/null 2>&1\",
\"docker system prune -af > /dev/null 2>&1\",
\"docker volume prune -f > /dev/null 2>&1\",
\"echo '[4/10] Cloning repository...'\",
\"sudo rm -rf MyBlog\",
\"git clone https://oauth2:${{ secrets.DEPLOY_TOKEN }}@github.com/BlockAce01/MyBlog.git MyBlog\",
\"cd MyBlog\",
\"echo '[5/10] Setting up environment variables...'\",
\"cat > .env << EOF\",
\"TZ=Asia/Colombo\",
\"NODE_ENV=production\",
\"AWS_ACCOUNT_ID=${{ secrets.AWS_ACCOUNT_ID }}\",
\"MONGODB_URI=${{ secrets.MONGODB_URI }}\",
\"JWT_SECRET=${{ secrets.JWT_SECRET }}\",
\"GOOGLE_CLIENT_ID=${{ secrets.GOOGLE_CLIENT_ID }}\",
\"GOOGLE_CLIENT_SECRET=${{ secrets.GOOGLE_CLIENT_SECRET }}\",
\"ADMIN_API_KEY=${{ secrets.ADMIN_API_KEY }}\",
\"ADMIN_SETUP_TOKEN=${{ secrets.ADMIN_SETUP_TOKEN }}\",
\"NEXTAUTH_SECRET=${{ secrets.NEXTAUTH_SECRET }}\",
\"NEXT_PUBLIC_TINYMCE_API_KEY=${{ secrets.TINYMCE_API_KEY }}\",
\"PROD_URL=${{ secrets.PROD_URL }}\",
\"ALLOWED_KEYGEN_HOUR=${{ secrets.ALLOWED_KEYGEN_HOUR }}\",
\"ALLOWED_KEYGEN_MINUTE_START=${{ secrets.ALLOWED_KEYGEN_MINUTE_START }}\",
\"ALLOWED_KEYGEN_MINUTE_END=${{ secrets.ALLOWED_KEYGEN_MINUTE_END }}\",
\"EOF\",
\"export \$(cat .env | xargs)\",
\"aws configure set aws_access_key_id ${{ secrets.AWS_ACCESS_KEY_ID }}\",
\"aws configure set aws_secret_access_key ${{ secrets.AWS_SECRET_ACCESS_KEY }}\",
\"aws configure set region us-east-1\",
\"echo '[6/10] Authenticating with ECR...'\",
\"aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.us-east-1.amazonaws.com\",
\"echo '[7/10] Removing old cached images and pulling latest...'\",
\"docker rmi -f ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.us-east-1.amazonaws.com/myblog/frontend:latest 2>/dev/null || true\",
\"docker rmi -f ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.us-east-1.amazonaws.com/myblog/backend:latest 2>/dev/null || true\",
\"docker pull ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.us-east-1.amazonaws.com/myblog/frontend:latest\",
\"docker pull ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.us-east-1.amazonaws.com/myblog/backend:latest\",
\"echo '[8/10] Setting up systemd auto-restart service...'\",
\"if [ ! -f /etc/systemd/system/myblog.service ]; then\",
\" echo 'Installing systemd service for auto-restart on reboot...'\",
\" sudo cp scripts/myblog.service /etc/systemd/system/myblog.service\",
\" sudo chmod 644 /etc/systemd/system/myblog.service\",
\" sudo systemctl daemon-reload\",
\" sudo systemctl enable myblog.service\",
\" echo '✅ Systemd service installed - containers will auto-start on reboot'\",
\"else\",
\" echo '✅ Systemd service already configured'\",
\"fi\",
\"echo '[9/10] Setting up automatic cleanup...'\",
\"if ! crontab -l 2>/dev/null | grep -q 'cleanup-docker'; then\",
\" echo 'Configuring automatic cleanup cron jobs...'\",
\" sudo mkdir -p /var/log/myblog\",
\" sudo chown ubuntu:ubuntu /var/log/myblog\",
\" sudo chmod +x scripts/*.sh\",
\" sudo bash -c 'cat > /etc/docker/daemon.json << DOCKEREOF\",
\"{\",
\" \\\"log-driver\\\": \\\"json-file\\\",\",
\" \\\"log-opts\\\": {\",
\" \\\"max-size\\\": \\\"10m\\\",\",
\" \\\"max-file\\\": \\\"3\\\"\",
\" }\",
\"}\",
\"DOCKEREOF'\",
\" sudo systemctl restart docker\",
\" sleep 3\",
\" crontab -l 2>/dev/null > /tmp/crontab.backup || true\",
\" cat > /tmp/new_crontab << CRONEOF\",
\"# MyBlog Automatic Maintenance\",
\"0 2 * * * /home/ubuntu/MyBlog/scripts/cleanup-docker.sh >> /var/log/myblog/cleanup.log 2>&1\",
\"0 */12 * * * /home/ubuntu/MyBlog/scripts/cleanup-docker.sh >> /var/log/myblog/cleanup.log 2>&1\",
\"0 */4 * * * DISK_USAGE=\\\$(df / | awk 'NR==2 {print \\\$5}' | sed 's/%//') && [ \\\"\\\$DISK_USAGE\\\" -gt 80 ] && /home/ubuntu/MyBlog/scripts/cleanup-storage.sh >> /var/log/myblog/storage-cleanup.log 2>&1\",
\"*/5 * * * * curl -sf http://localhost:3000/api/health > /dev/null || echo \\\"[\\\$(date)] Frontend health check failed\\\" >> /var/log/myblog/health.log\",
\"*/5 * * * * curl -sf http://localhost:3003/health > /dev/null || echo \\\"[\\\$(date)] Backend health check failed\\\" >> /var/log/myblog/health.log\",
\"0 0 * * 0 find /var/log/myblog -name '*.log' -type f -mtime +7 -delete 2>/dev/null\",
\"CRONEOF\",
\" crontab /tmp/new_crontab\",
\" echo '✅ Automatic cleanup configured'\",
\"else\",
\" echo '✅ Cleanup cron jobs already configured'\",
\"fi\",
\"echo '[10/10] Deploying containers...'\",
\"docker compose -f docker-compose.prod.yml down 2>/dev/null || true\",
\"docker compose -f docker-compose.prod.yml up -d --pull always\",
\"echo 'Waiting for services to be ready...'\",
\"sleep 15\",
\"echo 'Running health checks...'\",
\"RETRY_COUNT=0\",
\"MAX_RETRIES=10\",
\"while [ \$RETRY_COUNT -lt \$MAX_RETRIES ]; do\",
\" if curl -sf --connect-timeout 5 http://localhost:3000/api/health > /dev/null 2>&1 && curl -sf --connect-timeout 5 http://localhost:3003/health > /dev/null 2>&1; then\",
\" echo '✅ All services are healthy'\",
\" break\",
\" fi\",
\" RETRY_COUNT=\$((RETRY_COUNT+1))\",
\" if [ \$RETRY_COUNT -lt \$MAX_RETRIES ]; then\",
\" echo 'Waiting for services... (attempt \$RETRY_COUNT/\$MAX_RETRIES)'\",
\" sleep 5\",
\" fi\",
\"done\",
\"if [ \$RETRY_COUNT -ge \$MAX_RETRIES ]; then\",
\" echo '❌ Health checks failed - checking logs'\",
\" docker logs myblog-frontend --tail 20\",
\" docker logs myblog-backend --tail 20\",
\" exit 1\",
\"fi\",
\"echo '========================================'\",
\"echo '🎉 Deployment completed successfully!'\",
\"echo 'Time: \$(date)'\",
\"echo '========================================'\",
\"docker ps --format 'table {{.Names}}\\\\t{{.Status}}\\\\t{{.Size}}'\",
\"echo '========================================'\",
\"docker system df\"
]" \
--region ap-southeast-1