emo-online-api / scripts /sync-render-secrets.py
Emo Online
Deploy Emo API
dd87944
Raw
History Blame Contribute Delete
5.15 kB
#!/usr/bin/env python3
"""Sync backend/.env vers Render.com (API gratuite 24/7)."""
from __future__ import annotations
import os
import sys
from pathlib import Path
import httpx
from dotenv import load_dotenv
ROOT = Path(__file__).resolve().parents[1]
load_dotenv(ROOT / "emo" / "backend" / ".env", override=True)
RENDER_API = "https://api.render.com/v1"
SERVICE_NAME = os.environ.get("RENDER_SERVICE_NAME", "emo-online-api")
BACKEND_URL = os.environ.get(
"EMO_PUBLIC_BACKEND_URL", "https://xroxx-emo-online-api.hf.space"
).rstrip("/")
SECRET_KEYS = [
"MONGO_URL", "GOOGLE_CLIENT_ID", "GOOGLE_CLIENT_SECRET",
"OPENAI_API_KEY", "ANTHROPIC_API_KEY", "GEMINI_API_KEY",
"GROQ_API_KEY", "OPENROUTER_API_KEY", "DEEPSEEK_API_KEY",
"HF_TOKEN", "HUGGINGFACE_API_KEY", "EMERGENT_LLM_KEY",
"STRIPE_API_KEY", "STRIPE_BASIC_LINK", "STRIPE_PREMIUM_LINK", "STRIPE_ULTRA_LINK",
"EMO_PRODUCT_KEYS",
]
VARIABLES = {
"DB_NAME": "emo",
"EMO_DEV_MODE": "false",
"EMO_SERVE_FRONTEND": "false",
"EMO_BROWSER_ENABLED": "false",
"EMO_USE_SALES_LLM_KEYS": "true",
"EMO_PUBLIC_BACKEND_URL": BACKEND_URL,
"EMO_FRONTEND_URL": "https://xeroxytb.com",
"CORS_ORIGINS": "https://xeroxytb.com,https://www.xeroxytb.com,https://xeroxytb.github.io",
"GOOGLE_REDIRECT_URI": f"{BACKEND_URL}/api/auth/google/callback",
"PORT": "8010",
"EMO_ADMIN_EMAILS": os.environ.get("EMO_ADMIN_EMAILS", "huglostalatac@gmail.com"),
}
SALES_DUP = {
"SALES_OPENAI_API_KEY": "OPENAI_API_KEY",
"SALES_ANTHROPIC_API_KEY": "ANTHROPIC_API_KEY",
"SALES_GEMINI_API_KEY": "GEMINI_API_KEY",
"SALES_GROQ_API_KEY": "GROQ_API_KEY",
"SALES_OPENROUTER_API_KEY": "OPENROUTER_API_KEY",
"SALES_DEEPSEEK_API_KEY": "DEEPSEEK_API_KEY",
"SALES_HF_TOKEN": "HF_TOKEN",
}
def _headers(token: str) -> dict:
return {"Authorization": f"Bearer {token}", "Accept": "application/json"}
def find_service(client: httpx.Client, token: str) -> dict | None:
cursor = None
while True:
params = {"limit": 20}
if cursor:
params["cursor"] = cursor
r = client.get(f"{RENDER_API}/services", headers=_headers(token), params=params, timeout=30)
r.raise_for_status()
data = r.json()
for item in data:
svc = item.get("service") or item
if svc.get("name") == SERVICE_NAME:
return svc
cursor = r.headers.get("X-Next-Cursor") or r.headers.get("x-next-cursor")
if not cursor:
break
return None
def put_env(client: httpx.Client, token: str, service_id: str, key: str, value: str) -> None:
r = client.put(
f"{RENDER_API}/services/{service_id}/env-vars/{key}",
headers={**_headers(token), "Content-Type": "application/json"},
json={"value": value},
timeout=30,
)
if r.status_code == 404:
r = client.post(
f"{RENDER_API}/services/{service_id}/env-vars",
headers={**_headers(token), "Content-Type": "application/json"},
json={"envVar": {"key": key, "value": value}},
timeout=30,
)
r.raise_for_status()
def main() -> int:
token = os.environ.get("RENDER_API_KEY", "").strip()
if not token:
print("RENDER_API_KEY manquant — crée une clé sur https://dashboard.render.com/u/settings#api-keys")
print("Deploy 1-clic (gratuit) : https://render.com/deploy?repo=https://github.com/XeroxYTB/emo-online")
return 1
with httpx.Client() as client:
svc = find_service(client, token)
if not svc:
print(f"Service '{SERVICE_NAME}' introuvable sur Render.")
print("Deploy 1-clic : https://render.com/deploy?repo=https://github.com/XeroxYTB/emo-online")
return 1
sid = svc["id"]
print(f"Sync env → {svc.get('name')} ({svc.get('serviceDetails', {}).get('url', BACKEND_URL)})")
count = 0
for key in SECRET_KEYS:
val = os.environ.get(key, "").strip()
if val:
put_env(client, token, sid, key, val)
print(f" secret {key} OK")
count += 1
for key, val in VARIABLES.items():
put_env(client, token, sid, key, val)
print(f" var {key} OK")
count += 1
for sales, src in SALES_DUP.items():
val = os.environ.get(sales, "").strip() or os.environ.get(src, "").strip()
if val:
put_env(client, token, sid, sales, val)
print(f" sales {sales} OK")
count += 1
# Trigger redeploy
dr = client.post(
f"{RENDER_API}/services/{sid}/deploys",
headers={**_headers(token), "Content-Type": "application/json"},
json={"clearCache": "do_not_clear"},
timeout=60,
)
if dr.status_code in (200, 201):
print("Redeploy declenche.")
else:
print(f"Redeploy: HTTP {dr.status_code} (env sync OK, {count} vars)")
print("Done.")
return 0
if __name__ == "__main__":
raise SystemExit(main())