mirror of
https://github.com/healthchecks/healthchecks.git
synced 2025-04-10 23:40:11 +00:00
Fix integrations to include oncalendar schedules in notifications
This commit is contained in:
parent
011fa98154
commit
6fb46aee32
19 changed files with 179 additions and 18 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"}))
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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, {})
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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})
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 }}
|
||||
|
|
Loading…
Add table
Reference in a new issue