GitHub App demo: ingest repository snapshots and incremental file exports for Search/RAG workflows.
- Python 3.11+
giton yourPATH- ngrok (for receiving GitHub webhooks locally)
- A GitHub account and an existing repository to use as the demo target
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .envEdit .env with your app credentials and target repo (see Configuration).
uvicorn app.main:app --reload --port 8000Verify:
curl http://localhost:8000/health
# {"status":"ok"}Interactive API docs: http://localhost:8000/docs
- Open New GitHub App (personal account).
- GitHub App name: e.g.
GithubPull Demo(must be unique on GitHub). - Homepage URL:
http://localhost:8000(placeholder is fine for a demo). - Webhook
- Active: checked
- Webhook URL:
https://<your-ngrok-subdomain>.ngrok-free.app/webhook(set after ngrok is running; see below) - Webhook secret: generate a random string → copy into
.envasWEBHOOK_SECRET
- Permissions → Repository permissions
- Contents: Read-only
- Metadata: Read-only (often auto-selected)
- Pull requests: Read-only
- Subscribe to events
InstallationPushPull request
- Where can this GitHub App be installed? Only on this account (enough for a single-repo demo).
- Click Create GitHub App.
- On the app settings page, note the App ID →
APP_IDin.env. - Generate a private key → downloads a
.pemfile → save as e.g../github-app.pem(already in.gitignore). - Set
PRIVATE_KEY_PATH=./github-app.pemin.env.
In .env:
REPO_OWNER=your-github-username
REPO_NAME=your-existing-repoOnly webhooks for this repository are processed; all others return 200 and are logged as ignored.
In a second terminal:
ngrok http 8000Copy the HTTPS forwarding URL (e.g. https://abc123.ngrok-free.app) and set the app Webhook URL to:
https://abc123.ngrok-free.app/webhook
Save the app settings. GitHub sends a ping event; your server should log webhook ping ok.
Note: Free ngrok URLs change each session unless you use a reserved domain. Update the GitHub App webhook URL whenever ngrok restarts.
- App settings → Install App → install on your account.
- Select Only select repositories → choose the repo matching
REPO_OWNER/REPO_NAME. - Confirm install.
- Ensure
uvicornis running and ngrok is forwarding to port 8000. - GitHub App settings → Advanced → Recent Deliveries.
- Open a delivery → Redeliver and check your terminal logs.
Expected logs:
ping→webhook ping ok- Events for other repos →
ignored event=... - Events for your repo →
accepted event=...andinstallation token minted...(if credentials are set)
| Variable | Description |
|---|---|
APP_ID |
GitHub App ID |
PRIVATE_KEY_PATH |
Path to the app private key .pem |
WEBHOOK_SECRET |
Webhook secret from GitHub App settings |
REPO_OWNER |
Allowlisted repository owner |
REPO_NAME |
Allowlisted repository name |
| Method | Path | Description |
|---|---|---|
GET |
/health |
Liveness check |
POST |
/webhook |
GitHub webhook receiver (signature required) |
POST |
/debug/snapshot?installation_id= |
Manual full snapshot (no webhook) |
Manual snapshot example (find installation ID in the app’s install URL or webhook payload):
# Query param or INSTALLATION_ID in .env
curl -X POST "http://localhost:8000/debug/snapshot?installation_id=12345678"pip install -r requirements.txt
pytestdata/{owner}__{repo}/
git/ # bare clone
state.json # default_branch, last_exported_sha
snapshots/{sha}/files/ # full snapshot (install)
updates/{sha}/files/ # push incremental export
prs/{number}/{head_sha}/files/
| Issue | Feature |
|---|---|
| #1 | Bootstrap service |
| #2 | Operator runbook (this README) |
| #3 | Webhook ingress ✓ |
| #4 | Installation snapshot ✓ |
| #5 | Push incremental export ✓ |
| #6 | PR export ✓ |
| #7 | Debug snapshot endpoint ✓ |
second pr export test line