Skip to content

Latest commit

 

History

History

README.md

GitHub PR Review Assistant

Webhook-triggered AI code review that fetches diffs, analyzes changes, and posts comments.

GitHub PR Review Demo

What it demonstrates

  • Webhook triggers — GitHub webhook Impulse fires on PR open/update events
  • Sequential pipeline — fetch diff, AI review, post comment in dependency order
  • MCP integration — GitHub MCP server posts review comments via create_pull_request_review
  • Secret injection — GitHub token and webhook secret stored in Kubernetes Secrets

Architecture

flowchart LR
    GH[GitHub Webhook] --> IMP[Impulse]

    subgraph Pipeline["Story: pr-review-assistant"]
        F[fetch-diff<br/>http-request] --> R[review-code<br/>openai-chat] --> P[post-comment<br/>mcp-adapter]
    end

    IMP --> F
    P --> GHC[GitHub PR Comment]
Loading

Prerequisites

  • BubuStack installed on your cluster
  • EngramTemplates: http-request, openai-chat, mcp-adapter
  • ImpulseTemplate: github-webhook-impulse
  • OpenAI API key
  • GitHub personal access token with repo scope

Quick start

# 1. Create the namespace
kubectl apply -f bootstrap.yaml

# 2. Create secrets (copy and edit with your real values first)
cp secrets.yaml.example secrets.yaml
# Edit secrets.yaml with your OpenAI API key, GitHub token, and webhook secret

# 3. Deploy secrets and prompts ConfigMap
kubectl apply -f secrets.yaml -f prompts.yaml

# 4. Deploy the Engrams
kubectl apply -f engrams.yaml

# 5. Deploy the Story
kubectl apply -f story.yaml

# 6. Deploy the Impulse (starts the webhook listener)
kubectl apply -f impulse.yaml

# 7. Configure GitHub webhook
# Repository -> Settings -> Webhooks -> Add webhook
# Payload URL: your Impulse's external URL (see Verify section)
# Content type: application/json
# Secret: same as WEBHOOK_SECRET in your secrets.yaml
# Events: Pull requests

Verify

# Check deployed resources
kubectl get engrams,stories,impulses -n github-pr-review

# Get the Impulse's webhook endpoint URL
kubectl get impulse pr-review-trigger -n github-pr-review -o jsonpath='{.status.endpoint}'

# Watch StoryRuns (one appears per PR event)
kubectl get storyruns -n github-pr-review -w

# Check individual StepRun phases
kubectl get stepruns -n github-pr-review

Cleanup

kubectl delete namespace github-pr-review

Under the Hood

  1. The Impulse CRD (github-webhook-impulse template) starts an HTTP server. It uses the controller-managed runner identity, so Bobrapet creates the namespaced ServiceAccount, Role, and RoleBinding with the normal StoryTrigger submitter baseline automatically. When GitHub sends a webhook POST, the Impulse validates the signature, extracts event data, and submits a durable StoryTrigger with the PR metadata as inputs. The controller then creates or reuses the target StoryRun.

  2. The fetch-diff step uses an http-request Engram configured with GitHub API headers and bearer token from a Kubernetes Secret. It fetches the PR diff from api.github.com.

  3. The review-code step uses an openai-chat Engram. The system prompt is stored in a ConfigMap (pr-review-prompts) and referenced via $bubuConfigMapRef in the Engram config. This keeps the Engram's with block small — the SDK resolves the ConfigMap reference at runtime inside the pod, avoiding inline size limits on StepRun inputs.

  4. The post-comment step uses the mcp-adapter Engram. It spawns the GitHub MCP server subprocess, invokes create_pull_request_review with the AI-generated review text, and captures the result. Template expressions like {{ inputs.repository | split "/" | first }} resolve owner/repo from the webhook payload.

  5. The Impulse's sessionKeyStrategy: auto prevents duplicate runs for rapid webhook re-deliveries.

CRDs involved: Impulse, ImpulseTemplate (github-webhook-impulse), Story, StoryRun, StepRun, Engram, EngramTemplate (http-request, openai-chat, mcp-adapter)