An open API service indexing awesome lists of open source software.

https://github.com/rithviknishad/leaderboard-bot

Cloudflare Worker for GitHub App webhook handling
https://github.com/rithviknishad/leaderboard-bot

cloudflare github leaderboard webhook worker

Last synced: 2 months ago
JSON representation

Cloudflare Worker for GitHub App webhook handling

Awesome Lists containing this project

README

          

# Leaderboard Bot - Cloudflare Worker

A Cloudflare Worker that handles GitHub App webhook events and forwards installation events to the automation repository for processing.

## Features

- Receives GitHub App webhook events (installation and installation_repositories)
- **Secure webhook signature verification** using HMAC-SHA256
- Forwards relevant events to the automation repository via `repository_dispatch`
- **Automated repository setup** via GitHub Actions workflow
- Built with TypeScript for type safety
- Comprehensive test coverage with Vitest
- Easy deployment with Wrangler

## Prerequisites

- [Node.js](https://nodejs.org/) (v18 or later)
- [pnpm](https://pnpm.io/) package manager
- [Cloudflare account](https://dash.cloudflare.com/sign-up)
- [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/) (installed via pnpm)
- GitHub Personal Access Token with `repo` scope

## Setup

### 1. Install Dependencies

```bash
pnpm install
```

### 2. Configure Wrangler

Edit `wrangler.toml` and set your Cloudflare account ID:

```toml
account_id = "your-account-id-here"
```

You can find your account ID in the Cloudflare dashboard or by running:

```bash
pnpm wrangler whoami
```

### 3. Set Secrets

Set the required secrets for the worker:

```bash
# GitHub Personal Access Token for triggering repository_dispatch
pnpm wrangler secret put AUTOMATION_REPO_TRIGGER_TOKEN

# GitHub webhook secret for signature verification
pnpm wrangler secret put GITHUB_WEBHOOK_SECRET
```

**AUTOMATION_REPO_TRIGGER_TOKEN** - GitHub Personal Access Token that needs:
- `repo` scope (to trigger repository_dispatch events)
- Access to the `rithviknishad/leaderboard-bot` repository

**GITHUB_WEBHOOK_SECRET** - The webhook secret you configure in your GitHub App settings. This is used to verify that webhook requests are actually coming from GitHub using HMAC-SHA256 signatures.

### 4. Configure GitHub Repository Secrets and Variables

For the automation workflow to work, add these to your `rithviknishad/leaderboard-bot` repository:

1. Go to repository Settings → Secrets and variables → Actions

2. Under the **Variables** tab, add:
- **LEADERBOARD_BOT_ID**: Your GitHub App ID (found in App settings)

3. Under the **Secrets** tab, add:
- **LEADERBOARD_BOT_PRIVATE_KEY**: Your GitHub App private key (PEM format)

To generate a private key for your GitHub App:
1. Go to your GitHub App settings
2. Scroll to "Private keys" section
3. Click "Generate a private key"
4. Save the downloaded `.pem` file contents as the secret value

## Development

### Run Locally

Start the development server:

```bash
pnpm dev
```

This will start a local server (typically at `http://localhost:8787`) where you can test the worker.

### Test the Worker

You can test the worker locally using curl:

```bash
# Test GET request (should return "ok")
curl http://localhost:8787

# Test POST with installation event
curl -X POST http://localhost:8787 \
-H "x-github-event: installation" \
-H "Content-Type: application/json" \
-d '{"action":"created","installation":{"id":12345}}'
```

### Run Tests

Run the test suite:

```bash
# Run tests once
pnpm test

# Run tests in watch mode
pnpm test:watch
```

### Type Check

Check TypeScript types:

```bash
pnpm type-check
```

## Deployment

### Deploy to Cloudflare Workers

```bash
pnpm deploy
```

This will:
1. Build your worker
2. Upload it to Cloudflare
3. Make it available at your worker URL

### Configure GitHub Webhook

After deployment:

1. Go to your GitHub App settings
2. Set the Webhook URL to your worker URL (e.g., `https://leaderboard-bot.your-subdomain.workers.dev`)
3. **Set a webhook secret** - Generate a secure random string and save it (you'll need to add it as `GITHUB_WEBHOOK_SECRET` in Wrangler secrets)
4. Subscribe to these events:
- `installation`
- `installation_repositories`

**Important:** The worker requires webhook signature verification. Make sure the webhook secret in your GitHub App settings matches the `GITHUB_WEBHOOK_SECRET` you configured in step 3 of the setup.

## How It Works

1. GitHub sends webhook events to the worker when:
- Your app is installed on a repository (`installation` event)
- Repositories are added/removed from the installation (`installation_repositories` event)

2. The worker **verifies the webhook signature** using HMAC-SHA256 to ensure the request is authentic

3. The worker validates the request and filters for relevant events

4. For installation-related events, the worker forwards them to `rithviknishad/leaderboard-bot` via the GitHub API's `repository_dispatch` endpoint

5. The automation repository can then handle the event with a GitHub Actions workflow

## Installation Handler Workflow

The repository includes a GitHub Actions workflow (`.github/workflows/auto-setup.yml`) that automatically processes installation events:

### What It Does

1. **Receives repository_dispatch events** from the Cloudflare Worker
2. **Authenticates as the GitHub App** using the app credentials stored in this repository
3. **Sets up credentials on each installed repository**:
- Sets `LEADERBOARD_BOT_ID` as a repository variable
- Sets `LEADERBOARD_BOT_PRIVATE_KEY` as a repository secret

This allows the target repositories to use these credentials in their own workflows to generate installation tokens and interact with the GitHub API as the leaderboard bot.

### How It Works

```mermaid
graph LR
A[GitHub App Installed] --> B[Webhook to Worker]
B --> C[Worker Verifies Signature]
C --> D[Worker Dispatches Event]
D --> E[Workflow Triggered]
E --> F[Authenticate as App]
F --> G[Get Installation Token]
G --> H[Set Secrets/Variables on Target Repos]
```

### Using the Bot in Target Repositories

Once the bot is installed, target repositories will have access to:
- `LEADERBOARD_BOT_ID` (variable)
- `LEADERBOARD_BOT_PRIVATE_KEY` (secret)

These can be used in GitHub Actions workflows to generate installation tokens:

```yaml
- name: Generate app token
id: app_token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ vars.LEADERBOARD_BOT_ID }}
private-key: ${{ secrets.LEADERBOARD_BOT_PRIVATE_KEY }}

- name: Use the token
env:
GH_TOKEN: ${{ steps.app_token.outputs.token }}
run: |
gh api /user
```

## Project Structure

```
.
├── .github/
│ └── workflows/
│ ├── test.yml # CI/CD test workflow
│ └── auto-setup.yml # Installation handler workflow
├── src/
│ ├── index.ts # Main worker code
│ └── index.test.ts # Test suite
├── wrangler.toml # Cloudflare Worker configuration
├── tsconfig.json # TypeScript configuration
├── vitest.config.ts # Vitest configuration
├── package.json # Dependencies and scripts
├── SECURITY.md # Security documentation
└── README.md # This file
```

## Environment Variables

### Cloudflare Worker Secrets (via `wrangler secret put`)

- `AUTOMATION_REPO_TRIGGER_TOKEN`: GitHub Personal Access Token for triggering repository_dispatch events
- `GITHUB_WEBHOOK_SECRET`: Webhook secret for verifying GitHub webhook signatures (must match the secret configured in GitHub App settings)

### GitHub Repository Configuration (in `rithviknishad/leaderboard-bot` repository settings)

**Variables** (Settings → Secrets and variables → Actions → Variables):
- `LEADERBOARD_BOT_ID`: GitHub App ID

**Secrets** (Settings → Secrets and variables → Actions → Secrets):
- `LEADERBOARD_BOT_PRIVATE_KEY`: GitHub App private key (PEM format)

### Target Repository Configuration (automatically set by the workflow)

When the bot is installed on a repository, the workflow automatically sets:

**Variables**:
- `LEADERBOARD_BOT_ID`: GitHub App ID (same as above)

**Secrets**:
- `LEADERBOARD_BOT_PRIVATE_KEY`: GitHub App private key (same as above)

## Troubleshooting

### Worker returns "missing AUTOMATION_REPO_TRIGGER_TOKEN"

Make sure you've set the secret:

```bash
pnpm wrangler secret put AUTOMATION_REPO_TRIGGER_TOKEN
```

### Worker returns "invalid signature" (401)

This means the webhook signature verification failed. Check that:
- You've set the `GITHUB_WEBHOOK_SECRET` in Wrangler: `pnpm wrangler secret put GITHUB_WEBHOOK_SECRET`
- The secret matches exactly what you configured in your GitHub App webhook settings
- The request is actually coming from GitHub (not a test request without proper signature)

### Worker returns "missing x-hub-signature-256 header" (401)

The webhook request is missing the signature header. This typically means:
- The request is not coming from GitHub
- You need to configure a webhook secret in your GitHub App settings

### GitHub API returns 401 Unauthorized

Check that your token has the correct permissions:
- `repo` scope
- Access to the target repository

### Events are being ignored

Verify that:
- The `x-github-event` header is set to `installation` or `installation_repositories`
- The request body contains valid JSON
- The webhook signature is valid

## License

MIT