Skip to content

🐙 GitHub Webhook Impulse

A BubuStack Impulse that submits durable StoryTrigger requests from GitHub webhook events.

🌟 Highlights

  • HMAC-SHA256 signature validation - Secure webhook verification
  • Event filtering - Filter by event type, action, repository, branch
  • Smart session keys - Automatic session keying by PR/issue/commit
  • Policy-based routing - Route different events to different Stories
  • End event detection - Graceful session cleanup on PR close/merge

🚀 Quick Start

  1. Install the ImpulseTemplate:
kubectl apply -f Impulse.yaml
  1. Create an Impulse instance:
apiVersion: bubustack.io/v1alpha1kind: Impulsemetadata:
name: my-github-webhooknamespace: defaultspec:
templateRef:
name: github-webhook-impulsestoryRef:
name: my-github-storysecrets:
webhookSecret:
name: github-webhook-secretwith:
path: /webhookvalidateSignature: trueeventsAllowlist:
- pull_request
- issuesactionsAllowlist:
- opened
- closed
- labeled
  1. Create the webhook secret:
kubectl create secret generic github-webhook-secret \
--from-literal=WEBHOOK_SECRET=your-github-webhook-secret
  1. Configure the webhook in GitHub:
    • Go to your repository → Settings → Webhooks → Add webhook
    • Payload URL: https://your-ingress/webhook
    • Content type: application/json
    • Secret: Same as WEBHOOK_SECRET
    • Events: Select events you want to receive

⚙️ Configuration (Impulse.spec.with)

Event Filtering

with:
# Only accept these event typeseventsAllowlist:
- pull_request
- push
- issues# Only accept these actionsactionsAllowlist:
- opened
- synchronize
- closed# Only accept from these repositoriesrepositoriesAllowlist:
- owner/repo1
- owner/repo2# Only accept these branches (supports globs)branchesAllowlist:
- main
- release/*

Session Key Strategies

with:
# auto: Smart detection based on event type (default)# - PR events → repo-pr-123# - Issue events → repo-issue-456# - Push events → repo-refs/heads/mainsessionKeyStrategy: auto# delivery: Use unique X-GitHub-Delivery headersessionKeyStrategy: delivery# custom: evaluate a template expression# available variables: .event, .action, .deliveryId, .payload, .repositorysessionKeyStrategy: customsessionKeyExpression: 'printf "%s-pr-%v" .repository.full_name .payload.pull_request.number'

Policy-Based Routing

Route different events to different Stories:

with:
policies:
- name: pr-reviewevents:
- pull_requestactions:
- opened
- synchronizestoryName: pr-review-story
- name: issue-triageevents:
- issuesactions:
- openedstoryName: issue-triage-story
- name: release-notifyevents:
- releaseactions:
- publishedstoryName: release-notification-story

Session Lifecycle

with:
# Events that start a new sessionstartEvents:
- "pull_request:opened"# Events that end a session (calls StoryDispatcher.Stop)endEvents:
- "pull_request:closed"
- "pull_request:merged"

📥 Story Inputs

The impulse provides structured inputs to your Story:

# Common fields (all events)event: "pull_request"action: "opened"deliveryId: "abc123..."repository: "owner/repo"sender: "username"# PR-specific fieldspullRequest:
number: 123title: "Add feature X"state: "open"htmlUrl: "https://github.com/..."head:
ref: "feature-branch"sha: "abc123..."base:
ref: "main"sha: "def456..."user: "author"draft: falsemerged: false# Issue-specific fieldsissue:
number: 456title: "Bug report"state: "open"labels: ["bug", "priority-high"]# Comment fields (issue_comment)comment:
id: 789body: "This is a comment"user: "commenter"# Push-specific fieldspush:
ref: "refs/heads/main"before: "abc123..."after: "def456..."commits: [...]pusher: "username"

📘 Example Stories

PR Review Assistant

apiVersion: bubustack.io/v1alpha1kind: Storymetadata:
name: pr-review-assistantspec:
pattern: batchsteps:
- name: fetch-diffref:
name: http-requestwith:
url: "https://api.github.com/repos/{{ inputs.repository }}/pulls/{{ inputs.pullRequest.number }}"headers:
Accept: "application/vnd.github.v3.diff"
- name: reviewneeds: [fetch-diff]ref:
name: ai-reviewerwith:
code: "{{ steps['fetch-diff'].output.body }}"
- name: post-commentneeds: [review]ref:
name: github-mcpwith:
action: callTooltool: create_issue_commentarguments:
owner: "{{ inputs.repository | split('/') | first }}"repo: "{{ inputs.repository | split('/') | last }}"issue_number: "{{ inputs.pullRequest.number }}"body: "{{ steps['review'].output.text }}"

Issue Triage Bot

apiVersion: bubustack.io/v1alpha1kind: Storymetadata:
name: issue-triage-botspec:
pattern: batchsteps:
- name: analyzeref:
name: openai-chatwith:
userPrompt: | Analyze this GitHub issue and suggest: 1. Priority (P0-P3) 2. Labels (bug, feature, docs, etc.) 3. Suggested assignee team Title: {{ inputs.issue.title }} Body: {{ inputs.issue.body }} - name: apply-labelsneeds: [analyze]ref:
name: github-mcpwith:
action: callTooltool: add_issue_labelsarguments:
owner: "{{ inputs.repository | split('/') | first }}"repo: "{{ inputs.repository | split('/') | last }}"issue_number: "{{ inputs.issue.number }}"labels: "{{ steps['analyze'].output.structured.labels }}"

🩺 Health Endpoints

  • GET :8081/health - Liveness probe
  • GET :8081/ready - Readiness probe

🧪 Local Development

# Build binary
make build
# Run tests
make test# Build Docker image
make docker-build VERSION=v0.1.0
# Push to registry
make docker-push VERSION=v0.1.0

🤝 Community & Support

📄 License

Copyright 2025 BubuStack.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

About

GitHub webhook Impulse for bobrapet — triggers StoryRuns on push, PR, issue, and other GitHub events.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages