FossilRepo

fossilrepo / fossil / webhooks.py
Blame History Raw 57 lines
1
"""Outbound webhooks for project events.
2
3
Webhooks fire on Fossil events (checkin, ticket, wiki, release) and deliver
4
JSON payloads to configured URLs with HMAC signature verification.
5
"""
6
7
from django.db import models
8
9
from core.fields import EncryptedTextField
10
from core.models import ActiveManager, Tracking
11
12
13
class Webhook(Tracking):
14
"""Outbound webhook for project events."""
15
16
class EventType(models.TextChoices):
17
CHECKIN = "checkin", "New Checkin"
18
TICKET = "ticket", "Ticket Change"
19
WIKI = "wiki", "Wiki Edit"
20
RELEASE = "release", "New Release"
21
ALL = "all", "All Events"
22
23
repository = models.ForeignKey("fossil.FossilRepository", on_delete=models.CASCADE, related_name="webhooks")
24
url = models.URLField(max_length=500)
25
secret = EncryptedTextField(blank=True, default="")
26
events = models.CharField(max_length=100, default="all") # comma-separated event types
27
is_active = models.BooleanField(default=True)
28
29
objects = ActiveManager()
30
all_objects = models.Manager()
31
32
class Meta:
33
ordering = ["-created_at"]
34
35
def __str__(self):
36
return f"{self.url} ({self.events})"
37
38
39
class WebhookDelivery(models.Model):
40
"""Log of webhook delivery attempts."""
41
42
webhook = models.ForeignKey(Webhook, on_delete=models.CASCADE, related_name="deliveries")
43
event_type = models.CharField(max_length=20)
44
payload = models.JSONField()
45
response_status = models.IntegerField(null=True, blank=True)
46
response_body = models.TextField(blank=True, default="")
47
success = models.BooleanField(default=False)
48
delivered_at = models.DateTimeField(auto_now_add=True)
49
duration_ms = models.IntegerField(default=0)
50
attempt = models.IntegerField(default=1)
51
52
class Meta:
53
ordering = ["-delivered_at"]
54
55
def __str__(self):
56
return f"{self.webhook.url} @ {self.delivered_at}"
57

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button