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"),
|
("msteams", "Microsoft Teams"),
|
||||||
("shell", "Shell Command"),
|
("shell", "Shell Command"),
|
||||||
("zulip", "Zulip"),
|
("zulip", "Zulip"),
|
||||||
|
("spike", "Spike"),
|
||||||
)
|
)
|
||||||
|
|
||||||
PO_PRIORITIES = {-2: "lowest", -1: "low", 0: "normal", 1: "high", 2: "emergency"}
|
PO_PRIORITIES = {-2: "lowest", -1: "low", 0: "normal", 1: "high", 2: "emergency"}
|
||||||
@ -456,6 +457,8 @@ class Channel(models.Model):
|
|||||||
return transports.Shell(self)
|
return transports.Shell(self)
|
||||||
elif self.kind == "zulip":
|
elif self.kind == "zulip":
|
||||||
return transports.Zulip(self)
|
return transports.Zulip(self)
|
||||||
|
elif self.kind == "spike":
|
||||||
|
return transports.Spike(self)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError("Unknown channel kind: %s" % self.kind)
|
raise NotImplementedError("Unknown channel kind: %s" % self.kind)
|
||||||
|
|
||||||
|
@ -577,3 +577,17 @@ class Zulip(HttpTransport):
|
|||||||
}
|
}
|
||||||
|
|
||||||
return self.post(url, data=data, auth=auth)
|
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_webhook/", views.add_webhook, name="hc-add-webhook"),
|
||||||
path("add_whatsapp/", views.add_whatsapp, name="hc-add-whatsapp"),
|
path("add_whatsapp/", views.add_whatsapp, name="hc-add-whatsapp"),
|
||||||
path("add_zulip/", views.add_zulip, name="hc-add-zulip"),
|
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("badges/", views.badges, name="hc-badges"),
|
||||||
path("checks/", views.my_checks, name="hc-checks"),
|
path("checks/", views.my_checks, name="hc-checks"),
|
||||||
path("checks/add/", views.add_check, name="hc-add-check"),
|
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
|
yield "hc_checks_down_total %d\n" % num_down
|
||||||
|
|
||||||
return HttpResponse(output(checks), content_type="text/plain")
|
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 |
@ -335,6 +335,15 @@
|
|||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% 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 %}
|
{% if enable_telegram %}
|
||||||
<li>
|
<li>
|
||||||
<img src="{% static 'img/integrations/telegram.png' %}"
|
<img src="{% static 'img/integrations/telegram.png' %}"
|
||||||
|
@ -455,6 +455,13 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% 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 %}
|
{% if enable_telegram %}
|
||||||
<div class="col-lg-2 col-md-3 col-sm-4 col-xs-6">
|
<div class="col-lg-2 col-md-3 col-sm-4 col-xs-6">
|
||||||
<a href="{% url 'hc-telegram-help' %}" class="integration">
|
<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