Skip to content

Custom Rules in the Webhook Pipeline

Custom rules are evaluated in real-time as GitHub webhook events arrive. This page explains the execution flow.

When Rules Fire

Custom rules are evaluated for these GitHub events:

EventActions
issuesopened, reopened, edited
pull_requestopened, reopened, ready_for_review

Pipeline Order

When a webhook arrives, GitWire processes it in this order:

GitHub Webhook

  ├─ 1. Pillar Workers (existing)
  │     ├─ Triage: classify, label, detect duplicates
  │     ├─ AI Review: code review findings
  │     └─ CI Healing: diagnose failed runs

  ├─ 2. Custom Rules (new)
  │     ├─ Build expression context from payload
  │     ├─ Load config + plugins
  │     ├─ Evaluate all rules
  │     └─ Execute matched actions via GitHub API

  └─ 3. Audit & Response
        ├─ Log decisions to decision_log table
        ├─ Record managed actions for reconciliation
        └─ Return 202 to GitHub

Expression Context

The context available to custom rules is built from the webhook payload:

VariableSource
authorissue.user.login or pull_request.user.login
branchpull_request.head.ref
titleIssue or PR title
bodyIssue or PR body
labelsCurrent labels on the item
filesPR changed files (fetched via API for PRs)
changesadditions, deletions, changed_files from PR
reporepository.full_name
is_newTrue for opened/reopened events
is_draftTrue for draft PRs

Action Execution

When a rule matches, its actions execute immediately:

ActionGitHub APIManaged?
add-labelPOST /issues/{n}/labels
remove-labelDELETE /issues/{n}/labels/{name}
add-commentPOST /issues/{n}/comments
approvePOST /pulls/{n}/reviews (APPROVE)
request-reviewPOST /pulls/{n}/requested_reviewers
set-priorityPOST /issues/{n}/labels (priority:X)
skipNo-op

Managed Actions

Actions marked "Managed" are tracked in the managed_actions table. They are automatically:

  • Reconciled on PR force-push (synchronize) — stale actions are re-evaluated
  • Cleaned up on PR close — managed actions are deactivated

Error Handling

  • If custom rules evaluation fails, it's logged but doesn't block the webhook response
  • Individual action failures are logged per-action — other actions in the same rule still execute
  • Rule evaluation errors (bad expression syntax) skip the rule — other rules continue

Audit Trail

Every custom rule execution is logged to the decision_log table:

source: "custom_rules"
decision: "acted"
reason: "Custom rule 'approve_safe' matched — executed 2 action(s)"
conditions: [{ check: "custom_rule(approve_safe)", result: true }]

API

List custom rules for a repo

GET /api/config/{owner}/{repo}/custom-rules

Returns resolved rules with conditions and action names:

json
{
  "rules": [
    {
      "name": "approve_safe",
      "condition": "is.docs",
      "actions": ["approve"]
    }
  ],
  "expressions": {
    "is": {
      "docs": "files | all(extension('.md'))"
    }
  },
  "total": 1
}

Released under the MIT License.