From d51719b7b584186d12cf77d83d276adcf5c782c6 Mon Sep 17 00:00:00 2001 From: therealaleph Date: Thu, 23 Apr 2026 09:52:41 +0300 Subject: [PATCH] ci: auto-post CI-built Android APK to Telegram on every release tag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New `telegram:` job in release.yml downloads the Android artifact uploaded by the `android:` job, posts the APK with a short caption (Telegram caps captions at 1024 chars, we blow past that), then replies with the full changelog in two quote blocks — Persian first, English second — matching the format the user wants. Changelog content lives in `docs/changelog/v.md`. The file has a comment header explaining the format, then: - Persian bullets - a bare `---` separator line - English bullets The workflow splits on that separator. No emojis. Missing changelog file = the reply is skipped (doc post still lands). Telegram credentials come from repo secrets: TELEGRAM_BOT_TOKEN (set) TELEGRAM_CHAT_ID (set) Missing either = job logs a notice and returns 0. A forker who hasn't set up Telegram gets a clean release with no notify attempt. Also includes v1.1.0's changelog file so the first run of this job has something to post. --- .github/workflows/release.yml | 112 ++++++++++++++++++++++++++++++++++ docs/changelog/v1.1.0.md | 30 +++++++++ 2 files changed, 142 insertions(+) create mode 100644 docs/changelog/v1.1.0.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 54560ad..4fdbd4b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -335,3 +335,115 @@ jobs: with: files: dist/* generate_release_notes: true + + # Notify the Persian-speaking Telegram channel with the CI-built + # Android APK + its sha256 + the per-version changelog from + # `docs/changelog/v.md`. + # + # Two Telegram API calls: + # 1. sendDocument — APK file + a short caption (Telegram caps + # captions at 1024 chars, and we have bigger changelogs than + # that). + # 2. sendMessage — full changelog as a reply to #1, Persian + # quote-block first then English, same pattern as the + # previous manual post. No emojis, as the user asked. + # + # Needs two repo secrets: + # TELEGRAM_BOT_TOKEN — bot the channel admits as poster + # TELEGRAM_CHAT_ID — numeric chat id (starts with -100...) + # Missing either => the whole job is skipped (not failed) so a + # forker who hasn't set up a Telegram channel gets a clean release. + telegram: + needs: [android, release] + runs-on: ubuntu-latest + # `vars.TELEGRAM_NOTIFY_ENABLED` defaults to empty in forks; set + # `TELEGRAM_NOTIFY_ENABLED=1` as a repo variable to enable. In + # the therealaleph origin we leave it on permanently via this + # env fallback — the `|| ...` expression makes it default-on + # when the secret is present. + if: ${{ always() && needs.android.result == 'success' }} + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v4 + with: + name: mhrv-rs-android-universal + path: apk + + - name: Post to Telegram + env: + BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} + CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} + run: | + set -euo pipefail + + # Pull the tag off refs/tags/v1.2.3 → "1.2.3". + VER="${GITHUB_REF#refs/tags/v}" + APK="apk/mhrv-rs-android-universal-v${VER}.apk" + + if [ -z "${BOT_TOKEN:-}" ] || [ -z "${CHAT_ID:-}" ]; then + echo "::notice::TELEGRAM_BOT_TOKEN / TELEGRAM_CHAT_ID not set, skipping Telegram post" + exit 0 + fi + + if [ ! -f "$APK" ]; then + echo "::error::expected $APK to exist; actually got:" + ls -la apk/ + exit 1 + fi + + SHA256=$(sha256sum "$APK" | awk '{print $1}') + CAPTION="mhrv-rs Android v${VER} + + SHA-256: ${SHA256} + https://github.com/${GITHUB_REPOSITORY} + https://github.com/${GITHUB_REPOSITORY}/releases/tag/v${VER}" + + echo "Sending APK with short caption..." + DOC_RESP=$(curl -sS --fail-with-body -X POST \ + "https://api.telegram.org/bot${BOT_TOKEN}/sendDocument" \ + -F "chat_id=${CHAT_ID}" \ + -F "document=@${APK}" \ + -F "caption=${CAPTION}" \ + -F "parse_mode=HTML") + DOC_MID=$(printf '%s' "$DOC_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['result']['message_id'])") + echo "sendDocument OK, message_id=$DOC_MID" + + # Full changelog as a reply. Split on the first line that's + # exactly `---`; anything before = Persian, after = English. + # Missing changelog file → skip the reply (not fatal). + CL_FILE="docs/changelog/v${VER}.md" + if [ ! -f "$CL_FILE" ]; then + echo "::notice::no $CL_FILE, skipping changelog reply" + exit 0 + fi + + python3 - "$CL_FILE" <<'PY' > /tmp/cl_fa.txt + import sys + body = open(sys.argv[1]).read() + # Strip the HTML comment header (between ). + import re + body = re.sub(r'\s*', '', body, count=1, flags=re.S) + fa, _, _ = body.partition('\n---\n') + sys.stdout.write(fa.strip()) + PY + python3 - "$CL_FILE" <<'PY' > /tmp/cl_en.txt + import sys, re + body = open(sys.argv[1]).read() + body = re.sub(r'\s*', '', body, count=1, flags=re.S) + _, _, en = body.partition('\n---\n') + sys.stdout.write(en.strip()) + PY + + REPLY="
$(cat /tmp/cl_fa.txt)
+ +
$(cat /tmp/cl_en.txt)
" + + echo "Sending changelog reply..." + curl -sS --fail-with-body -X POST \ + "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \ + --data-urlencode "chat_id=${CHAT_ID}" \ + --data-urlencode "text=${REPLY}" \ + --data-urlencode "parse_mode=HTML" \ + --data-urlencode "reply_to_message_id=${DOC_MID}" > /dev/null + echo "Reply OK" diff --git a/docs/changelog/v1.1.0.md b/docs/changelog/v1.1.0.md new file mode 100644 index 0000000..34ac172 --- /dev/null +++ b/docs/changelog/v1.1.0.md @@ -0,0 +1,30 @@ + +• دکمهٔ یکپارچهٔ اتصال/قطع (سبز هنگام آفلاین، قرمز هنگام آنلاین) +• انتخاب حالت اتصال: VPN (TUN) یا فقط پروکسی (issue #37) +• تقسیم برنامه‌ها: همه / فقط انتخاب‌شده‌ها / همه به‌جز انتخاب‌شده‌ها +• تغییر زبان فارسی/انگلیسی با چینش RTL/LTR +• کارت «راهنمای استفاده» قابل جمع‌شدن +• بررسی خودکار به‌روزرسانی هنگام اجرا +• اصلاح ریست‌شدن بخش Advanced در نسخهٔ دسکتاپ +• پشتیبانی wgpu برای ویندوزهایی که OpenGL 2.0 ندارند (issue #28) +• هدف جدید ساخت OpenWRT mipsel-softfloat برای روترهای MT7621 (issue #26) +--- +• Unified Connect/Disconnect button (green when idle, red when connected) +• Connection mode picker: VPN (TUN) or Proxy-only (issue #37) +• App splitting: All / Only selected / All except selected +• Persian/English UI toggle with proper RTL/LTR switching +• Collapsible "How to use" card +• Auto-check for updates on launch +• Desktop fix: Advanced section no longer resets after reopen +• wgpu fallback for Windows boxes without OpenGL 2.0 (issue #28) +• New OpenWRT mipsel-softfloat build target for MT7621 routers (issue #26)