forked from GithubBackups/healthchecks
integration for Spike
This commit is contained in:
parent
d34854f838
commit
6300947c77
@ -49,6 +49,7 @@ CHANNEL_KINDS = (
|
||||
("msteams", "Microsoft Teams"),
|
||||
("shell", "Shell Command"),
|
||||
("zulip", "Zulip"),
|
||||
("spike", "Spike"),
|
||||
)
|
||||
|
||||
PO_PRIORITIES = {-2: "lowest", -1: "low", 0: "normal", 1: "high", 2: "emergency"}
|
||||
@ -456,6 +457,8 @@ class Channel(models.Model):
|
||||
return transports.Shell(self)
|
||||
elif self.kind == "zulip":
|
||||
return transports.Zulip(self)
|
||||
elif self.kind == "spike":
|
||||
return transports.Spike(self)
|
||||
else:
|
||||
raise NotImplementedError("Unknown channel kind: %s" % self.kind)
|
||||
|
||||
|
@ -577,3 +577,17 @@ class Zulip(HttpTransport):
|
||||
}
|
||||
|
||||
return self.post(url, data=data, auth=auth)
|
||||
|
||||
|
||||
|
||||
class Spike(HttpTransport):
|
||||
def notify(self, check):
|
||||
url = self.channel.value
|
||||
headers = {"Conent-Type": "application/json"}
|
||||
payload = {
|
||||
"title": tmpl("spike_title.html", check=check),
|
||||
"message": tmpl("spike_description.html", check=check),
|
||||
"status": check.status
|
||||
}
|
||||
|
||||
return self.post(url, json=payload, headers=headers)
|
||||
|
30
hc/front/tests/test_add_spike.py
Normal file
30
hc/front/tests/test_add_spike.py
Normal file
@ -0,0 +1,30 @@
|
||||
from hc.api.models import Channel
|
||||
from hc.test import BaseTestCase
|
||||
|
||||
|
||||
class AddSpikeTestCase(BaseTestCase):
|
||||
url = "/integrations/add_spike/"
|
||||
|
||||
def test_instructions_work(self):
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.get(self.url)
|
||||
self.assertContains(r, "Spike")
|
||||
|
||||
def test_it_works(self):
|
||||
form = {"value": "http://example.org"}
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.post(self.url, form)
|
||||
self.assertRedirects(r, "/integrations/")
|
||||
|
||||
c = Channel.objects.get()
|
||||
self.assertEqual(c.kind, "spike")
|
||||
self.assertEqual(c.value, "http://example.org")
|
||||
self.assertEqual(c.project, self.project)
|
||||
|
||||
def test_it_rejects_bad_url(self):
|
||||
form = {"value": "not an URL"}
|
||||
|
||||
self.client.login(username="alice@example.org", password="password")
|
||||
r = self.client.post(self.url, form)
|
||||
self.assertContains(r, "Enter a valid URL")
|
@ -77,6 +77,7 @@ project_urls = [
|
||||
path("add_webhook/", views.add_webhook, name="hc-add-webhook"),
|
||||
path("add_whatsapp/", views.add_whatsapp, name="hc-add-whatsapp"),
|
||||
path("add_zulip/", views.add_zulip, name="hc-add-zulip"),
|
||||
path("add_spike/", views.add_spike, name="hc-add-spike"),
|
||||
path("badges/", views.badges, name="hc-badges"),
|
||||
path("checks/", views.my_checks, name="hc-checks"),
|
||||
path("checks/add/", views.add_check, name="hc-add-check"),
|
||||
|
@ -1724,3 +1724,25 @@ def metrics(request, code, key):
|
||||
yield "hc_checks_down_total %d\n" % num_down
|
||||
|
||||
return HttpResponse(output(checks), content_type="text/plain")
|
||||
|
||||
|
||||
|
||||
@login_required
|
||||
def add_spike(request, code):
|
||||
project = _get_project_for_user(request, code)
|
||||
|
||||
if request.method == "POST":
|
||||
form = forms.AddUrlForm(request.POST)
|
||||
if form.is_valid():
|
||||
channel = Channel(project=project, kind="spike")
|
||||
channel.value = form.cleaned_data["value"]
|
||||
channel.save()
|
||||
|
||||
channel.assign_all_checks()
|
||||
return redirect("hc-p-channels", project.code)
|
||||
else:
|
||||
form = forms.AddUrlForm()
|
||||
|
||||
ctx = {"page": "channels", "project": project, "form": form}
|
||||
return render(request, "integrations/add_spike.html", ctx)
|
||||
|
||||
|
BIN
static/img/integrations/setup_spike_1.png
Normal file
BIN
static/img/integrations/setup_spike_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 285 KiB |
BIN
static/img/integrations/setup_spike_2.png
Normal file
BIN
static/img/integrations/setup_spike_2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 72 KiB |
BIN
static/img/integrations/setup_spike_3.png
Normal file
BIN
static/img/integrations/setup_spike_3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 46 KiB |
BIN
static/img/integrations/spike.png
Normal file
BIN
static/img/integrations/spike.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
@ -334,12 +334,21 @@
|
||||
<a href="{% url 'hc-add-sms' project.code %}" class="btn btn-primary">Add Integration</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li>
|
||||
<img src="{% static 'img/integrations/spike.png' %}" class="icon" alt="Spike.sh icon" />
|
||||
|
||||
<h2>Spike.sh</h2>
|
||||
<p>No BS Incident management with unlimited alerts and on-call schedules</p>
|
||||
|
||||
<a href="{% url 'hc-add-spike' project.code %}" class="btn btn-primary">Add Integration</a>
|
||||
</li>
|
||||
|
||||
{% if enable_telegram %}
|
||||
<li>
|
||||
<img src="{% static 'img/integrations/telegram.png' %}"
|
||||
class="icon" alt="Telegram icon" />
|
||||
|
||||
|
||||
<h2>Telegram</h2>
|
||||
<p>A messaging app with a focus on speed and security.</p>
|
||||
<a href="{% url 'hc-add-telegram' %}" class="btn btn-primary">Add Integration</a>
|
||||
|
@ -455,6 +455,13 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="col-md-2 col-sm-4 col-xs-6">
|
||||
<div class="integration">
|
||||
<img src="{% static 'img/integrations/spike.png' %}" class="icon" alt="Spike.sh icon" />
|
||||
<h3>Spike.sh <br><small>Incident Management</small></h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if enable_telegram %}
|
||||
<div class="col-lg-2 col-md-3 col-sm-4 col-xs-6">
|
||||
<a href="{% url 'hc-telegram-help' %}" class="integration">
|
||||
|
94
templates/integrations/add_spike.html
Normal file
94
templates/integrations/add_spike.html
Normal file
@ -0,0 +1,94 @@
|
||||
{% extends "base.html" %}
|
||||
{% load humanize static hc_extras %}
|
||||
|
||||
{% block title %}Spike.sh Integration for {% site_name %}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h1>Spike.sh</h1>
|
||||
|
||||
<p>If you are using <a href="https://spike.sh">Spike.sh</a>, make sure to please copy the Healthchecks webhook
|
||||
and paste it here. Read through the instructions.</p>
|
||||
|
||||
<h2>Setup Guide</h2>
|
||||
|
||||
<div class="row ai-step">
|
||||
<div class="col-sm-6">
|
||||
<span class="step-no"></span>
|
||||
<p>
|
||||
Create a <strong>Healthchecks</strong> integration by clicking on <a
|
||||
href="https://app.spike.sh/integrations/new">add
|
||||
integration</a> on Spike.sh’s dashboard.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="marker-wrap">
|
||||
<span style="left: 89%; top: 19%;" class="marker"></span>
|
||||
<img class="ai-guide-screenshot" alt="Click create integration button"
|
||||
src="{% static 'img/integrations/setup_spike_1.png' %}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row ai-step">
|
||||
<div class="col-sm-6">
|
||||
<span class="step-no"></span>
|
||||
<p>
|
||||
After you have created the integration, click on copy webhook.
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<img class="ai-guide-screenshot" alt="Create Healthchecks.io integration with details"
|
||||
src="{% static 'img/integrations/setup_spike_2.png' %}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row ai-step">
|
||||
<div class="col-sm-6">
|
||||
<span class="step-no"></span>
|
||||
<p>
|
||||
This modal with the details for the webhook will show up. Copy that webhook and paste it below. Make
|
||||
sure you have Healthchecks integration’s webhook so Spike.sh can create and resolve incidents
|
||||
automatically.
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="marker-wrap">
|
||||
<span style="left: 32%; top: 59%;" class="marker"></span>
|
||||
|
||||
<img class="ai-guide-screenshot" alt="Copy the Webhook URL"
|
||||
src="{% static 'img/integrations/setup_spike_3.png' %}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Integration Settings</h2>
|
||||
|
||||
<form method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
<div class="form-group {{ form.value.css_classes }}">
|
||||
<label for="post-url" class="col-sm-2 control-label">Endpoint</label>
|
||||
<div class="col-sm-10">
|
||||
<input id="post-url" type="text" class="form-control" name="value" placeholder="https://"
|
||||
value="{{ form.value.value|default:"" }}">
|
||||
|
||||
{% if form.value.errors %}
|
||||
<div class="help-block">
|
||||
{{ form.value.errors|join:"" }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button type="submit" class="btn btn-primary">Save Integration</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
5
templates/integrations/spike_description.html
Normal file
5
templates/integrations/spike_description.html
Normal file
@ -0,0 +1,5 @@
|
||||
{% load humanize %}
|
||||
{{ check.name_then_code }} is {{ check.status|upper }}.
|
||||
{% if check.status == "down" %}
|
||||
Last ping was {{ check.last_ping|naturaltime }}.
|
||||
{% endif %}
|
1
templates/integrations/spike_title.html
Normal file
1
templates/integrations/spike_title.html
Normal file
@ -0,0 +1 @@
|
||||
{{ check.name_then_code }} is {{ check.status|upper }}
|
Loading…
x
Reference in New Issue
Block a user