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
33 changes: 25 additions & 8 deletions .github/actions/prepare-telegram-release-message/prepare.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
RELEASE_DESCRIPTION_LIMIT = 3500
MARKDOWN_V2_SPECIAL_CHARACTERS = frozenset("_*[]()~`>#+-=|{}.!\\")
MARKDOWN_LINK = re.compile(r"\[([^]]+)]\([^)]*\)")
MARKDOWN_HEADING = re.compile(r"^(#{1,6})\s+")
MARKDOWN_LIST_ITEM = re.compile(r"^(?:[-+*]|\d+\.)\s+")


def escape_markdown(value):
Expand All @@ -22,16 +24,31 @@ def truncate(value, limit):
return value[: limit - 3].rstrip() + "..."


def release_description(value, limit=RELEASE_DESCRIPTION_LIMIT):
def is_release_heading(value, tag):
version = re.escape(tag.removeprefix("v"))
return bool(re.fullmatch(rf"v?{version}(?:\s+\(\d{{4}}-\d{{2}}-\d{{2}}\))?", value))


def release_description(value, tag="", 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)
source_line = source_line.strip()
if not source_line:
continue

heading = bool(MARKDOWN_HEADING.match(source_line))
line = MARKDOWN_HEADING.sub("", source_line)
line = MARKDOWN_LIST_ITEM.sub("", line)
line = MARKDOWN_LINK.sub(r"\1", line)
if line or (lines and lines[-1]):
lines.append(line)
if not line or line in ("---", "***"):
continue
if heading and not lines and tag and is_release_heading(line, tag):
continue

escaped = escape_markdown(line)
lines.append(f"*{escaped}*" if heading else f"• {escaped}")

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


def format_published(repository, release):
Expand All @@ -46,8 +63,8 @@ def format_published(repository, release):

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


Expand Down
12 changes: 8 additions & 4 deletions test/test_telegram_notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ 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):
def test_formats_release_please_description_as_compact_list(self):
release = {
"tag": "v0.16.0",
"name": "v0.16.0",
Expand All @@ -230,7 +230,8 @@ def test_includes_release_please_description_as_plain_text(self):
"### Features\n\n"
"* add Telegram release notifications "
"([#171](https://github.com/owner/repo/issues/171)) "
"([8d9e8c0](https://github.com/owner/repo/commit/8d9e8c0))"
"([8d9e8c0](https://github.com/owner/repo/commit/8d9e8c0))\n\n"
"Deploy: mainframe updated"
),
"actor": "octocat",
}
Expand All @@ -239,10 +240,13 @@ def test_includes_release_please_description_as_plain_text(self):

self.assertTrue(
message.endswith(
"octocat\n0\\.16\\.0 \\(2026\\-08\\-24\\)\n\n"
"Features\n\nadd Telegram release notifications \\(\\#171\\) \\(8d9e8c0\\)"
"octocat\n*Features*\n"
"• add Telegram release notifications \\(\\#171\\) \\(8d9e8c0\\)\n"
"• Deploy: mainframe updated"
)
)
self.assertNotIn("0\\.16\\.0 \\(2026\\-08\\-24\\)", message)
self.assertNotIn("\n\n", message)

def test_truncates_long_release_description(self):
description = RELEASE_TELEGRAM.release_description(
Expand Down