Skip to content

Commit 5e53d23

Browse files
committed
update
1 parent 8235dae commit 5e53d23

File tree

7 files changed

+190
-1
lines changed

7 files changed

+190
-1
lines changed

Dockerfile

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Use Python 3.11 runtime as base image
2+
FROM python:3.11-slim
3+
4+
# Set working directory
5+
WORKDIR /app
6+
7+
# Copy requirements and install dependencies
8+
COPY requirements.txt .
9+
RUN pip install --no-cache-dir -r requirements.txt
10+
11+
# Copy the application code
12+
COPY . .
13+
14+
# Expose port 8080 for Cloud Run
15+
EXPOSE 8080
16+
17+
# Option 1: Use uvicorn directly (simpler)
18+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
19+
20+
# Option 2: Use gunicorn with uvicorn workers (production-ready)
21+
# CMD ["gunicorn", "--config", "gunicorn.conf.py", "main:app"]

cloudrun.yaml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# apiVersion: serving.knative.dev/v1
2+
# kind: Service
3+
# metadata:
4+
# name: whatsapp-bot
5+
# annotations:
6+
# run.googleapis.com/ingress: all
7+
# spec:
8+
# template:
9+
# metadata:
10+
# annotations:
11+
# run.googleapis.com/cpu-throttling: "false"
12+
# run.googleapis.com/memory: "1Gi"
13+
# run.googleapis.com/cpu: "1"
14+
# run.googleapis.com/execution-environment: gen2
15+
# run.googleapis.com/startup-cpu-boost: "true"
16+
# spec:
17+
# containerConcurrency: 1000
18+
# timeoutSeconds: 300
19+
# containers:
20+
# - image: gcr.io/PROJECT_ID/whatsapp-bot
21+
# ports:
22+
# - containerPort: 8080
23+
# env:
24+
# - name: PORT
25+
# value: "8080"
26+
# resources:
27+
# limits:
28+
# cpu: 1000m
29+
# memory: 1Gi
30+
# startupProbe:
31+
# httpGet:
32+
# path: /health
33+
# port: 8080
34+
# initialDelaySeconds: 10
35+
# timeoutSeconds: 5
36+
# periodSeconds: 5
37+
# failureThreshold: 3
38+
# livenessProbe:
39+
# httpGet:
40+
# path: /health
41+
# port: 8080
42+
# initialDelaySeconds: 30
43+
# timeoutSeconds: 5
44+
# periodSeconds: 10
45+
# failureThreshold: 3

deploy.sh

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/bin/bash
2+
3+
# Deployment script for WhatsApp Bot on Google Cloud Run
4+
5+
set -e
6+
7+
# Configuration
8+
PROJECT_ID=${PROJECT_ID:-"your-project-id"}
9+
REGION=${REGION:-"us-central1"}
10+
SERVICE_NAME=${SERVICE_NAME:-"whatsapp-bot"}
11+
IMAGE_NAME="gcr.io/${PROJECT_ID}/${SERVICE_NAME}"
12+
13+
echo "🚀 Deploying WhatsApp Bot to Google Cloud Run..."
14+
echo "Project ID: ${PROJECT_ID}"
15+
echo "Region: ${REGION}"
16+
echo "Service Name: ${SERVICE_NAME}"
17+
18+
# Build and push the Docker image
19+
echo "📦 Building Docker image..."
20+
docker build -t ${IMAGE_NAME} .
21+
22+
echo "📤 Pushing image to Google Container Registry..."
23+
docker push ${IMAGE_NAME}
24+
25+
# Deploy to Cloud Run
26+
echo "🚀 Deploying to Cloud Run..."
27+
gcloud run deploy ${SERVICE_NAME} \
28+
--image ${IMAGE_NAME} \
29+
--platform managed \
30+
--region ${REGION} \
31+
--allow-unauthenticated \
32+
--memory 1Gi \
33+
--cpu 1 \
34+
--timeout 300 \
35+
--max-instances 10 \
36+
--set-env-vars PORT=8080 \
37+
--port 8080
38+
39+
echo "✅ Deployment complete!"
40+
41+
# Get the service URL
42+
SERVICE_URL=$(gcloud run services describe ${SERVICE_NAME} --region=${REGION} --format='value(status.url)')
43+
echo "🌐 Service URL: ${SERVICE_URL}"
44+
45+
echo "💡 Don't forget to update your webhook URL in WhatsApp Business API settings!"
46+
echo "Webhook URL: ${SERVICE_URL}/webhook"

gunicorn.conf.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Gunicorn configuration for FastAPI with ASGI
2+
import os
3+
4+
# Server socket
5+
bind = f"0.0.0.0:{os.getenv('PORT', '8080')}"
6+
backlog = 2048
7+
8+
# Worker processes
9+
workers = 1 # For async applications, usually 1 worker per CPU core
10+
worker_class = "uvicorn.workers.UvicornWorker"
11+
worker_connections = 1000
12+
keepalive = 5
13+
14+
# Logging
15+
loglevel = "info"
16+
accesslog = "-"
17+
errorlog = "-"
18+
19+
# Process naming
20+
proc_name = "whatsapp-bot"
21+
22+
# Server mechanics
23+
preload_app = True
24+
timeout = 120
25+
graceful_timeout = 30
26+
max_requests = 1000
27+
max_requests_jitter = 50
28+
29+
# SSL (if needed)
30+
# keyfile = None
31+
# certfile = None

main.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,5 +153,15 @@ async def handle_analyze(self, _, msg: types.Message):
153153

154154
# Initialize FastAPI
155155
app = FastAPI()
156+
157+
# Add health check endpoint for Cloud Run
158+
@app.get("/")
159+
async def health_check():
160+
return {"status": "healthy", "message": "WhatsApp Bot is running"}
161+
162+
@app.get("/health")
163+
async def health():
164+
return {"status": "ok"}
165+
156166
# Create an instance of the WhatsAppBot which registers the handlers
157167
bot = WhatsAppBot(app)

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ filelock==3.17.0
1414
frozenlist==1.5.0
1515
fsspec==2025.2.0
1616
googletrans==4.0.2
17+
gunicorn==21.2.0
1718
h11==0.14.0
1819
h2==4.2.0
1920
hpack==4.1.0
@@ -50,7 +51,7 @@ pydantic-core==2.27.2
5051
pygments==2.19.1
5152
python-dotenv==1.0.1
5253
python-multipart==0.0.20
53-
pywa==2.7.0
54+
pywa-async==2.7.0
5455
pyyaml==6.0.2
5556
rich==13.9.4
5657
rich-toolkit==0.13.2

start.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Startup script for the WhatsApp Bot application
4+
"""
5+
import sys
6+
import os
7+
8+
def main():
9+
"""Main entry point for the application"""
10+
try:
11+
# Import the FastAPI app
12+
from main import app
13+
14+
# Start the server
15+
import uvicorn
16+
17+
port = int(os.getenv("PORT", "8080"))
18+
19+
uvicorn.run(
20+
"main:app",
21+
host="0.0.0.0",
22+
port=port,
23+
log_level="info",
24+
access_log=True
25+
)
26+
27+
except ImportError as e:
28+
print(f"Import error: {e}")
29+
sys.exit(1)
30+
except Exception as e:
31+
print(f"Startup error: {e}")
32+
sys.exit(1)
33+
34+
if __name__ == "__main__":
35+
main()

0 commit comments

Comments
 (0)