From 3df6f5d7f0235dcc82735c94c150fd70e105f410 Mon Sep 17 00:00:00 2001 From: Nicolas Cantu Date: Mon, 22 Sep 2025 14:02:07 +0000 Subject: [PATCH] align for IA agents + grafana --- .env.master | 21 ++++++++++++++------- .env.master.exemple | 27 ++++++++++++++++----------- web/status/api.py | 27 ++++++++++++++++++++++++--- 3 files changed, 54 insertions(+), 21 deletions(-) diff --git a/.env.master b/.env.master index da4fce4..195508c 100644 --- a/.env.master +++ b/.env.master @@ -2,6 +2,7 @@ DOMAIN=dev4.4nkweb.com BOOTSTRAP_DOMAIN=dev3.4nkweb.com LOCAL_DOMAIN=local.4nkweb.com +LECOFFRE_BACK_DOMAIN=dev3.4nkweb.com # GIT GITEA_BASE_URL=git.4nkweb.com @@ -31,7 +32,7 @@ NEXT_PUBLIC_FRONT_APP_HOST=https://dev4.4nkweb.com/lecoffre NEXT_PUBLIC_IDNOT_BASE_URL=https://qual-connexion.idnot.fr NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT=/IdPOAuth2/authorize/idnot_idp_v1 NEXT_PUBLIC_BACK_API_PROTOCOL=https -NEXT_PUBLIC_BACK_API_HOST=${DOMAIN} +NEXT_PUBLIC_BACK_API_HOST=${LECOFFRE_BACK_DOMAIN} NEXT_PUBLIC_BACK_API_PORT=443 NEXT_PUBLIC_BACK_API_ROOT_URL=/api NEXT_PUBLIC_BACK_API_VERSION=v1 @@ -99,13 +100,19 @@ MAILCHIMP_KEY=3fa54304bc766dfd0b8043a827b28a3a-us17 MAILCHIMP_LIST_ID=a48d9ad852 # Configuration Stripe -STRIPE_SECRET_KEY=sk_test_51OwKmMP5xh1u9BqSeFpqw0Yr15hHtFsh0pvRGaE0VERhlYtvw33ND1qiGA6Dy1DPmmV61B6BqIimlhuv7bwElhjF00PLQwD60n -STRIPE_PUBLISHABLE_KEY=pk_test_51OwKmMP5xh1u9BqSOCBC1H40ACnGE4qH5ZERZ4tKktQuTcqRTPY26QqKeM6FfghdnbcC7nPbtMtnB6jemInrs67Z008RxkUGcn +STRIPE_SECRET_KEY=sk_test_51SA9bu0NPxjC8mAm5xdqVR5iKjzXw2QfNXfjYC2KbIJtCfENGj1uLvVCWJ2H7QCnnmLUqqgH45Qh74Sbss9GqDZv00WF9Me4Zp +# STRIPE_SECRET_KEY=sk_test_51OwKmMP5xh1u9BqSeFpqw0Yr15hHtFsh0pvRGaE0VERhlYtvw33ND1qiGA6Dy1DPmmV61B6BqIimlhuv7bwElhjF00PLQwD60n +# STRIPE_PUBLISHABLE_KEY=pk_test_51OwKmMP5xh1u9BqSOCBC1H40ACnGE4qH5ZERZ4tKktQuTcqRTPY26QqKeM6FfghdnbcC7nPbtMtnB6jemInrs67Z008RxkUGcn +STRIPE_PUBLISHABLE_KEY=pk_test_51SA9bu0NPxjC8mAm2a6Z01BqdpoLRGup8va1wPnYP0OLhrV6s5ch9rwE0y82oQpCiBJrDPfgab6cl0g4Rh1MPQ9h00f7TJXNhU STRIPE_WEBHOOK_SECRET= -STRIPE_STANDARD_SUBSCRIPTION_PRICE_ID=price_1P66fuP5xh1u9BqSHj0O6Uy3 -STRIPE_STANDARD_ANNUAL_SUBSCRIPTION_PRICE_ID=price_1P9NsRP5xh1u9BqSFgkUDbQY -STRIPE_UNLIMITED_SUBSCRIPTION_PRICE_ID=price_1P66RqP5xh1u9BqSuUzkQNac -STRIPE_UNLIMITED_ANNUAL_SUBSCRIPTION_PRICE_ID=price_1P9NpKP5xh1u9BqSApFogvUB +# STRIPE_STANDARD_SUBSCRIPTION_PRICE_ID=price_1P66fuP5xh1u9BqSHj0O6Uy3 +STRIPE_STANDARD_SUBSCRIPTION_PRICE_ID=price_1SA9qP0NPxjC8mAml8YAm5mQ +# STRIPE_STANDARD_ANNUAL_SUBSCRIPTION_PRICE_ID=price_1P9NsRP5xh1u9BqSFgkUDbQY +STRIPE_STANDARD_ANNUAL_SUBSCRIPTION_PRICE_ID=price_1SA9q60NPxjC8mAmvzkoWdnE +# STRIPE_UNLIMITED_SUBSCRIPTION_PRICE_ID=price_1P66RqP5xh1u9BqSuUzkQNac +STRIPE_UNLIMITED_SUBSCRIPTION_PRICE_ID=price_1SA9nI0NPxjC8mAmfQBlQQFl +# STRIPE_UNLIMITED_ANNUAL_SUBSCRIPTION_PRICE_ID=price_1P9NpKP5xh1u9BqSApFogvUB +STRIPE_UNLIMITED_ANNUAL_SUBSCRIPTION_PRICE_ID=price_1SA9n20NPxjC8mAmZFn2fw9l price_1QMUuXP5xh1u9BqS26uzbJaF_name='créateurs' price_1P9O6BP5xh1u9BqSelP9ZI52_name='standard annuel' price_1P9O68P5xh1u9BqSfNVdM8QL_name='starter annuel' diff --git a/.env.master.exemple b/.env.master.exemple index 8f355e3..195508c 100644 --- a/.env.master.exemple +++ b/.env.master.exemple @@ -2,6 +2,7 @@ DOMAIN=dev4.4nkweb.com BOOTSTRAP_DOMAIN=dev3.4nkweb.com LOCAL_DOMAIN=local.4nkweb.com +LECOFFRE_BACK_DOMAIN=dev3.4nkweb.com # GIT GITEA_BASE_URL=git.4nkweb.com @@ -10,8 +11,9 @@ GITEA_OWNER="nicolas.cantu,Omar" GITEA_RUNNER_NAME=debian-runner # Variables d'environnement pour l'application back-end -NODE_OPTIONS=--max-old-space-size=2048 NODE_ENV=production +RUST_LOG=DEBUG +NODE_OPTIONS=--max-old-space-size=2048 # Configuration IDNOT IDNOT_ANNUARY_BASE_URL=https://qual-api.notaires.fr/annuaire @@ -30,7 +32,7 @@ NEXT_PUBLIC_FRONT_APP_HOST=https://dev4.4nkweb.com/lecoffre NEXT_PUBLIC_IDNOT_BASE_URL=https://qual-connexion.idnot.fr NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT=/IdPOAuth2/authorize/idnot_idp_v1 NEXT_PUBLIC_BACK_API_PROTOCOL=https -NEXT_PUBLIC_BACK_API_HOST=${DOMAIN} +NEXT_PUBLIC_BACK_API_HOST=${LECOFFRE_BACK_DOMAIN} NEXT_PUBLIC_BACK_API_PORT=443 NEXT_PUBLIC_BACK_API_ROOT_URL=/api NEXT_PUBLIC_BACK_API_VERSION=v1 @@ -71,9 +73,6 @@ bitcoin_data_dir=/home/bitcoin/.bitcoin bootstrap_url=wss://${BOOTSTRAP_DOMAIN}/ws/ bootstrap_faucet=true -RUST_LOG=DEBUG, -NODE_OPTIONS=--max-old-space-size=2048 - # ================== /!\ sensible ========================= # Configuration IDNOT @@ -101,13 +100,19 @@ MAILCHIMP_KEY=3fa54304bc766dfd0b8043a827b28a3a-us17 MAILCHIMP_LIST_ID=a48d9ad852 # Configuration Stripe -STRIPE_SECRET_KEY=sk_test_51OwKmMP5xh1u9BqSeFpqw0Yr15hHtFsh0pvRGaE0VERhlYtvw33ND1qiGA6Dy1DPmmV61B6BqIimlhuv7bwElhjF00PLQwD60n -STRIPE_PUBLISHABLE_KEY= +STRIPE_SECRET_KEY=sk_test_51SA9bu0NPxjC8mAm5xdqVR5iKjzXw2QfNXfjYC2KbIJtCfENGj1uLvVCWJ2H7QCnnmLUqqgH45Qh74Sbss9GqDZv00WF9Me4Zp +# STRIPE_SECRET_KEY=sk_test_51OwKmMP5xh1u9BqSeFpqw0Yr15hHtFsh0pvRGaE0VERhlYtvw33ND1qiGA6Dy1DPmmV61B6BqIimlhuv7bwElhjF00PLQwD60n +# STRIPE_PUBLISHABLE_KEY=pk_test_51OwKmMP5xh1u9BqSOCBC1H40ACnGE4qH5ZERZ4tKktQuTcqRTPY26QqKeM6FfghdnbcC7nPbtMtnB6jemInrs67Z008RxkUGcn +STRIPE_PUBLISHABLE_KEY=pk_test_51SA9bu0NPxjC8mAm2a6Z01BqdpoLRGup8va1wPnYP0OLhrV6s5ch9rwE0y82oQpCiBJrDPfgab6cl0g4Rh1MPQ9h00f7TJXNhU STRIPE_WEBHOOK_SECRET= -STRIPE_STANDARD_SUBSCRIPTION_PRICE_ID=price_1P66fuP5xh1u9BqSHj0O6Uy3 -STRIPE_STANDARD_ANNUAL_SUBSCRIPTION_PRICE_ID=price_1P9NsRP5xh1u9BqSFgkUDbQY -STRIPE_UNLIMITED_SUBSCRIPTION_PRICE_ID=price_1P66RqP5xh1u9BqSuUzkQNac -STRIPE_UNLIMITED_ANNUAL_SUBSCRIPTION_PRICE_ID=price_1P9NpKP5xh1u9BqSApFogvUB +# STRIPE_STANDARD_SUBSCRIPTION_PRICE_ID=price_1P66fuP5xh1u9BqSHj0O6Uy3 +STRIPE_STANDARD_SUBSCRIPTION_PRICE_ID=price_1SA9qP0NPxjC8mAml8YAm5mQ +# STRIPE_STANDARD_ANNUAL_SUBSCRIPTION_PRICE_ID=price_1P9NsRP5xh1u9BqSFgkUDbQY +STRIPE_STANDARD_ANNUAL_SUBSCRIPTION_PRICE_ID=price_1SA9q60NPxjC8mAmvzkoWdnE +# STRIPE_UNLIMITED_SUBSCRIPTION_PRICE_ID=price_1P66RqP5xh1u9BqSuUzkQNac +STRIPE_UNLIMITED_SUBSCRIPTION_PRICE_ID=price_1SA9nI0NPxjC8mAmfQBlQQFl +# STRIPE_UNLIMITED_ANNUAL_SUBSCRIPTION_PRICE_ID=price_1P9NpKP5xh1u9BqSApFogvUB +STRIPE_UNLIMITED_ANNUAL_SUBSCRIPTION_PRICE_ID=price_1SA9n20NPxjC8mAmZFn2fw9l price_1QMUuXP5xh1u9BqS26uzbJaF_name='créateurs' price_1P9O6BP5xh1u9BqSelP9ZI52_name='standard annuel' price_1P9O68P5xh1u9BqSfNVdM8QL_name='starter annuel' diff --git a/web/status/api.py b/web/status/api.py index def7f24..8e38693 100644 --- a/web/status/api.py +++ b/web/status/api.py @@ -211,6 +211,12 @@ def get_storage_size_bytes(container: str) -> int: return {} +def docker_ps_names() -> set: + code, out, _ = run_cmd(["docker", "ps", "--format", "{{.Names}}"], timeout_seconds=6) + if code != 0 or not out: + return set() + return set(n.strip() for n in out.splitlines() if n.strip()) + def ovh_safe_check(app_key: str, app_secret: str, consumer_key: str, service_name: str, base_url: str = "https://eu.api.ovh.com/1.0") -> dict: try: # Get OVH time @@ -401,10 +407,20 @@ class StatusAPIHandler(BaseHTTPRequestHandler): except Exception: pass - # Deployment progress: percentage of services healthy/running + # Deployment progress: basé sur présence (docker ps) ET santé + running_names = docker_ps_names() total = len(services) - healthy = sum(1 for s in services if s.get("health") == "healthy" or s.get("status") == "running") - percent = int(healthy * 100 / total) if total else 0 + ready = 0 + for s in services: + name = s.get("name") + container = next((d["container"] for d in service_defs if d["name"] == name), None) + present = container in running_names if container else False + healthy_s = (s.get("health") == "healthy") + running_s = (s.get("status") == "running") + # considérer prêt si present ET (healthy ou running) + if present and (healthy_s or running_s): + ready += 1 + percent = int(ready * 100 / total) if total else 0 # Integrations: Mailchimp (Mandrill ping) and Stripe (counts) mailchimp_test = {"provider": "Mailchimp", "status": "missing"} @@ -426,6 +442,7 @@ class StatusAPIHandler(BaseHTTPRequestHandler): # Stripe: lister prices et agréger en balayant les subscriptions (sans filtre price) stripe_by_offer = {"CREATORS": 0, "STARTER": 0, "STANDARD": 0, "UNLIMITED": 0, "TOTAL": 0} stripe_prices_map = {} + stripe_price_counts = {} if env_map.get("STRIPE_SECRET_KEY"): try: auth_h = f"Authorization: Bearer {env_map.get('STRIPE_SECRET_KEY')}" @@ -439,6 +456,7 @@ class StatusAPIHandler(BaseHTTPRequestHandler): for pr in prices: pid = pr.get('id') stripe_prices_map[pid] = pr.get('nickname') or '' + stripe_price_counts[pid] = 0 # Déterminer les familles par ID connus (si présents dans l'env) sinon par nickname creators_ids = set(filter(None, [env_map.get("STRIPE_CREATORS_PRICE_ID")])) standard_ids = set(filter(None, [ @@ -489,6 +507,8 @@ class StatusAPIHandler(BaseHTTPRequestHandler): continue stripe_by_offer[fam] = stripe_by_offer.get(fam, 0) + 1 stripe_by_offer["TOTAL"] += 1 + if pid: + stripe_price_counts[pid] = stripe_price_counts.get(pid, 0) + 1 if d.get("has_more") and subs: starting_after = subs[-1].get('id') pages += 1 @@ -572,6 +592,7 @@ class StatusAPIHandler(BaseHTTPRequestHandler): "ovh": ovh_test, "mailchimp": mailchimp_test, "stripe_subscriptions_by_offer": stripe_by_offer, + "stripe_prices": {pid: {"nickname": stripe_prices_map.get(pid, ""), "count": cnt} for pid, cnt in stripe_price_counts.items()}, }, "wallets": wallets, }