0
0
Fork 0
mirror of https://github.com/healthchecks/healthchecks.git synced 2025-04-05 05:15:26 +00:00

Fix integrations to include oncalendar schedules in notifications

This commit is contained in:
Pēteris Caune 2024-04-24 16:08:55 +03:00
parent 011fa98154
commit 6fb46aee32
No known key found for this signature in database
GPG key ID: E28D7679E9A9EDE2
19 changed files with 179 additions and 18 deletions

View file

@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file.
### Bug Fixes
- Fix hc.front.views.docs_search to handle words "AND", "OR", "NOT" as queries
- Fix integrations to not disclose check's code in incident data
- Fix integrations to include oncalendar schedules in notifications
## v3.3 - 2024-04-03

View file

@ -157,6 +157,21 @@ class NotifyEmailTestCase(BaseTestCase):
self.assertIn("<code>0 18-23,0-8 * * *</code>", html)
self.assertIn("Europe/Riga", html)
def test_it_shows_oncalendar_schedule(self) -> None:
self.check.kind = "oncalendar"
self.check.schedule = "Mon 2-29"
self.check.tz = "Europe/Riga"
self.check.save()
self.channel.notify(self.flip)
email = mail.outbox[0]
html = self.get_html(email)
self.assertIn("Mon 2-29", email.body)
self.assertIn("Europe/Riga", email.body)
self.assertIn("<code>Mon 2-29</code>", html)
self.assertIn("Europe/Riga", html)
def test_it_truncates_long_body(self) -> None:
self.ping.body = "X" * 10000 + ", and the rest gets cut off"
self.ping.save()

View file

@ -66,7 +66,7 @@ class NotifyMsTeamsTestCase(BaseTestCase):
self.assertNotIn(str(self.check.code), serialized)
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_shows_schedule_and_tz(self, mock_post: Mock) -> None:
def test_it_shows_cron_schedule_and_tz(self, mock_post: Mock) -> None:
mock_post.return_value.status_code = 200
self.check.kind = "cron"
self.check.tz = "Europe/Riga"
@ -78,6 +78,20 @@ class NotifyMsTeamsTestCase(BaseTestCase):
self.assertEqual(facts["Schedule:"], "\u034f* \u034f* \u034f* \u034f* \u034f*")
self.assertEqual(facts["Time Zone:"], "Europe/Riga")
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_shows_oncalendar_schedule_and_tz(self, mock_post: Mock) -> None:
mock_post.return_value.status_code = 200
self.check.kind = "oncalendar"
self.check.schedule = "Mon 2-29"
self.check.tz = "Europe/Riga"
self.check.save()
self.channel.notify(self.flip)
payload = mock_post.call_args.kwargs["json"]
facts = {f["name"]: f["value"] for f in payload["sections"][0]["facts"]}
self.assertEqual(facts["Schedule:"], "Mon 2-29")
self.assertEqual(facts["Time Zone:"], "Europe/Riga")
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_escapes_stars_in_schedule(self, mock_post: Mock) -> None:
mock_post.return_value.status_code = 200

View file

@ -107,7 +107,7 @@ class NotifyNtfyTestCase(BaseTestCase):
self.assertIn("<Foobar>", payload["message"])
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_shows_schedule_and_tz(self, mock_post: Mock) -> None:
def test_it_shows_cron_schedule_and_tz(self, mock_post: Mock) -> None:
mock_post.return_value.status_code = 200
self.check.kind = "cron"
@ -119,6 +119,20 @@ class NotifyNtfyTestCase(BaseTestCase):
self.assertIn("Schedule: * * * * *", payload["message"])
self.assertIn("Time Zone: Europe/Riga", payload["message"])
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_shows_oncalendar_schedule_and_tz(self, mock_post: Mock) -> None:
mock_post.return_value.status_code = 200
self.check.kind = "oncalendar"
self.check.schedule = "Mon 2-29"
self.check.tz = "Europe/Riga"
self.check.save()
self.channel.notify(self.flip)
payload = mock_post.call_args.kwargs["json"]
self.assertIn("Schedule: Mon 2-29", payload["message"])
self.assertIn("Time Zone: Europe/Riga", payload["message"])
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_shows_all_other_checks_up_note(self, mock_post: Mock) -> None:
mock_post.return_value.status_code = 200

View file

