When to Use
- CI/CD automation: Trigger a build, test, or deployment workflow the moment a commit lands on a protected branch, keeping infrastructure changes tightly coupled to code changes with no polling overhead.
- PR review notifications: Fire a notification workflow when a pull request is opened, synchronised, or marked ready for review, routing it to the right reviewer team automatically.
- Issue tracking sync: Create or update records in an internal project tracker whenever a GitHub issue is opened, labelled, or closed, keeping both systems consistent without a manual import step.
- Release deployment triggers: Automatically kick off a deployment pipeline when a non-prerelease tag is published on GitHub, replacing manual approval steps with a verified, auditable trigger.
- Code change notifications: Alert on-call teams or compliance systems when commits land on main from external contributors, using
allowedRepositories and requireOwnerOrMember to scope the alert precisely.
Five webhook endpoints registered automatically. The node registers five paths on startup: /webhooks/github/push, /webhooks/github/pull-request, /webhooks/github/issues, /webhooks/github/releases, and /webhooks/github/workflow. Configure your GitHub webhook to deliver to the path matching your event type. All five are handled by a single node instance and share the same configuration.
Configuration
Security
| Field | Required | Description |
webhookSecret |
Required |
HMAC-SHA256 signing secret entered in GitHub → Repository Settings → Webhooks → Secret. Store in BizFirst Credentials Manager and reference as {{ $credentials.github-webhook-secret }}. Never paste a raw secret value into node configuration. |
enableIdempotencyCheck |
Optional |
Default false. When true, the X-GitHub-Delivery header is used as a deduplication key so a GitHub retry delivery does not start a second workflow run. |
includeFullEventObject |
Optional |
Default false. When true, the raw GitHub event JSON is written into the output under _raw_event. Increases payload size significantly; enable only when downstream nodes need fields not extracted by default. |
Event Filtering
| Field | Required | Description |
allowedEventTypes |
Optional |
Comma-separated event types to process. Other events are silently ignored. Valid values: push, pull_request, issues, release, workflow_run. Leave empty to process all five event types. |
allowedRepositories |
Optional |
Comma-separated repositories in owner/repo format. Events from other repositories are dropped before execution. Example: myorg/api,myorg/worker. Leave empty to process events from all repositories. |
allowedOrganizations |
Optional |
Comma-separated GitHub organization names. Events from repositories outside these organizations are ignored. Organization names must be 1–39 characters. Leave empty to process events from any organization. |
allowedBranches |
Optional |
Comma-separated branch names or wildcard patterns (e.g. main,release/*). Applies only to push events; all other event types bypass this filter. Leave empty to process pushes to all branches. |
allowedPullRequestActions |
Optional |
Comma-separated PR action names that fire the workflow. Applies only to pull_request events. Valid values: opened, synchronize, reopened, closed, edited, assigned, unassigned, labeled, unlabeled, review_requested, review_request_removed. Leave empty to process all PR actions. |
allowedIssueActions |
Optional |
Comma-separated issue action names that fire the workflow. Applies only to issues events. Valid values: opened, edited, deleted, transferred, pinned, unpinned, closed, reopened, assigned, unassigned, labeled, unlabeled, locked, unlocked, milestoned, demilestoned. Leave empty to process all issue actions. |
Access Control
| Field | Required | Description |
requireContributorAccess |
Optional |
Default false. When true, only processes events triggered by users who have push access to the repository. Recommended for public open-source repositories. |
requireOwnerOrMember |
Optional |
Default false. When true, only processes events triggered by the repository owner or verified organization members, blocking events from external forks or anonymous activity. |
onlyProcessNonEmptyPushes |
Optional |
Default false. When true, skips push events that carry no actual commit changes (e.g. branch creation pushes or force pushes to empty refs). |
Sample Configuration JSON
{
"webhookSecret": "{{ $credentials.github-webhook-secret }}",
"allowedEventTypes": "push,pull_request",
"allowedRepositories": "myorg/api,myorg/worker",
"allowedBranches": "main,release/*",
"allowedPullRequestActions": "opened,synchronize,closed",
"enableIdempotencyCheck": true,
"onlyProcessNonEmptyPushes": true,
"requireOwnerOrMember": true
}
Validation Errors
| Error | Cause |
Unknown event type: <value> | allowedEventTypes contains a value not in the valid set (push, pull_request, issues, release, workflow_run). |
Invalid repository format: <value> | An entry in allowedRepositories is missing the / separator. Required format: owner/repo. |
Invalid organization name: <value> | An entry in allowedOrganizations is empty or exceeds 39 characters. |
Unknown PR action: <value> | allowedPullRequestActions contains an unrecognised action string. |
Unknown issue action: <value> | allowedIssueActions contains an unrecognised action string. |
Missing 'x-hub-signature-256' header | The inbound request has no GitHub signature header. The request did not originate from GitHub or was tampered with in transit. |
Invalid GitHub signature | The HMAC-SHA256 of the request body does not match the header value. Likely a misconfigured webhookSecret. |
Webhook secret not configured | webhookSecret is empty and no fallback exists in appsettings.json under GitHub:WebhookSecret. |
Output
Success Port — Common Fields
Present on every successful execution regardless of event type:
| Field | Type | Description |
event_type | string | GitHub event name: push, pull_request, issues, release, or workflow_run. |
repository | string | Full repository name in owner/repo format. |
repository_id | number | Numeric GitHub repository identifier. |
repository_url | string | HTTPS URL to the repository on GitHub. |
repository_private | boolean | true for private repositories. |
action | string | Specific action that triggered the event (e.g. pushed, opened, closed). |
sender_login | string | GitHub login of the user who triggered the event. |
sender_type | string | User, Bot, or Organization. |
owner_login | string | GitHub login of the repository owner or organization. |
owner_type | string | User or Organization. |
timestamp | string | ISO 8601 UTC timestamp when the event occurred. |
Event-Specific Fields
| Event type | Additional output fields |
push |
branch — branch name without refs/heads/ prefix.
before_commit — SHA before the push (all zeros for new branch).
after_commit — SHA of the head commit after the push.
commits — array; each entry has id, message, author, author_email, url, timestamp, has_changes.
|
pull_request |
pr_number, pr_title, pr_state (open/closed/draft), pr_head_branch, pr_base_branch, pr_merged (boolean), pr_labels (string array), pr_requested_reviewers (string array). |
issues |
issue_number, issue_title, issue_state (open/closed), issue_labels (string array), issue_assignees (string array). |
release |
release_tag, release_name, release_prerelease (boolean), release_draft (boolean), release_url, release_asset_count (number). |
workflow_run |
workflow_name, workflow_status, workflow_conclusion, workflow_head_branch. |
Error Port
Fires when signature verification fails, the event type is not in allowedEventTypes, the sender fails an access control check, or the webhook body cannot be parsed. The output object contains errorCode and message string fields.
Sample Output JSON — Push Event
{
"event_type": "push",
"repository": "myorg/api",
"repository_id": 123456,
"repository_url": "https://github.com/myorg/api",
"repository_private": true,
"branch": "main",
"before_commit": "abc1234567890def1234567890abcdef12345678",
"after_commit": "def5678901234abc5678901234def567890abcde",
"action": "pushed",
"sender_login": "developer1",
"sender_type": "User",
"owner_login": "myorg",
"owner_type": "Organization",
"timestamp": "2026-05-26T09:15:30Z",
"commits": [
{
"id": "def5678901234abc5678901234def567890abcde",
"message": "fix: correct payment rounding on invoice totals",
"author": "Jane Smith",
"author_email": "jane@myorg.com",
"url": "https://github.com/myorg/api/commit/def5678901234abc",
"timestamp": "2026-05-26T09:14:55Z",
"has_changes": true
}
],
"_webhook_method": "POST",
"_webhook_path": "/webhooks/github/push",
"_webhook_received_at": "2026-05-26T09:15:31.042Z"
}
Expression Reference
| Expression | Value returned |
{{ $output.github.event_type }} | Event name string. |
{{ $output.github.repository }} | Full repository name (owner/repo). |
{{ $output.github.branch }} | Branch name for push events. |
{{ $output.github.after_commit }} | Head commit SHA after a push. |
{{ $output.github.commits[0].message }} | First commit message in a push event. |
{{ $output.github.action }} | Specific action string (e.g. opened, synchronize). |
{{ $output.github.pr_number }} | Pull request number. |
{{ $output.github.pr_title }} | Pull request title. |
{{ $output.github.issue_number }} | Issue number. |
{{ $output.github.issue_title }} | Issue title. |
{{ $output.github.release_tag }} | Release tag name (e.g. v2.1.0). |
{{ $output.github.sender_login }} | GitHub username who triggered the event. |
Node Policies & GuardRails
- Never skip signature verification. Always provide a
webhookSecret. The node uses constant-time comparison of the HMAC-SHA256 over the raw body against the X-Hub-Signature-256 header. Do not configure a blank or wildcard secret.
- Store secrets in Credentials Manager. Reference stored credentials with
{{ $credentials.name }}. Never paste raw webhook secret values into the node configuration field or commit them to source control.
- Enable idempotency for downstream writes. GitHub retries deliveries on network timeout. Set
enableIdempotencyCheck: true and include idempotency handling in any downstream node that writes to a database or external system.
- Scope
allowedRepositories in multi-tenant environments. If multiple workflows share one BizFirstAI tenant, use allowedRepositories to ensure each workflow fires only for the intended repository.
- Filter at the trigger — not inside the workflow. Use
allowedBranches, allowedPullRequestActions, and allowedIssueActions rather than adding an If-Condition node as the first step; filtering at the trigger avoids unnecessary workflow runs and reduces execution cost.
- Apply access control flags for public repositories. For open-source repositories, set
requireOwnerOrMember: true or requireContributorAccess: true to prevent external fork events from triggering internal automation.
Examples
Push to Main — Trigger Deployment Pipeline
{
"webhookSecret": "{{ $credentials.github-deploy-secret }}",
"allowedEventTypes": "push",
"allowedRepositories": "myorg/api",
"allowedBranches": "main",
"onlyProcessNonEmptyPushes": true,
"enableIdempotencyCheck": true
}
Only push events to the main branch of myorg/api start the deployment workflow. Empty pushes (branch creation, tag operations with no commits) are discarded. The X-GitHub-Delivery header prevents a GitHub retry from launching a duplicate deployment.
Pull Request Opened or Updated — Notify Review Team
{
"webhookSecret": "{{ $credentials.github-pr-secret }}",
"allowedEventTypes": "pull_request",
"allowedRepositories": "myorg/api",
"allowedPullRequestActions": "opened,synchronize,review_requested",
"requireOwnerOrMember": true
}
Fires a Slack or email notification to the assigned reviewers when a team member opens a PR, pushes new commits to an open PR, or explicitly requests a review. External fork pull requests from contributors outside the organization are blocked by requireOwnerOrMember.
Issue Opened or Labelled — Create Jira Ticket
{
"webhookSecret": "{{ $credentials.github-issue-secret }}",
"allowedEventTypes": "issues",
"allowedRepositories": "myorg/api,myorg/worker",
"allowedIssueActions": "opened,labeled",
"allowedOrganizations": "myorg"
}
When an issue is opened or a label is applied across either monitored repository, the downstream Jira node creates a ticket pre-populated with the issue title, body, and labels. The allowedOrganizations filter ensures events from forks under other organizations are dropped before execution.