Spaces:
Sleeping
Sleeping
File size: 5,145 Bytes
dd87944 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | #!/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())
|