@ -61,7 +61,7 @@ class NotifyPdTestCase(BaseTestCase):
self.assertEqual(payload["incident_key"], self.check.unique_key)
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_shows_schedule_and_tz(self, mock_post: Mock) -> None:
def test_it_shows_cron_schedule_and_tz(self, mock_post: Mock) -> None:
self._setup_data("123")
self.check.kind = "cron"
self.check.tz = "Europe/Riga"
@ -73,6 +73,20 @@ class NotifyPdTestCase(BaseTestCase):
self.assertEqual(payload["details"]["Schedule"], "* * * * *")
self.assertEqual(payload["details"]["Time zone"], "Europe/Riga")
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_shows_oncalendar_schedule_and_tz(self, mock_post: Mock) -> None:
self._setup_data("123")
self.check.kind = "oncalendar"
self.check.schedule = "Mon 2-29"
self.check.tz = "Europe/Riga"
self.check.save()
mock_post.return_value.status_code = 200
self.channel.notify(self.flip)
payload = mock_post.call_args.kwargs["json"]
self.assertEqual(payload["details"]["Schedule"], "Mon 2-29")
self.assertEqual(payload["details"]["Time zone"], "Europe/Riga")
@patch("hc.api.transports.curl.request", autospec=True)
def test_pd_complex(self, mock_post: Mock) -> None:
self._setup_data(json.dumps({"service_key": "456"}))

View file

@ -66,6 +66,35 @@ class NotifyPushoverTestCase(BaseTestCase):
self.assertNotIn("All the other checks are up.", payload["message"])
self.assertEqual(payload["tags"], self.check.unique_key)
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_shows_cron_schedule(self, mock_post: Mock) -> None:
self._setup_data("123|0")
self.check.kind = "cron"
self.check.tz = "Europe/Riga"
self.check.save()
mock_post.return_value.status_code = 200
self.channel.notify(self.flip)
payload = mock_post.call_args.kwargs["data"]
self.assertIn("<b>Schedule:</b> <code>* * * * *</code>", payload["message"])
self.assertIn("<b>Time Zone:</b> Europe/Riga", payload["message"])
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_shows_oncalendar_schedule(self, mock_post: Mock) -> None:
self._setup_data("123|0")
self.check.kind = "oncalendar"
self.check.schedule = "Mon 2-29"
self.check.tz = "Europe/Riga"
self.check.save()
mock_post.return_value.status_code = 200
self.channel.notify(self.flip)
payload = mock_post.call_args.kwargs["data"]
self.assertIn("<b>Schedule:</b> <code>Mon 2-29</code>", payload["message"])
self.assertIn("<b>Time Zone:</b> Europe/Riga", payload["message"])
@override_settings(PUSHOVER_API_TOKEN=None)
def test_it_requires_pushover_api_token(self) -> None:
self._setup_data("123|0")

View file

@ -74,7 +74,7 @@ class NotifyRocketChatTestCase(BaseTestCase):
self.assertEqual(self.channel.last_error, "Received status code 404")
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_shows_schedule_and_tz(self, mock_post: Mock) -> None:
def test_it_shows_cron_schedule_and_tz(self, mock_post: Mock) -> None:
mock_post.return_value.status_code = 200
self.check.kind = "cron"
self.check.tz = "Europe/Riga"
@ -86,6 +86,20 @@ class NotifyRocketChatTestCase(BaseTestCase):
self.assertEqual(fields["Schedule"], "\u034f* \u034f* \u034f* \u034f* \u034f*")
self.assertEqual(fields["Time Zone"], "Europe/Riga")
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_shows_oncalendar_schedule_and_tz(self, mock_post: Mock) -> None:
mock_post.return_value.status_code = 200
self.check.kind = "oncalendar"
self.check.schedule = "Mon 2-29"
self.check.tz = "Europe/Riga"
self.check.save()
self.channel.notify(self.flip)
attachment = mock_post.call_args.kwargs["json"]["attachments"][0]
fields = {f["title"]: f["value"] for f in attachment["fields"]}
self.assertEqual(fields["Schedule"], "Mon 2-29")
self.assertEqual(fields["Time Zone"], "Europe/Riga")
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_shows_last_ping_body_size(self, mock_post: Mock) -> None:
mock_post.return_value.status_code = 200

View file

