From ac8bb3bae1c792eb6437d19d90198d5bf2e5fcc3 Mon Sep 17 00:00:00 2001 From: alisaza Date: Sun, 13 Sep 2026 18:31:13 +0330 Subject: [PATCH] fix: send admin deploy Telegram alerts from Actions runner [skip ci] Iran VPS cannot reach api.telegram.org, and sourcing backend .env broke on BOOKING_EXPIRY_CRON globs. Extract TELEGRAM_* safely over SSH and notify from the foreign act_runner instead. --- .gitea/workflows/deploy-vps.yml | 6 ++- .gitea/workflows/notify-telegram.yml | 31 +++++++++++++++ scripts/extract-telegram-env.py | 47 +++++++++++++++++++++++ scripts/notify-via-vps.sh | 56 ++++++++++++++-------------- 4 files changed, 109 insertions(+), 31 deletions(-) create mode 100644 .gitea/workflows/notify-telegram.yml create mode 100644 scripts/extract-telegram-env.py diff --git a/.gitea/workflows/deploy-vps.yml b/.gitea/workflows/deploy-vps.yml index fc9e718..b1df8d8 100644 --- a/.gitea/workflows/deploy-vps.yml +++ b/.gitea/workflows/deploy-vps.yml @@ -66,6 +66,7 @@ jobs: - name: Notify Telegram if: always() + continue-on-error: true env: DEPLOY_SHA: ${{ github.sha }} DEPLOY_STATUS: ${{ job.status }} @@ -79,5 +80,6 @@ jobs: success) export DEPLOY_STATUS=success ;; *) export DEPLOY_STATUS=failed ;; esac - chmod +x scripts/notify-via-vps.sh scripts/notify-ops-telegram.sh scripts/notify-deploy.sh || true - ./scripts/notify-via-vps.sh || true + chmod +x scripts/notify-via-vps.sh scripts/notify-ops-telegram.sh scripts/notify-deploy.sh + # Creds from Iran VPS .env; send from this foreign runner (Telegram blocked in Iran). + ./scripts/notify-via-vps.sh diff --git a/.gitea/workflows/notify-telegram.yml b/.gitea/workflows/notify-telegram.yml new file mode 100644 index 0000000..88f4341 --- /dev/null +++ b/.gitea/workflows/notify-telegram.yml @@ -0,0 +1,31 @@ +name: Notify Telegram (manual) + +# Lightweight check that deploy alerts work without rebuilding the admin image. +on: + workflow_dispatch: + +jobs: + notify: + name: Send test deploy notification + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + + - name: Notify Telegram + env: + DEPLOY_SHA: ${{ github.sha }} + DEPLOY_STATUS: success + DEPLOY_COMMIT_SUBJECT: manual notify test + SSH_KEY: ${{ secrets.VPS_SSH_KEY }} + VPS_HOST: ${{ secrets.VPS_HOST }} + VPS_USER: ${{ secrets.VPS_USER }} + run: | + set -euo pipefail + if ! command -v ssh >/dev/null 2>&1 || ! command -v scp >/dev/null 2>&1; then + apt-get update -qq + apt-get install -y -qq openssh-client + fi + export DEPLOY_VERSION="$(node -p "require('./package.json').version" 2>/dev/null || echo '?')" + chmod +x scripts/notify-via-vps.sh scripts/notify-ops-telegram.sh scripts/notify-deploy.sh + ./scripts/notify-via-vps.sh diff --git a/scripts/extract-telegram-env.py b/scripts/extract-telegram-env.py new file mode 100644 index 0000000..628e0cb --- /dev/null +++ b/scripts/extract-telegram-env.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +"""Print TELEGRAM_* assignments from known VPS env files (stdout only).""" +from __future__ import annotations + +from pathlib import Path + +WANTED = ( + 'TELEGRAM_BOT_TOKEN', + 'TELEGRAM_GROUP_CHAT_ID', + 'TELEGRAM_GROUP_THREAD_ID', + 'TELEGRAM_CHAT_ID', +) +PATHS = ( + Path('/opt/ghabilee-backend/.env'), + Path('/opt/ghabilee/backend/.env'), + Path('/opt/ghabilee-admin/.env'), +) + + +def main() -> None: + found: dict[str, str] = {} + for path in PATHS: + if not path.is_file() or path.stat().st_size == 0: + continue + for raw in path.read_text(encoding='utf-8', errors='replace').splitlines(): + line = raw.strip() + if not line or line.startswith('#') or '=' not in line: + continue + key, value = line.split('=', 1) + key = key.strip() + if key not in WANTED or key in found: + continue + value = value.strip() + if len(value) >= 2 and value[0] == value[-1] and value[0] in "\"'": + value = value[1:-1] + value = value.replace('\n', '').replace('\r', '') + found[key] = value + if 'TELEGRAM_BOT_TOKEN' in found: + break + + for key in WANTED: + if key in found and found[key]: + print(f'{key}={found[key]}') + + +if __name__ == '__main__': + main() diff --git a/scripts/notify-via-vps.sh b/scripts/notify-via-vps.sh index 3a5f6bc..8b08349 100755 --- a/scripts/notify-via-vps.sh +++ b/scripts/notify-via-vps.sh @@ -1,6 +1,11 @@ #!/usr/bin/env bash -# Send deploy notification from VPS (Telegram creds from /opt/ghabilee-backend/.env). -# GitHub runners may not reach api.telegram.org; VPS can. +# Load Telegram credentials from the Iran VPS .env, then send from this host. +# +# Why not notify on the VPS? +# - Iran egress often cannot reach api.telegram.org +# - Sourcing the full backend .env breaks on cron globs (BOOKING_EXPIRY_CRON=*) +# +# Gitea act_runner (foreign) can reach Telegram; we only SSH to fetch TELEGRAM_* keys. set -euo pipefail : "${SSH_KEY:?SSH_KEY required}" @@ -8,8 +13,7 @@ set -euo pipefail : "${VPS_USER:?VPS_USER required}" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REMOTE_DIR="/tmp/ghabilee-notify-$$" -COMMIT_SUBJECT_B64="$(printf '%s' "${DEPLOY_COMMIT_SUBJECT:-}" | base64 | tr -d '\n')" +EXTRACTOR="${SCRIPT_DIR}/extract-telegram-env.py" install -m 700 -d "$HOME/.ssh" printf '%s\n' "$SSH_KEY" > "$HOME/.ssh/vps_key" @@ -17,32 +21,26 @@ chmod 600 "$HOME/.ssh/vps_key" trap 'rm -f "$HOME/.ssh/vps_key"' EXIT SSH_OPTS=(-i "$HOME/.ssh/vps_key" -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new) -SCP_OPTS=("${SSH_OPTS[@]}") +REMOTE_EXTRACT="/tmp/ghabilee-extract-telegram-env-$$.py" -ssh "${SSH_OPTS[@]}" "${VPS_USER}@${VPS_HOST}" "mkdir -p '${REMOTE_DIR}'" -scp "${SCP_OPTS[@]}" \ - "${SCRIPT_DIR}/notify-ops-telegram.sh" \ - "${SCRIPT_DIR}/notify-deploy.sh" \ - "${VPS_USER}@${VPS_HOST}:${REMOTE_DIR}/" +scp "${SSH_OPTS[@]}" "$EXTRACTOR" "${VPS_USER}@${VPS_HOST}:${REMOTE_EXTRACT}" -ssh "${SSH_OPTS[@]}" "${VPS_USER}@${VPS_HOST}" \ - "DEPLOY_SHA='${DEPLOY_SHA:-}' DEPLOY_STATUS='${DEPLOY_STATUS:-success}' DEPLOY_VERSION='${DEPLOY_VERSION:-}' COMMIT_SUBJECT_B64='${COMMIT_SUBJECT_B64}' REMOTE_DIR='${REMOTE_DIR}' sh -s" <<'REMOTE' -set -eu -if [ -n "${COMMIT_SUBJECT_B64:-}" ]; then - DEPLOY_COMMIT_SUBJECT="$(printf '%s' "$COMMIT_SUBJECT_B64" | base64 -d 2>/dev/null || true)" - export DEPLOY_COMMIT_SUBJECT +while IFS= read -r line; do + [[ -z "$line" || "$line" != TELEGRAM_*=* ]] && continue + key="${line%%=*}" + value="${line#*=}" + export "${key}=${value}" +done < <(ssh "${SSH_OPTS[@]}" "${VPS_USER}@${VPS_HOST}" "python3 '${REMOTE_EXTRACT}'; rm -f '${REMOTE_EXTRACT}'") + +if [[ -z "${TELEGRAM_BOT_TOKEN:-}" ]]; then + echo "[ghabilee-admin-notify] failed: TELEGRAM_BOT_TOKEN missing on VPS" >&2 + exit 1 fi -set -a -if [ -s /opt/ghabilee-backend/.env ]; then - # shellcheck disable=SC1091 - . /opt/ghabilee-backend/.env -elif [ -s /opt/ghabilee/backend/.env ]; then - # shellcheck disable=SC1091 - . /opt/ghabilee/backend/.env +if [[ -z "${TELEGRAM_GROUP_CHAT_ID:-}${TELEGRAM_CHAT_ID:-}" ]]; then + echo "[ghabilee-admin-notify] failed: no Telegram chat id on VPS" >&2 + exit 1 fi -set +a -export DEPLOY_SHA DEPLOY_STATUS DEPLOY_COMMIT_SUBJECT DEPLOY_VERSION -chmod +x "${REMOTE_DIR}/notify-ops-telegram.sh" "${REMOTE_DIR}/notify-deploy.sh" -bash "${REMOTE_DIR}/notify-deploy.sh" -rm -rf "${REMOTE_DIR}" -REMOTE + +chmod +x "${SCRIPT_DIR}/notify-ops-telegram.sh" "${SCRIPT_DIR}/notify-deploy.sh" +# Run on the Actions runner (foreign) — not on the Iran VPS. +bash "${SCRIPT_DIR}/notify-deploy.sh"