Skip to content

Commit 43bb014

Browse files
committedMar 2, 2025··
formatters: Add custom formatter for AerynOS
The way this is done will _hopefully_ make it easier to rebase on top of upstream master in this branch. As of this commit, the formatter: - Will not print events from private repos - Prints a subset of branch actions - Prints a subset of PR actions - Sanely elides multiple commits - Tries to yield links with useful information Signed-off-by: Rune Morling <ermo@serpentos.com>
1 parent 3649a2b commit 43bb014

File tree

2 files changed

+202
-9
lines changed

2 files changed

+202
-9
lines changed
 

‎matrix_webhook/formatters.py

+89-9
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,97 @@ def grafana_9x(data, headers):
3333
def github(data, headers):
3434
"""Pretty-print a github notification."""
3535
# TODO: Write nice useful formatters. This is only an example.
36-
if headers["X-GitHub-Event"] == "push":
37-
pusher, ref, a, b, c = (
38-
data[k] for k in ["pusher", "ref", "after", "before", "compare"]
36+
#if headers["X-GitHub-Event"] == "push":
37+
# pusher, ref, a, b, c = (
38+
# data[k] for k in ["pusher", "ref", "after", "before", "compare"]
39+
# )
40+
# pusher = f"[@{pusher['name']}](https://github.com/{pusher['name']})"
41+
# data["body"] = f"{pusher} pushed on {ref}: [{b} → {a}]({c}):\n\n"
42+
# for commit in data["commits"]:
43+
# data["body"] += f"- [{commit['message']}]({commit['url']})\n"
44+
#else:
45+
# data["body"] = "notification from github"
46+
#data["digest"] = headers["X-Hub-Signature-256"].replace("sha256=", "")
47+
#return data
48+
return github_aerynos(data, headers)
49+
50+
51+
def github_aerynos(data, headers):
52+
"""Custom pretty-printer for GH notifications"""
53+
repository = data['repository']
54+
# It doesn't make sense to show private commits in public, so turn that off
55+
if repository['private'] and repository['visibility'] == "private":
56+
pass
57+
# GH webhook will get a 400 return code w/missing body
58+
elif headers['X-GitHub-Event'] == "push":
59+
pusher, ref, compare, created, deleted, forced = (
60+
data[k] for k in ["pusher", "ref", "compare", "created", "deleted", "forced"]
3961
)
40-
pusher = f"[@{pusher['name']}](https://github.com/{pusher['name']})"
41-
data["body"] = f"{pusher} pushed on {ref}: [{b}{a}]({c}):\n\n"
42-
for commit in data["commits"]:
43-
data["body"] += f"- [{commit['message']}]({commit['url']})\n"
62+
pusher_url = f"[@{pusher['name']}](https://github.com/{pusher['name']})"
63+
# Since we use monorepos and use an org-wide webhook, let's add repo info too.
64+
repo_url = f"[{repository['full_name']}]({repository['html_url']})"
65+
66+
if len(data['commits']) == 0:
67+
# these are booleans
68+
created, deleted, forced = (data[k] for k in ["created", "deleted", "forced"])
69+
# `git push --tags` has empty commit field, but mentions refs/tags/<the-tag> in ref
70+
if "refs/tags/" in ref:
71+
tag = ref.split("/")[-1]
72+
tag_url = f"{repository['html_url']}/releases/tag/{tag}"
73+
data['body'] = f"{repo_url}: {pusher_url} pushed tag [{tag}]({tag_url})\n"
74+
elif created:
75+
data['body'] = f"{repo_url}: {pusher_url} created empty branch _{ref}_\n"
76+
elif deleted:
77+
data['body'] = f"{repo_url}: {pusher_url} deleted branch <del>{ref}</del>\n"
78+
elif forced:
79+
branch = ref.split("/")[-1]
80+
branch_url = f"{repository['html_url']}/commits/{branch}"
81+
data['body'] = f"{repo_url}: {pusher_url} force pushed on [{ref}]({branch_url})\n"
82+
# Yet to be understood scenario
83+
else:
84+
pass
85+
else:
86+
# The commit shasum hashes are noisy, so just make the ref link to the full compare
87+
data['body'] = f"{repo_url}: {pusher_url} "
88+
if forced:
89+
data['body'] += "force "
90+
data['body'] += f"pushed on [{ref}]({compare}):\n\n"
91+
92+
for idx, commit in enumerate(data['commits']):
93+
# Elide commit list once we go past a reasonable number of commits for readability
94+
if idx >= 4:
95+
data['body'] += f"- (... {len(data['commits']) - 4} more commits ...)"
96+
break
97+
# We only really need the shortlog of each relevant commit
98+
shortlog = commit['message'].strip().split("\n")[0]
99+
data['body'] += f"- [{shortlog}]({commit['url']})\n"
100+
elif headers['X-GitHub-Event'] == "pull_request":
101+
action, number, pr, sender = (
102+
data[k] for k in ["action", "number", "pull_request", "sender"]
103+
)
104+
# avoid PR spam and wasted CPU cycles
105+
if action in ["opened", "closed", "reopened", "ready for review", "review requested"]:
106+
pr_title = pr['title']
107+
pr_url = pr['html_url']
108+
reponame = repository['full_name']
109+
repo_url = repository['html_url']
110+
# the user associated with the actual action, not just the PR
111+
sender_user = sender['login']
112+
url_query = "pulls/"
113+
114+
if action == "closed":
115+
url_query="pulls/?q=is%3Apr+is%3Aclosed"
116+
117+
data['body'] = f"PR#{number} [{pr_title}]({pr_url})\n\n"
118+
data['body'] += f"{action} by [@{sender_user}](https://github.com/{sender_user}) "
119+
data['body'] += f"in [{reponame}]({repo_url}/{url_query})"
120+
# endif
121+
# GH webhook will get a 400 return code w/missing body if the action
122+
# isn't in the allow-list
44123
else:
45-
data["body"] = "notification from github"
46-
data["digest"] = headers["X-Hub-Signature-256"].replace("sha256=", "")
124+
event = headers['X-GitHub-Event']
125+
data['body'] = f"unsupported github event: '{event}'"
126+
data['digest'] = headers['X-Hub-Signature-256'].replace("sha256=", "")
47127
return data
48128

49129

‎matrix_webhook/formatters.py.orig

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
"""Formatters for matrix webhook."""
2+
3+
import re
4+
5+
6+
def grafana(data, headers):
7+
"""Pretty-print a Grafana (version 8 and older) notification."""
8+
text = ""
9+
if "ruleName" not in data and "alerts" in data:
10+
return grafana_9x(data, headers)
11+
if "title" in data:
12+
text = "#### " + data["title"] + "\n"
13+
if "message" in data:
14+
text = text + data["message"] + "\n\n"
15+
if "evalMatches" in data:
16+
for match in data["evalMatches"]:
17+
text = text + "* " + match["metric"] + ": " + str(match["value"]) + "\n"
18+
data["body"] = text
19+
return data
20+
21+
22+
def grafana_9x(data, headers):
23+
"""Pretty-print a Grafana newer than v9.x notification."""
24+
text = ""
25+
if "title" in data:
26+
text = "#### " + data["title"] + "\n"
27+
if "message" in data:
28+
text = text + data["message"].replace("\n", "\n\n") + "\n\n"
29+
data["body"] = text
30+
return data
31+
32+
33+
def github(data, headers):
34+
"""Pretty-print a github notification."""
35+
# TODO: Write nice useful formatters. This is only an example.
36+
if headers["X-GitHub-Event"] == "push":
37+
pusher, ref, a, b, c = (
38+
data[k] for k in ["pusher", "ref", "after", "before", "compare"]
39+
)
40+
pusher = f"[@{pusher['name']}](https://github.com/{pusher['name']})"
41+
data["body"] = f"{pusher} pushed on {ref}: [{b} → {a}]({c}):\n\n"
42+
for commit in data["commits"]:
43+
data["body"] += f"- [{commit['message']}]({commit['url']})\n"
44+
else:
45+
data["body"] = "notification from github"
46+
data["digest"] = headers["X-Hub-Signature-256"].replace("sha256=", "")
47+
return data
48+
49+
50+
def gitlab_gchat(data, headers):
51+
"""Pretty-print a gitlab notification preformatted for Google Chat."""
52+
data["body"] = re.sub(
53+
"<(.*?)\\|(.*?)>",
54+
"[\\2](\\1)",
55+
data["body"],
56+
flags=re.MULTILINE,
57+
)
58+
return data
59+
60+
61+
def gitlab_teams(data, headers):
62+
"""Pretty-print a gitlab notification preformatted for Microsoft Teams."""
63+
body = []
64+
for section in data["sections"]:
65+
if "text" in section.keys():
66+
text = section["text"].split("\n\n")
67+
text = ["* " + t for t in text]
68+
body.append("\n" + " \n".join(text))
69+
elif all(
70+
k in section.keys()
71+
for k in ("activityTitle", "activitySubtitle", "activityText")
72+
):
73+
text = section["activityTitle"] + " " + section["activitySubtitle"] + " → "
74+
text += section["activityText"]
75+
body.append(text)
76+
77+
data["body"] = " \n".join(body)
78+
return data
79+
80+
81+
def gitlab_webhook(data, headers):
82+
"""Pretty-print a gitlab notification.
83+
84+
NB: This is a work-in-progress minimal example for now
85+
"""
86+
body = []
87+
88+
event_name = data["event_name"]
89+
user_name = data["user_name"]
90+
project = data["project"]
91+
92+
body.append(f"New {event_name} event")
93+
body.append(f"on [{project['name']}]({project['web_url']})")
94+
body.append(f"by {user_name}.")
95+
96+
data["body"] = " ".join(body)
97+
if "X-Gitlab-Token" in headers:
98+
data["key"] = headers["X-Gitlab-Token"]
99+
return data
100+
101+
102+
def grn(data, headers):
103+
"""Pretty-print a github release notifier (grn) notification."""
104+
version, title, author, package = (
105+
data[k] for k in ["version", "title", "author", "package_name"]
106+
)
107+
data["body"] = (
108+
f"### {package} - {version}\n\n{title}\n\n"
109+
f"[{author} released new version **{version}** for **{package}**]"
110+
f"(https://github.com/{package}/releases/tag/{version}).\n\n"
111+
)
112+
113+
return data

0 commit comments

Comments
 (0)
Please sign in to comment.