88 lines
3.4 KiB
YAML
88 lines
3.4 KiB
YAML
name: Deploy to Production
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
|
|
jobs:
|
|
deploy:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout code
|
|
run: |
|
|
git clone "http://172.17.0.1:3000/${{ github.repository }}.git" .
|
|
git checkout "${{ github.sha }}"
|
|
|
|
- name: Create .env.production from secrets
|
|
run: |
|
|
cat > .env.production << 'ENVEOF'
|
|
DOMAIN=${{ secrets.DOMAIN }}
|
|
BACKEND_HOST=${{ secrets.BACKEND_HOST }}
|
|
FRONTEND_HOST=${{ secrets.FRONTEND_HOST }}
|
|
ENVIRONMENT=production
|
|
PROJECT_NAME=${{ secrets.PROJECT_NAME }}
|
|
STACK_NAME=${{ secrets.STACK_NAME }}
|
|
BACKEND_CORS_ORIGINS=${{ secrets.BACKEND_CORS_ORIGINS }}
|
|
SECRET_KEY=${{ secrets.SECRET_KEY }}
|
|
FIRST_SUPERUSER=${{ secrets.FIRST_SUPERUSER }}
|
|
FIRST_SUPERUSER_PASSWORD=${{ secrets.FIRST_SUPERUSER_PASSWORD }}
|
|
SMTP_HOST=${{ secrets.SMTP_HOST }}
|
|
SMTP_USER=${{ secrets.SMTP_USER }}
|
|
SMTP_PASSWORD=${{ secrets.SMTP_PASSWORD }}
|
|
EMAILS_FROM_EMAIL=${{ secrets.EMAILS_FROM_EMAIL }}
|
|
SMTP_TLS=${{ secrets.SMTP_TLS }}
|
|
SMTP_SSL=${{ secrets.SMTP_SSL }}
|
|
SMTP_PORT=${{ secrets.SMTP_PORT }}
|
|
POSTGRES_SERVER=${{ secrets.POSTGRES_SERVER }}
|
|
POSTGRES_PORT=${{ secrets.POSTGRES_PORT }}
|
|
POSTGRES_DB=${{ secrets.POSTGRES_DB }}
|
|
POSTGRES_USER=${{ secrets.POSTGRES_USER }}
|
|
POSTGRES_PASSWORD=${{ secrets.POSTGRES_PASSWORD }}
|
|
SENTRY_DSN=${{ secrets.SENTRY_DSN }}
|
|
DOCKER_IMAGE_BACKEND=${{ secrets.DOCKER_IMAGE_BACKEND }}
|
|
DOCKER_IMAGE_FRONTEND=${{ secrets.DOCKER_IMAGE_FRONTEND }}
|
|
ENVEOF
|
|
|
|
# Fallback defaults if image name secrets are empty
|
|
sed -i 's/^DOCKER_IMAGE_BACKEND=$/DOCKER_IMAGE_BACKEND=backend/' .env.production
|
|
sed -i 's/^DOCKER_IMAGE_FRONTEND=$/DOCKER_IMAGE_FRONTEND=frontend/' .env.production
|
|
|
|
- name: Build Docker images
|
|
run: docker compose --env-file .env.production -f compose.prod.yml build
|
|
|
|
- name: Stop existing services
|
|
run: docker compose --env-file .env.production -f compose.prod.yml down --remove-orphans || true
|
|
|
|
- name: Start services
|
|
run: docker compose --env-file .env.production -f compose.prod.yml up -d
|
|
|
|
- name: Wait for backend health check
|
|
run: |
|
|
echo "Waiting for backend container health=healthy..."
|
|
for i in $(seq 1 30); do
|
|
status=$(docker inspect -f '{{.State.Health.Status}}' full-stack-fastapi-backend-1 2>/dev/null || echo "unknown")
|
|
if [ "$status" = "healthy" ]; then
|
|
echo "✅ Backend is healthy!"
|
|
exit 0
|
|
fi
|
|
echo "Attempt $i/30 - status=$status, waiting 10s..."
|
|
sleep 10
|
|
done
|
|
echo "❌ Backend health check failed after 300s"
|
|
docker compose --env-file .env.production -f compose.prod.yml logs backend
|
|
exit 1
|
|
|
|
- name: Verify frontend
|
|
run: |
|
|
if docker compose --env-file .env.production -f compose.prod.yml ps frontend --status running | grep -q frontend; then
|
|
echo "✅ Frontend is accessible!"
|
|
else
|
|
echo "❌ Frontend is not accessible"
|
|
docker compose --env-file .env.production -f compose.prod.yml logs frontend
|
|
exit 1
|
|
fi
|
|
|
|
- name: Cleanup old Docker images
|
|
run: docker image prune -f || true
|