From 096807f35670241c4f2ba422e2f1c189c1ec1742 Mon Sep 17 00:00:00 2001 From: lizerk Date: Mon, 7 Sep 2026 21:05:50 +0300 Subject: [PATCH] Add Telegram transport fallbacks --- .gitea/workflows/deploy-production.yml | 113 +++++++++++++++++++------ ops/deploy/README.md | 3 +- 2 files changed, 90 insertions(+), 26 deletions(-) diff --git a/.gitea/workflows/deploy-production.yml b/.gitea/workflows/deploy-production.yml index c412dc25..3affc62a 100644 --- a/.gitea/workflows/deploy-production.yml +++ b/.gitea/workflows/deploy-production.yml @@ -68,11 +68,6 @@ jobs: echo "Telegram deployment report skipped: TELEGRAM_BOT_TOKEN or TELEGRAM_CHAT_ID is not configured." exit 0 fi - if ! command -v curl >/dev/null 2>&1; then - echo "Telegram deployment report skipped: curl is unavailable on the runner." - exit 0 - fi - case "${DEPLOY_OUTCOME:-unknown}" in success) heading="✅ Деплой production успешно завершён" @@ -103,29 +98,97 @@ jobs: "${run_url}")" response_file="$(mktemp)" - http_code="$(curl \ - --silent \ - --output "${response_file}" \ - --write-out '%{http_code}' \ - --connect-timeout 5 \ - --max-time 15 \ - --retry 2 \ - --retry-delay 2 \ - --retry-all-errors \ - --request POST \ - "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ - --data-urlencode "chat_id=${TELEGRAM_CHAT_ID}" \ - --data-urlencode "text=${message}" \ - --data-urlencode "disable_web_page_preview=true" 2>/dev/null)" - curl_status=$? + telegram_url="https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" + report_sent=false + + if command -v curl >/dev/null 2>&1; then + http_code="$(curl \ + --silent \ + --output "${response_file}" \ + --write-out '%{http_code}' \ + --connect-timeout 5 \ + --max-time 15 \ + --retry 2 \ + --retry-delay 2 \ + --request POST \ + "${telegram_url}" \ + --data-urlencode "chat_id=${TELEGRAM_CHAT_ID}" \ + --data-urlencode "text=${message}" \ + --data-urlencode "disable_web_page_preview=true" 2>/dev/null)" + transport_status=$? + if [ "${transport_status}" -eq 0 ] \ + && [ "${http_code}" -ge 200 ] 2>/dev/null \ + && [ "${http_code}" -lt 300 ] 2>/dev/null; then + report_sent=true + else + echo "Telegram report through curl failed; trying another available transport." + fi + fi + + if [ "${report_sent}" != true ] && command -v wget >/dev/null 2>&1; then + compact_message="$(printf '%s | Репозиторий: %s | Ветка: %s | Ревизия: %s | Инициатор: %s | Текущее состояние: %s | Запуск: %s' \ + "${heading}" \ + "${DEPLOY_REPOSITORY}" \ + "${DEPLOY_REF}" \ + "${DEPLOY_SHA}" \ + "${DEPLOY_ACTOR}" \ + "${production_state}" \ + "${run_url}")" + telegram_payload="$(printf '{"chat_id":"%s","text":"%s","disable_web_page_preview":true}' \ + "${TELEGRAM_CHAT_ID}" "${compact_message}")" + wget \ + -q \ + -O "${response_file}" \ + -T 15 \ + -t 3 \ + --header='Content-Type: application/json' \ + --post-data="${telegram_payload}" \ + "${telegram_url}" 2>/dev/null + transport_status=$? + if [ "${transport_status}" -eq 0 ]; then + report_sent=true + else + echo "Telegram report through wget failed; trying another available transport." + fi + fi + + if [ "${report_sent}" != true ] && command -v python3 >/dev/null 2>&1; then + TELEGRAM_MESSAGE="${message}" python3 - <<'PY' + import json + import os + import urllib.request + + payload = json.dumps( + { + "chat_id": os.environ["TELEGRAM_CHAT_ID"], + "text": os.environ["TELEGRAM_MESSAGE"], + "disable_web_page_preview": True, + } + ).encode() + request = urllib.request.Request( + f"https://api.telegram.org/bot{os.environ['TELEGRAM_BOT_TOKEN']}/sendMessage", + data=payload, + headers={"Content-Type": "application/json"}, + method="POST", + ) + with urllib.request.urlopen(request, timeout=15) as response: + if not 200 <= response.status < 300: + raise RuntimeError(f"Telegram returned HTTP {response.status}") + PY + transport_status=$? + if [ "${transport_status}" -eq 0 ]; then + report_sent=true + else + echo "Telegram report through Python failed." + fi + fi + rm -f "${response_file}" - if [ "${curl_status}" -ne 0 ]; then - echo "Telegram deployment report failed: curl exited with status ${curl_status}." - elif [ "${http_code}" -lt 200 ] 2>/dev/null || [ "${http_code}" -ge 300 ] 2>/dev/null; then - echo "Telegram deployment report failed: Telegram returned HTTP ${http_code:-unknown}." - else + if [ "${report_sent}" = true ]; then echo "Telegram deployment report sent." + else + echo "Telegram deployment report skipped: no available transport could deliver it." fi exit 0 diff --git a/ops/deploy/README.md b/ops/deploy/README.md index 19a44c17..65e0e55a 100644 --- a/ops/deploy/README.md +++ b/ops/deploy/README.md @@ -49,5 +49,6 @@ SHA are recorded under `/var/lib/eusrr-deploy`. The final workflow step reports successful, failed, cancelled, and unknown deployment outcomes with the repository, branch, revision, actor, current production state, and Gitea run link. Reporting is skipped when either Telegram -secret is absent. Missing tools, network failures, Telegram API errors, and +secret is absent. The runner tries `curl`, `wget`, and Python's standard HTTP +library in that order. Missing tools, network failures, Telegram API errors, and reporting timeouts are logged but never change the deployment result.