Skip to content

Latest commit

 

History

History

README.md

GitHub Webhook Dashboard

A real-time GitHub repository activity monitor built with Cloudflare Agents. This example demonstrates how to handle webhooks with Agents, verify signatures, store events in SQLite, and stream updates to connected clients.

Features

  • Webhook Handling - Receive and process GitHub webhooks
  • Signature Verification - HMAC-SHA256 verification of webhook payloads
  • Agent-per-Repository - Each repo gets its own isolated agent instance
  • Real-time Updates - WebSocket connection streams events as they arrive
  • Event History - Events stored in SQLite for persistence
  • Beautiful Dashboard - Dark-themed UI with live event feed

Quick Start

1. Install dependencies

npm install

2. Configure webhook secret

Copy .dev.vars.example to .dev.vars and set your webhook secret:

cp .dev.vars.example .dev.vars

Edit .dev.vars:

GITHUB_WEBHOOK_SECRET=your-secret-here

3. Start the development server

npm start

4. Expose your local server (for testing)

Since GitHub needs to reach your webhook endpoint, use a tool like ngrok:

ngrok http 5173

Copy the ngrok URL (e.g., https://abc123.ngrok.io).

5. Configure GitHub Webhook

  1. Go to your GitHub repository → SettingsWebhooks
  2. Click Add webhook
  3. Configure:
    • Payload URL: https://your-ngrok-url.ngrok.io/webhooks/github/owner/repo
    • Content type: application/json
    • Secret: Same value as GITHUB_WEBHOOK_SECRET
    • Events: Select which events to receive (or "Send me everything")
  4. Click Add webhook

6. Connect to your repo

Open http://localhost:5173 in your browser, enter your repository name (e.g., cloudflare/agents), and click Connect.

How It Works

Architecture

GitHub → POST /webhooks/github/owner/repo → Worker → RepoAgent (Durable Object)
                                                            ↓
Browser ← WebSocket ← Agent broadcasts state updates ←─────┘

Key Patterns Demonstrated

  1. Webhook Routing

    // Route webhooks to the right agent based on repository
    const agentName = sanitizeRepoName(payload.repository.full_name);
    const agent = await getAgentByName(env.RepoAgent, agentName);
    return agent.fetch(request);
  2. Signature Verification

    // Verify GitHub's HMAC-SHA256 signature
    const key = await crypto.subtle.importKey(
      "raw",
      secret,
      { name: "HMAC", hash: "SHA-256" },
      false,
      ["sign"]
    );
    const signature = await crypto.subtle.sign("HMAC", key, payload);
  3. Event Storage in SQLite

    this.sql`INSERT INTO events (id, type, title, ...) VALUES (...)`;
  4. Real-time State Broadcasting

    • When a webhook arrives, the agent updates its state
    • Connected clients receive the update via WebSocket

Supported Events

Event Type Description
push Commits pushed to a branch
pull_request PR opened, closed, merged, etc.
issues Issue opened, closed, labeled, etc.
issue_comment Comment on an issue or PR
star Repository starred/unstarred
fork Repository forked
release Release published
ping Webhook configured

Deployment

npm run deploy

After deploying:

  1. Set the webhook secret in Cloudflare:

    wrangler secret put GITHUB_WEBHOOK_SECRET
  2. Update your GitHub webhook URL to your deployed worker URL

Extending This Example

Ideas for enhancements:

  • AI PR Summaries - Use OpenAI to summarize PR diffs
  • Slack Notifications - Forward important events to Slack
  • Multi-Repo Dashboard - Monitor all your repos in one view
  • Custom Alerts - Schedule reminders for stale PRs
  • Webhook Replay - Re-send events for testing

Project Structure

examples/github-webhook/
├── src/
│   ├── server.ts        # RepoAgent + webhook routing
│   ├── client.tsx       # React dashboard
│   ├── github-types.ts  # TypeScript types for GitHub payloads
│   └── styles.css       # Dashboard styles
├── public/
│   └── normalize.css
├── index.html
├── wrangler.jsonc
└── package.json