@ -155,7 +155,7 @@ class NotifySignalTestCase(BaseTestCase):
self.assertIn("Last Ping: Exit status 123, 10 minutes ago", params["message"])
@patch("hc.api.transports.socket.socket")
def test_it_shows_schedule_and_tz(self, socket: Mock) -> None:
def test_it_shows_cron_schedule_and_tz(self, socket: Mock) -> None:
socketobj = setup_mock(socket, {})
self.check.kind = "cron"
@ -168,6 +168,21 @@ class NotifySignalTestCase(BaseTestCase):
self.assertIn("Schedule: * * * * *", params["message"])
self.assertIn("Time Zone: Europe/Riga", params["message"])
@patch("hc.api.transports.socket.socket")
def test_it_shows_oncalendar_schedule_and_tz(self, socket: Mock) -> None:
socketobj = setup_mock(socket, {})
self.check.kind = "oncalendar"
self.check.schedule = "Mon 2-29"
self.check.tz = "Europe/Riga"
self.check.save()
self.channel.notify(self.flip)
assert socketobj.req
params = socketobj.req["params"]
self.assertIn("Schedule: Mon 2-29", params["message"])
self.assertIn("Time Zone: Europe/Riga", params["message"])
@patch("hc.api.transports.socket.socket")
def test_it_handles_special_characters(self, socket: Mock) -> None:
socketobj = setup_mock(socket, {})

View file

@ -107,7 +107,7 @@ class NotifySlackTestCase(BaseTestCase):
self.assertEqual(mock_post.call_count, 3)
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_shows_schedule_and_tz(self, mock_post: Mock) -> None:
def test_it_shows_cron_schedule_and_tz(self, mock_post: Mock) -> None:
self._setup_data("123")
self.check.kind = "cron"
self.check.tz = "Europe/Riga"
@ -121,6 +121,22 @@ class NotifySlackTestCase(BaseTestCase):
self.assertEqual(fields["Schedule"], "\u034f* \u034f* \u034f* \u034f* \u034f*")
self.assertEqual(fields["Time Zone"], "Europe/Riga")
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_shows_oncalendar_schedule_and_tz(self, mock_post: Mock) -> None:
self._setup_data("123")
self.check.kind = "oncalendar"
self.check.schedule = "Mon 2-29"
self.check.tz = "Europe/Riga"
self.check.save()
mock_post.return_value.status_code = 200
self.channel.notify(self.flip)
payload = mock_post.call_args.kwargs["json"]
attachment = payload["attachments"][0]
fields = {f["title"]: f["value"] for f in attachment["fields"]}
self.assertEqual(fields["Schedule"], "Mon 2-29")
self.assertEqual(fields["Time Zone"], "Europe/Riga")
@patch("hc.api.transports.curl.request", autospec=True)
def test_slack_with_tabs_in_schedule(self, mock_post: Mock) -> None:
self._setup_data("123")

View file

@ -111,6 +111,21 @@ class NotifyTelegramTestCase(BaseTestCase):
)
self.assertIn("<b>Time Zone:</b> Europe/Riga\n", payload["text"])
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_shows_oncalendar_schedule(self, mock_post: Mock) -> None:
mock_post.return_value.status_code = 200
self.check.kind = "oncalendar"
self.check.schedule = "Mon 2-29"
self.check.tz = "Europe/Riga"
self.check.save()
self.channel.notify(self.flip)
payload = mock_post.call_args.kwargs["json"]
self.assertIn("<b>Schedule:</b> <code>Mon 2-29</code>\n", payload["text"])
self.assertIn("<b>Time Zone:</b> Europe/Riga\n", payload["text"])
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_returns_error(self, mock_post: Mock) -> None:
mock_post.return_value.status_code = 400

View file

@ -70,7 +70,7 @@ class NotifyTrelloTestCase(BaseTestCase):
self.assertEqual(n.error, "Trello notifications are not enabled.")
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_shows_schedule_and_tz(self, mock_post: Mock) -> None:
def test_it_shows_cron_schedule_and_tz(self, mock_post: Mock) -> None:
mock_post.return_value.status_code = 200
self.check.kind = "cron"
self.check.tz = "Europe/Riga"
@ -83,6 +83,20 @@ class NotifyTrelloTestCase(BaseTestCase):
self.assertIn(f"**Schedule:** `{a} {a} {a} {a} {a}`", params["desc"])
self.assertIn("**Time Zone:** Europe/Riga", params["desc"])
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_shows_oncalendar_schedule(self, mock_post: Mock) -> None:
mock_post.return_value.status_code = 200
self.check.kind = "oncalendar"
self.check.schedule = "Mon 2-29"
self.check.tz = "Europe/Riga"
self.check.save()
self.channel.notify(self.flip)
params = mock_post.call_args.kwargs["params"]
self.assertIn("**Schedule:** `Mon 2-29`", params["desc"])
self.assertIn("**Time Zone:** Europe/Riga", params["desc"])
@patch("hc.api.transports.curl.request", autospec=True)
def test_it_does_not_escape_name(self, mock_post: Mock) -> None:
mock_post.return_value.status_code = 200

