Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ runs:
TAG_NAME: ${{ github.event.release.tag_name }}
RELEASE_NAME: ${{ github.event.release.name }}
RELEASE_URL: ${{ github.event.release.html_url }}
RELEASE_BODY: ${{ github.event.release.body }}
ACTOR: ${{ github.event.release.author.login }}
run: python3 "${{ github.action_path }}/prepare.py"
27 changes: 26 additions & 1 deletion .github/actions/prepare-telegram-release-message/prepare.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#!/usr/bin/env python3
import os
import re
import uuid

RELEASE_DESCRIPTION_LIMIT = 3500
MARKDOWN_V2_SPECIAL_CHARACTERS = frozenset("_*[]()~`>#+-=|{}.!\\")
MARKDOWN_LINK = re.compile(r"\[([^]]+)]\([^)]*\)")


def escape_markdown(value):
Expand All @@ -13,6 +16,24 @@ def escape_link_url(value):
return str(value).replace("\\", "\\\\").replace(")", "\\)")


def truncate(value, limit):
if len(value) <= limit:
return value
return value[: limit - 3].rstrip() + "..."


def release_description(value, limit=RELEASE_DESCRIPTION_LIMIT):
lines = []
for source_line in value.strip().splitlines():
line = re.sub(r"^#{1,6}\s+", "", source_line.strip())
line = re.sub(r"^(?:[-+*]|\d+\.)\s+", "", line)
line = MARKDOWN_LINK.sub(r"\1", line)
if line or (lines and lines[-1]):
lines.append(line)

return truncate("\n".join(lines).strip(), limit)


def format_published(repository, release):
tag = release["tag"]
label = escape_markdown(f"release {tag}")
Expand All @@ -24,7 +45,10 @@ def format_published(repository, release):
parts.append(f"*{escape_markdown(name)}*")

parts.append(escape_markdown(release.get("actor") or "ghost"))
return " · ".join(parts)
message = " · ".join(parts)
if description := release_description(release.get("body") or ""):
message += f"\n{escape_markdown(description)}"
return message


def write_output(message):
Expand All @@ -40,6 +64,7 @@ def main():
"tag": os.environ["TAG_NAME"],
"name": os.environ.get("RELEASE_NAME") or "",
"url": os.environ["RELEASE_URL"],
"body": os.environ.get("RELEASE_BODY") or "",
"actor": os.environ.get("ACTOR") or "ghost",
}
write_output(format_published(os.environ["REPOSITORY"], release))
Expand Down
32 changes: 32 additions & 0 deletions test/test_telegram_notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,38 @@ def test_formats_distinct_release_name_and_escapes_markdown(self):
self.assertIn(r"*Summer \[release\]*", message)
self.assertTrue(message.endswith(r"dependabot\[bot\]"))

def test_includes_release_please_description_as_plain_text(self):
release = {
"tag": "v0.16.0",
"name": "v0.16.0",
"url": "https://github.com/owner/repo/releases/tag/v0.16.0",
"body": (
"## [0.16.0](https://github.com/owner/repo/compare/v0.15.0...v0.16.0) (2026-08-24)\n\n"
"### Features\n\n"
"* add Telegram release notifications "
"([#171](https://github.com/owner/repo/issues/171)) "
"([8d9e8c0](https://github.com/owner/repo/commit/8d9e8c0))"
),
"actor": "octocat",
}

message = RELEASE_TELEGRAM.format_published("owner/repo", release)

self.assertTrue(
message.endswith(
"octocat\n0\\.16\\.0 \\(2026\\-08\\-24\\)\n\n"
"Features\n\nadd Telegram release notifications \\(\\#171\\) \\(8d9e8c0\\)"
)
)

def test_truncates_long_release_description(self):
description = RELEASE_TELEGRAM.release_description(
"x" * (RELEASE_TELEGRAM.RELEASE_DESCRIPTION_LIMIT + 10)
)

self.assertEqual(len(description), RELEASE_TELEGRAM.RELEASE_DESCRIPTION_LIMIT)
self.assertTrue(description.endswith("..."))


class TelegramWorkflowTest(unittest.TestCase):
def load_workflow(self, name):
Expand Down