Convex GitHub

Sync GitHub issues and pull requests into Convex via webhooks, then query, create, comment, close, and merge them directly from Convex functions.

Installation

npm install convex-github

About Convex GitHub

convex-github maintains a live, queryable mirror of GitHub issues and pull requests inside an isolated Convex component schema, kept current via verified GitHub webhooks. It exposes actions for creating issues, posting comments, closing issues, and merging pull requests through the GitHub REST API, with changes written to Convex immediately rather than waiting for webhook round-trips. Webhook deliveries are deduplicated by X-GitHub-Delivery ID and verified via HMAC-SHA256, making retries safe.

Benefits

Use cases

how to sync GitHub issues into a Convex database reactively

convex-github mounts a webhook handler at any HTTP route in your Convex deployment. Every issues and pull_request event from GitHub is verified by HMAC-SHA256 signature, deduplicated by delivery ID, and upserted into the component's isolated issues or pullRequests table. Your React app can then call useQuery on listIssuesByRepo or listPullRequestsByRepo and re-render live without polling.

open GitHub issues from Convex backend functions

The GitHub client exposed by convex-github includes a createIssue action that calls the GitHub REST API and immediately records the new issue in Convex without waiting for the webhook round-trip. You call it from a Convex action with owner, repo, title, and optional body, labels, and assignees arguments, and it returns the issue number and URL.

merge pull requests programmatically from a Convex action

convex-github exposes a mergePullRequest method you call from a Convex action with owner, repo, pullNumber, and an optional mergeMethod of merge, squash, or rebase. It fetches the PR to get its internal ID, merges it via the REST API, and immediately patches the merged and state fields in Convex so your queries reflect the result before the webhook arrives.

verify GitHub webhook signatures in Convex HTTP actions

The webhookHandler property of the GitHub client is a Convex httpAction that performs constant-time HMAC-SHA256 verification against the X-Hub-Signature-256 header before processing any event. You mount it on any route in your Convex HTTP router, and it rejects requests that fail signature verification before writing anything to the database.

Frequently asked questions

Does convex-github add tables to my app's schema?

No. convex-github is a Convex component, so its issues, pullRequests, and webhookEvents tables live in an isolated schema namespace separate from your app's convex/schema.ts. You access them only through the functions the component exposes, and they will never collide with your own table names.

What happens if GitHub retries a webhook delivery that already succeeded?

convex-github records every delivery by its X-GitHub-Delivery header ID in the webhookEvents table before processing it. If a retry arrives with the same delivery ID, the handler recognizes it as a duplicate and skips the write, so no issue or pull request row is double-processed.

Which GitHub webhook events does convex-github handle?

The handler processes issues events (opened, edited, labeled, assigned, closed, reopened, and others) and pull_request events (opened, edited, closed, reopened, synchronize, and others). Other event types such as push, star, and release pass signature verification and idempotency recording but are otherwise ignored, so you can subscribe to additional events on the same webhook without needing a new endpoint.

What GitHub token scopes does convex-github require?

convex-github accepts a personal access token, a fine-grained token, or a GitHub App installation token. The token needs issues and pull_requests scopes on the repositories you want to manage. You set it as a Convex environment variable named GITHUB_TOKEN using npx convex env set.

How are issues and pull requests identified internally in convex-github?

Records are keyed by GitHub's globally unique numeric id field, stored as a string in issueId and pullRequestId fields. The issue or PR number is also stored but is only unique within a single repository, so convex-github uses the global id for indexing and deduplication while the number field is available for display and lookup by repo plus number.

Links