name: Deploy to Production on: push: branches: [ main ] jobs: deploy: name: Deploy to Server runs-on: ubuntu-latest steps: - name: Write secrets and deploy uses: appleboy/ssh-action@v1.1.0 with: host: ${{ secrets.SERVER_HOST }} username: ${{ secrets.SERVER_USER }} key: ${{ secrets.SSH_PRIVATE_KEY }} envs: STRIPE_SECRET_KEY,STRIPE_WEBHOOK_SECRET,DATABASE_PASSWORD script: | set -e echo "๐Ÿš€ Starting deployment..." cd /root/docfast # Write .env from CI secrets echo "๐Ÿ“ Writing .env from CI secrets..." printf "STRIPE_SECRET_KEY=%s\nSTRIPE_WEBHOOK_SECRET=%s\nDATABASE_PASSWORD=%s\n" "$STRIPE_SECRET_KEY" "$STRIPE_WEBHOOK_SECRET" "$DATABASE_PASSWORD" > .env # Verify .env has non-empty values if grep -q '=$' .env; then echo "โŒ ERROR: .env has empty values - secrets not configured in Forgejo!" echo "Add STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, DATABASE_PASSWORD in Forgejo repo settings." exit 1 fi echo "โœ… .env written with $(wc -l < .env) vars" git status --short || true echo "๐Ÿ“ฅ Pulling latest changes..." git fetch origin git pull origin main TIMESTAMP=$(date +%Y%m%d-%H%M%S) docker tag docfast-docfast:latest docfast-docfast:rollback-$TIMESTAMP || echo "No existing image to tag" echo "๐Ÿ”จ Building new Docker image..." docker compose build --no-cache echo "โน๏ธ Stopping services..." docker compose down --timeout 30 echo "โ–ถ๏ธ Starting services..." docker compose up -d echo "โฑ๏ธ Waiting for service to be ready..." for i in $(seq 1 30); do if curl -f -s http://127.0.0.1:3100/health > /dev/null; then echo "โœ… Service is healthy!" break fi if [ $i -eq 30 ]; then echo "โŒ Service failed to start - initiating rollback..." docker compose down ROLLBACK_IMAGE=$(docker images --format "table {{.Repository}}:{{.Tag}}" | grep "docfast-docfast:rollback-" | head -n1 | tr -s ' ' | cut -d' ' -f1) if [ ! -z "$ROLLBACK_IMAGE" ]; then echo "๐Ÿ”„ Rolling back to $ROLLBACK_IMAGE" docker tag $ROLLBACK_IMAGE docfast-docfast:latest docker compose up -d sleep 10 if curl -f -s http://127.0.0.1:3100/health > /dev/null; then echo "โœ… Rollback successful" else echo "โŒ Rollback failed - manual intervention required" fi fi exit 1 fi echo "โณ Attempt $i/30 - waiting 5 seconds..." sleep 5 done echo "๐Ÿ” Running post-deploy verification..." bash scripts/verify-deploy.sh echo "๐Ÿงน Cleaning up old rollback images..." docker images --format "table {{.Repository}}:{{.Tag}}" | grep "docfast-docfast:rollback-" | tail -n +6 | awk '{print $1}' | xargs -r docker rmi || true echo "๐ŸŽ‰ Deployment completed successfully!" env: STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }} STRIPE_WEBHOOK_SECRET: ${{ secrets.STRIPE_WEBHOOK_SECRET }} DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}