A GitHub App that automatically reviews pull requests using Google Gemini AI. When a PR is opened, synchronised, or reopened, the bot fetches the diff, sends it to Gemini for analysis, and posts a structured code review comment.
- Features
- Architecture
- Prerequisites
- 1. Create a GitHub App
- 2. Generate a Private Key
- 3. Environment Variables
- 4. Running Locally
- 5. Expose Localhost for Webhooks
- 6. Install the App on a Repository
- 7. Running Tests
- 8. Docker Deployment
- Project Structure
- 🔍 Automated Code Review — Reviews every PR diff using the Gemini 1.5 Flash model
- 🛡️ Signature Verification — Validates GitHub webhook signatures for security
- 🤖 Bot Filtering — Ignores PR events created by other bots
- 🔁 Duplicate Detection — Skips review if the bot has already commented
- ⚡ Async Processing — Returns 200 immediately, processes the review in the background
- 🐳 Docker Ready — Multi-stage Dockerfile with non-root user and health checks
- ✅ CI/CD — GitHub Actions pipeline for linting, testing, and Docker build validation
GitHub PR Event
│
▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Webhook │────▶│ GitHub │────▶│ Gemini │
│ Handler │ │ Module │ │ Module │
│ (verify sig) │ │ (fetch diff) │ │ (AI review) │
└──────────────┘ └──────────────┘ └──────────────┘
│ │
▼ │
┌──────────────┐ │
│ Post Comment │◀────────────┘
│ on PR │
└──────────────┘
- Node.js ≥ 20
- npm ≥ 9
- A GitHub account with permission to create GitHub Apps
- A Google Gemini API key — get one at https://aistudio.google.com/apikey
- Go to GitHub → Settings → Developer Settings → GitHub Apps → New GitHub App
- Fill in the details:
- Name:
your-pr-review-bot(must be globally unique) - Homepage URL:
https://github.com/yourusername/pr-review-bot - Webhook URL:
https://your-domain.com/webhook(use smee.io or ngrok for local dev — see step 5) - Webhook secret: Generate a strong random string and save it
- Name:
- Permissions:
- Pull requests: Read & Write
- Contents: Read-only
- Issues: Read & Write (needed for posting comments)
- Subscribe to events:
- ✅ Pull request
- Where can this app be installed? — "Only on this account" (for development)
- Click Create GitHub App
- Note the App ID shown on the app settings page
- On the GitHub App settings page, scroll to Private keys
- Click Generate a private key
- A
.pemfile will be downloaded — keep it safe - You'll reference this key in the environment variable
GITHUB_PRIVATE_KEY
Copy the example file and fill in your values:
cp .env.example .env| Variable | Description |
|---|---|
GITHUB_APP_ID |
The numeric App ID from your GitHub App settings |
GITHUB_PRIVATE_KEY |
The full PEM private key string (replace newlines with \n) |
GITHUB_WEBHOOK_SECRET |
The webhook secret you set when creating the app |
GEMINI_API_KEY |
Your Google Gemini API key |
PORT |
Server port (default: 3000) |
Tip: To convert your .pem file to a single-line env var:
awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' private-key.pem# Install dependencies
npm install
# Start in development mode (hot-reload)
npm run devThe server starts at http://localhost:3000. Verify with:
curl http://localhost:3000/health
# → {"status":"ok","timestamp":"..."}GitHub needs to reach your local server. Use one of these tools:
# Install the smee client
npm install -g smee-client
# Create a channel at https://smee.io and use the URL
smee -u https://smee.io/YOUR_CHANNEL_ID -t http://localhost:3000/webhookSet your GitHub App webhook URL to the smee.io URL.
ngrok http 3000Set your GitHub App webhook URL to the ngrok HTTPS URL + /webhook.
- Go to your GitHub App's settings page
- Click Install App in the sidebar
- Choose your account and select the repository you want to test with
- Confirm the installation
- Open a pull request on that repository — the bot will automatically post a review!
# Run all tests
npm test
# Run with coverage
npx jest --coverage
# Run a specific test file
npx jest tests/gemini.test.ts# Build and run with docker-compose
docker-compose up --build
# Or build the image directly
docker build -t pr-review-bot .
docker run --env-file .env -p 3000:3000 pr-review-botpr-review-bot/
├── src/
│ ├── index.ts # Express server entry point
│ ├── webhook.ts # Webhook handler & event routing
│ ├── github.ts # Octokit client & GitHub API calls
│ ├── gemini.ts # Gemini API client & prompt logic
│ └── config.ts # Environment variable validation
├── tests/
│ ├── gemini.test.ts # Prompt & response formatting tests
│ ├── github.test.ts # API call parameter tests
│ └── webhook.test.ts # Event routing & filtering tests
├── .github/workflows/
│ └── ci.yml # CI: lint, test, docker build
├── Dockerfile # Multi-stage production build
├── docker-compose.yml # Docker Compose config
├── .env.example # Example environment variables
├── package.json # Dependencies & scripts
├── tsconfig.json # TypeScript configuration
└── README.md # This file
When the bot reviews a PR, it posts a comment that looks like:
Found issue in
src/handler.tsline 42...No issues found.
Consider renaming the variable...
This review was generated automatically. Please use your own judgment.
MIT