Skip to content

feat: entrypoint.sh dosyasındaki izin kontrolü güncellendi; dosya sis… #136

feat: entrypoint.sh dosyasındaki izin kontrolü güncellendi; dosya sis…

feat: entrypoint.sh dosyasındaki izin kontrolü güncellendi; dosya sis… #136

name: Notification Service CI/CD
on:
push:
branches: [master]
paths:
- "notification-service/**"
- "pom.xml"
- ".github/workflows/notification-service-ci-cd.yml"
workflow_dispatch:
jobs:
build-and-deploy:
runs-on: self-hosted
defaults:
run:
working-directory: ./notification-service
steps:
- uses: actions/checkout@v3
- id: "auth"
name: "Authenticate to Google Cloud"
uses: "google-github-actions/auth@v1"
with:
credentials_json: "${{ secrets.GCP_SA_KEY }}"
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: "21"
distribution: "temurin"
- name: Cache Maven packages
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Grant execute permission for mvnw
run: chmod +x mvnw
- name: Build
run: ./mvnw clean package -DskipTests
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
with:
platforms: arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
with:
platforms: linux/arm64
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
logout: true
- name: Build and Push Docker image
uses: docker/build-push-action@v4
with:
context: ./notification-service # Değiştirildi
file: ./notification-service/Dockerfile
platforms: linux/arm64
push: true
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/notification-service:latest-arm64
${{ secrets.DOCKERHUB_USERNAME }}/notification-service:${{ github.sha }}-arm64
cache-from: type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/notification-service:buildcache-arm64
cache-to: type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/notification-service:buildcache-arm64,mode=max
- name: Deploy to VPS
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
echo "Starting deployment process..."
# Debug mode enabled
set -x
echo "Checking Docker service status..."
systemctl status docker || true
# Infrastructure containers
docker network create craftpilot-network || true
# MongoDB container check
MONGODB_CONTAINER="craftpilot-mongodb"
if ! docker ps | grep -q "$MONGODB_CONTAINER"; then
echo "WARNING: Default MongoDB container not found ($MONGODB_CONTAINER)"
# Try to detect any MongoDB container as fallback
MONGODB_CONTAINER=$(docker ps --format '{{.Names}}' | grep -E 'mongo|mongodb' | head -n 1)
if [ -z "$MONGODB_CONTAINER" ]; then
echo "ERROR: No MongoDB container found! Using default name, but connection may fail."
MONGODB_CONTAINER="craftpilot-mongodb" # Fallback to default
else
echo "Found alternative MongoDB container: $MONGODB_CONTAINER"
fi
fi
echo "Using MongoDB container: $MONGODB_CONTAINER"
# Test MongoDB connection before deployment
echo "Testing MongoDB connection..."
if docker run --rm --network craftpilot-network mongo:6.0 mongosh --quiet --eval "db.runCommand({ping:1}).ok" admin --host $MONGODB_CONTAINER --port 27017 -u ${{ secrets.MONGO_ROOT_USERNAME }} -p ${{ secrets.MONGO_ROOT_PASSWORD }} --authenticationDatabase admin | grep -q "1"; then
echo "✅ MongoDB connection test successful!"
else
echo "⚠️ MongoDB connection test failed! Deployment will continue but may have issues."
echo "Checking MongoDB container status:"
docker ps | grep -i $MONGODB_CONTAINER || echo "Container not found!"
fi
echo "Checking existing containers..."
docker ps -a | grep notification-service || true
echo "Stopping and removing existing container..."
docker stop notification-service || true
docker rm notification-service || true
echo "Setting up directories and permissions..."
mkdir -p /opt/craftpilot/config/notification-service
mkdir -p /craftpilot
echo "Creating Firebase credentials..."
# Standardize credentials path to /craftpilot/gcp-credentials.json
echo '${{ secrets.GCP_SA_KEY }}' > /craftpilot/gcp-credentials.json
chmod 644 /craftpilot/gcp-credentials.json
ls -la /craftpilot/gcp-credentials.json
# Also keep existing path for backward compatibility
echo '${{ secrets.GCP_SA_KEY }}' > /opt/craftpilot/config/notification-service/firebase-service-account.json
chmod 644 /opt/craftpilot/config/notification-service/firebase-service-account.json
ls -la /opt/craftpilot/config/notification-service/firebase-service-account.json
echo "#!/bin/sh
curl -f http://localhost:8053/actuator/health || exit 1" > /opt/craftpilot/config/notification-service/healthcheck.sh
chmod +x /opt/craftpilot/config/notification-service/healthcheck.sh
# Create function definition in a variable to avoid semicolon issues
FUNCTION_DEF="notificationEventConsumer;notificationEventProducer"
# Setup networking config
echo "Setting up networking config..."
cat > /opt/craftpilot/config/notification-service/grpc-netty.properties << EOF
io.netty.handler.ssl.openssl.useKeyManagerFactory=true
EOF
# Build MongoDB URI with the correct container name
if [ -n "${{ secrets.MONGODB_URI }}" ]; then
# Parse the URI and replace the hostname with our container name
URI_PREFIX=$(echo "${{ secrets.MONGODB_URI }}" | grep -oP 'mongodb://[^@]+@')
URI_SUFFIX=$(echo "$URI_PREFIX" | grep -oP '(?<=@)[^/]+/.*')
URI_HOST=$(echo "$URI_SUFFIX" | grep -oP '^[^:/]+')
URI_REMAINDER=$(echo "$URI_SUFFIX" | grep -oP '(?<='"$URI_HOST"')[:/].*')
MONGODB_URI="${URI_PREFIX}${MONGODB_CONTAINER}${URI_REMAINDER}"
echo "Modified MongoDB URI with correct container name: $(echo $MONGODB_URI | sed 's/:[^:]*@/:*****@/g')"
else
MONGODB_URI="mongodb://${{ secrets.MONGO_ROOT_USERNAME }}:${{ secrets.MONGO_ROOT_PASSWORD }}@${MONGODB_CONTAINER}:27017/craftpilot_notification_db?authSource=admin&retryWrites=true&w=majority&serverSelectionTimeoutMS=60000"
echo "Built MongoDB URI from credential components: $(echo $MONGODB_URI | sed 's/:[^:]*@/:*****@/g')"
fi
echo "Starting container..."
docker run -d \
--name notification-service \
--network craftpilot-network \
--restart unless-stopped \
--memory="1g" \
--memory-swap="2g" \
--memory-reservation="512m" \
--cpus="1.0" \
-p 8053:8053 \
-v /opt/craftpilot/config/notification-service:/app/config:ro \
-v "/opt/craftpilot/config/notification-service/firebase-service-account.json:/app/credentials/firebase-credentials.json:ro" \
-v "/craftpilot/gcp-credentials.json:/app/gcp-credentials.json:ro" \
-v "/opt/craftpilot/config/notification-service/grpc-netty.properties:/app/config/grpc-netty.properties:ro" \
-v "/opt/craftpilot/config/notification-service/healthcheck.sh:/app/healthcheck.sh:ro" \
-e FIREBASE_CONFIG=/app/credentials/firebase-credentials.json \
-e GOOGLE_APPLICATION_CREDENTIALS=/app/gcp-credentials.json \
-e SPRING_PROFILES_ACTIVE=prod \
-e SERVER_PORT=8053 \
-e KAFKA_BOOTSTRAP_SERVERS=kafka:9092 \
-e SPRING_KAFKA_BOOTSTRAP_SERVERS=kafka:9092 \
-e SPRING_CLOUD_STREAM_KAFKA_BINDER_BROKERS=kafka:9092 \
-e SPRING_CLOUD_STREAM_DEFAULT_BINDER=kafka \
-e "SPRING_CLOUD_FUNCTION_DEFINITION=${FUNCTION_DEF}" \
-e SPRING_CLOUD_STREAM_BINDINGS_PROCESSNOTIFICATION_IN_0_DESTINATION=notifications \
-e SPRING_CLOUD_STREAM_BINDINGS_PROCESSNOTIFICATION_IN_0_GROUP=notification-service-group \
-e SPRING_CLOUD_STREAM_BINDINGS_PROCESSNOTIFICATION_OUT_0_DESTINATION=notifications \
-e REDIS_HOST=redis \
-e REDIS_PORT=6379 \
-e REDIS_PASSWORD=13579ada \
-e SPRING_DATA_REDIS_HOST=redis \
-e SPRING_DATA_REDIS_PORT=6379 \
-e SPRING_DATA_REDIS_PASSWORD=13579ada \
-e MONGODB_URI="${MONGODB_URI}" \
-e SPRING_DATA_MONGODB_URI="${MONGODB_URI}" \
-e SPRING_DATA_MONGODB_DATABASE=craftpilot_notification_db \
-e EUREKA_CLIENT_SERVICEURL_DEFAULTZONE=http://craftpilot:13579ada@eureka-server:8761/eureka/ \
-e SPRING_MAIL_SENDGRID_FROM='${{ secrets.SENDGRID_FROM_EMAIL }}' \
-e SPRING_MAIL_HOST=smtp.sendgrid.net \
-e SPRING_MAIL_PORT=587 \
-e SPRING_MAIL_USERNAME=apikey \
-e SPRING_MAIL_PASSWORD='${{ secrets.SENDGRID_API_KEY }}' \
-e MANAGEMENT_HEALTH_MAIL_ENABLED=false \
-e SPRING_MAIL_ENABLED=false \
-e SPRING_SENDGRID_API_KEY='${{ secrets.SENDGRID_API_KEY }}' \
-e SPRING_SENDGRID_ENABLED=true \
--dns 8.8.8.8 \
--dns 8.8.4.4 \
--health-cmd="/healthcheck.sh" \
--health-interval=30s \
--health-timeout=10s \
--health-retries=5 \
--health-start-period=180s \
${{ secrets.DOCKERHUB_USERNAME }}/notification-service:latest-arm64
echo "Waiting for container to start..."
sleep 30
echo "Performing enhanced health checks..."
# Install jq if not present for proper JSON parsing
if ! command -v jq &> /dev/null; then
apt-get update && apt-get install -y jq || echo "Could not install jq, will use alternatives"
fi
# Enhanced health check with component verification
for i in {1..20}; do
if ! docker ps | grep -q "notification-service"; then
echo "❌ Container stopped unexpectedly!"
docker logs notification-service || echo "No logs available"
exit 1
fi
# Try health check with better parsing
HEALTH_CHECK=$(curl -s http://localhost:8053/actuator/health || echo "{}")
# Check if overall service is UP
if echo "$HEALTH_CHECK" | grep -q '"status":"UP"'; then
echo "✅ Service reports overall status as UP!"
# Try to parse with jq if available
if command -v jq &> /dev/null; then
MONGO_STATUS=$(echo "$HEALTH_CHECK" | jq -r '.components.mongodb.status' 2>/dev/null || echo "UNKNOWN")
REDIS_STATUS=$(echo "$HEALTH_CHECK" | jq -r '.components.redis.status' 2>/dev/null || echo "UNKNOWN")
if [ "$MONGO_STATUS" = "UP" ] && [ "$REDIS_STATUS" = "UP" ]; then
echo "✅ All critical components are healthy!"
echo "Deployment completed successfully!"
docker logs notification-service --tail 20
exit 0
else
echo "⚠️ Service is UP but component statuses - MongoDB: $MONGO_STATUS, Redis: $REDIS_STATUS"
fi
elif echo "$HEALTH_CHECK" | grep -q '"mongodb":{.*"status":"UP"' && echo "$HEALTH_CHECK" | grep -q '"redis":{.*"status":"UP"'; then
echo "✅ All critical components are healthy based on string search!"
echo "Deployment completed successfully!"
docker logs notification-service --tail 20
exit 0
fi
# If we've been UP for several checks, assume success
if [ $i -ge 10 ]; then
echo "✅ Service has been reporting UP status for multiple checks"
echo "Assuming deployment is successful"
docker logs notification-service --tail 20
exit 0
fi
fi
echo "Health check attempt $i/20 - service not ready yet or components not healthy"
# Enhanced diagnostics on certain iterations
if [ $i -eq 5 ] || [ $i -eq 10 ] || [ $i -eq 15 ]; then
echo "--- Connection Diagnostics ---"
echo "MongoDB container status:"
docker ps | grep $MONGODB_CONTAINER || echo "MongoDB container not running!"
echo "Redis container status:"
docker ps | grep redis || echo "Redis container not running!"
echo "Testing network connectivity:"
docker exec notification-service nc -zv $MONGODB_CONTAINER 27017 || echo "Cannot connect to MongoDB"
docker exec notification-service nc -zv redis 6379 || echo "Cannot connect to Redis"
echo "Container environment variables:"
docker exec notification-service env | grep -E 'MONGO|REDIS|SENDGRID' || echo "No relevant env vars found"
echo "Network details:"
docker network inspect craftpilot-network | grep -A 5 -E "$MONGODB_CONTAINER|redis|notification-service" || echo "Network inspection failed"
fi
sleep 15
done
echo "❌ Service failed to become fully healthy within timeout period."
echo "Final container logs:"
docker logs notification-service --tail 50
echo "Container is still running for debugging purposes."
# Testing external connectivity
echo "Testing SendGrid API connectivity..."
docker exec notification-service curl -v https://api.sendgrid.com/v3/mail/send -H "Authorization: Bearer $SENDGRID_API_KEY" || echo "SendGrid connection failed"
exit 1
# Disable debug mode
set +x