View file

@ -458,7 +458,7 @@ class Slackalike(HttpTransport):
if check.kind == "simple":
fields.add("Period", format_duration(check.timeout))
if check.kind == "cron":
if check.kind in ("cron", "oncalendar"):
fields.add("Schedule", fix_asterisks(check.schedule))
fields.add("Time Zone", check.tz)
@ -609,7 +609,7 @@ class PagerDuty(HttpTransport):
details["Tags"] = ", ".join(check.tags_list())
if check.kind == "simple":
details["Period"] = format_duration(check.timeout)
if check.kind == "cron":
if check.kind in ("cron", "oncalendar"):
details["Schedule"] = check.schedule
details["Time zone"] = check.tz
@ -781,7 +781,7 @@ class RocketChat(HttpTransport):
if check.kind == "simple":
fields.add("Period", format_duration(check.timeout))
if check.kind == "cron":
if check.kind in ("cron", "oncalendar"):
fields.add("Schedule", fix_asterisks(check.schedule))
fields.add("Time Zone", check.tz)
@ -1189,7 +1189,7 @@ class MsTeams(HttpTransport):
if check.kind == "simple":
facts.append({"name": "Period:", "value": format_duration(check.timeout)})
if check.kind == "cron":
if check.kind in ("cron", "oncalendar"):
facts.append({"name": "Schedule:", "value": fix_asterisks(check.schedule)})
facts.append({"name": "Time Zone:", "value": check.tz})

View file

@ -43,7 +43,7 @@
{{ trtr|safe }} {% cycle trtr %}
{% endif %}
{% if check.kind == "cron" %}
{% if check.kind == "cron" or check.kind == "oncalendar" %}
<td style="padding-right: 32px; padding-bottom: 8px; vertical-align: top;">
<b>Schedule</b><br>
<code>{{ check.schedule }}</code>

View file

@ -29,7 +29,7 @@
{% line %}Period: {{ check.timeout|hc_duration }}{% endline %}
{% endif %}
{% if check.kind == "cron" %}
{% if check.kind == "cron" or check.kind == "oncalendar" %}
{% line %}Schedule: {{ check.schedule }}{% endline %}
{% line %}Time Zone: {{ check.tz }}{% endline %}
{% endif %}

View file

@ -12,7 +12,7 @@
{% line %}Period: {{ check.timeout|hc_duration }}{% endline %}
{% endif %}
{% if check.kind == "cron" %}
{% if check.kind == "cron" or check.kind == "oncalendar" %}
{% line %}Schedule: {{ check.schedule }}{% endline %}
{% line %}Time Zone: {{ check.tz }}{% endline %}
{% endif %}

View file

@ -19,7 +19,7 @@
{% line %}<b>Period:</b> {{ check.timeout|hc_duration }}{% endline %}
{% endif %}
{% if check.kind == "cron" %}
{% if check.kind == "cron" or check.kind == "oncalendar" %}
{% line %}<b>Schedule:</b> <code>{{ check.schedule }}</code>{% endline %}
{% line %}<b>Time Zone:</b> {{ check.tz }}{% endline %}
{% endif %}

View file

@ -19,7 +19,7 @@
{% line %}<b>Period:</b> {{ check.timeout|hc_duration }}{% endline %}
{% endif %}
{% if check.kind == "cron" %}
{% if check.kind == "cron" or check.kind == "oncalendar" %}
{% line %}<b>Schedule:</b> <code>{{ check.schedule }}</code>{% endline %}
{% line %}<b>Time Zone:</b> {{ check.tz }}{% endline %}
{% endif %}

View file

@ -18,7 +18,7 @@
{% line %}<b>Period:</b> {{ check.timeout|hc_duration }}{% endline %}
{% endif %}
{% if check.kind == "cron" %}
{% if check.kind == "cron" or check.kind == "oncalendar" %}
{% line %}<b>Schedule:</b> <code>{{ check.schedule }}</code>{% endline %}
{% line %}<b>Time Zone:</b> {{ check.tz }}{% endline %}
{% endif %}

View file

@ -5,7 +5,7 @@
**Period:** {{ check.timeout|hc_duration }}
{% endif %}
{% if check.kind == "cron" %}
{% if check.kind == "cron" or check.kind == "oncalendar" %}
**Schedule:** `{{ check.schedule|fix_asterisks }}`
**Time Zone:** {{ check.tz }}