Add event-driven tasks via Gitea webhooks
Webhook endpoint at /api/webhooks/gitea receives Gitea status events,
matches them against configurable event triggers with conditions
(event type, repo glob, state, context), renders task templates with
{{variable}} substitution, and creates harness tasks automatically.
Includes circuit breaker: after N consecutive task failures from the
same trigger (default 3), the trigger auto-disables. Re-enable
manually via PATCH /api/event-triggers/:id.
New tables: harness_event_triggers (rules + circuit breaker state),
harness_event_log (audit trail + dedup via X-Gitea-Delivery).
This commit is contained in:
34
apps/harness/src/lib/event-matching.ts
Normal file
34
apps/harness/src/lib/event-matching.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
// Match webhook events against event trigger conditions.
|
||||
|
||||
import { getEnabledEventTriggers, type EventTrigger } from "./event-store";
|
||||
import { type ParsedEvent } from "./template";
|
||||
|
||||
function escapeRegex(s: string): string {
|
||||
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
}
|
||||
|
||||
function globMatch(pattern: string, value: string): boolean {
|
||||
const regex = new RegExp(
|
||||
"^" + pattern.split("*").map(escapeRegex).join(".*") + "$",
|
||||
);
|
||||
return regex.test(value);
|
||||
}
|
||||
|
||||
export function matchesTrigger(trigger: EventTrigger, event: ParsedEvent): boolean {
|
||||
if (!trigger.enabled) return false;
|
||||
|
||||
if (trigger.eventType !== "*" && trigger.eventType !== event.eventType) return false;
|
||||
|
||||
if (trigger.repoFilter && !globMatch(trigger.repoFilter, event.repo)) return false;
|
||||
|
||||
if (trigger.stateFilter && trigger.stateFilter !== event.state) return false;
|
||||
|
||||
if (trigger.contextFilter && !event.context.includes(trigger.contextFilter)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export async function findMatchingTriggers(event: ParsedEvent): Promise<EventTrigger[]> {
|
||||
const triggers = await getEnabledEventTriggers();
|
||||
return triggers.filter(t => matchesTrigger(t, event));
|
||||
}
|
||||
Reference in New Issue
Block a user