Init
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
# gitea-pr-review-bot
|
||||
|
||||
Central webhook service that reviews Gitea pull requests using the Cursor SDK and posts a full Gitea review (summary + inline comments).
|
||||
|
||||
This bot is designed to run once for many repositories in `Bram/*` instead of duplicating workflows in every repo.
|
||||
|
||||
## What This Bot Does
|
||||
|
||||
- Listens to Gitea webhook events.
|
||||
- Triggers on:
|
||||
- `pull_request` with action `opened`
|
||||
- `pull_request_review_request` with action `review_requested` when requested reviewer is the bot user
|
||||
- Loads PR metadata and changed files from Gitea.
|
||||
- Builds a review prompt (including optional repo-specific rule files).
|
||||
- Calls Cursor Cloud Agent (`Agent.prompt`) for structured review output.
|
||||
- Validates and posts a single consolidated Gitea review.
|
||||
- Removes itself from requested reviewers after successful review.
|
||||
- Prevents duplicate processing by dedupe key:
|
||||
- `{owner}/{repo}#{pr_number}#{head_sha}`
|
||||
|
||||
## High-Level Flow
|
||||
|
||||
1. `src/server.ts` receives webhook payload.
|
||||
2. `src/webhook/verify-signature.ts` validates HMAC (`WEBHOOK_SECRET`).
|
||||
3. `src/webhook/event-router.ts` accepts or ignores event by type/action.
|
||||
4. `src/run/review-runner.ts` orchestrates full review run.
|
||||
5. `src/config/load-repo-config.ts` loads optional per-repo overrides.
|
||||
6. `src/gitea/client.ts` fetches PR + files and writes reviews.
|
||||
7. `src/prompt/build-review-prompt.ts` assembles review instructions/context.
|
||||
8. `src/cursor/review-agent.ts` invokes Cursor SDK in cloud mode.
|
||||
9. `src/cursor/review-schema.ts` validates structured JSON response.
|
||||
10. `src/gitea/review-api.ts` posts review and handles inline comment fallback.
|
||||
11. `src/gitea/reviewer-api.ts` removes bot reviewer from PR.
|
||||
|
||||
## Project Structure
|
||||
|
||||
### Server and Webhook Layer
|
||||
|
||||
- `src/server.ts`
|
||||
- HTTP server, `/healthz`, `/webhooks/gitea`
|
||||
- Signature check + event routing + response codes
|
||||
- `src/webhook/verify-signature.ts`
|
||||
- SHA256 HMAC validation with timing-safe compare
|
||||
- `src/webhook/event-router.ts`
|
||||
- Converts raw webhook headers/payload into supported routed events
|
||||
|
||||
### Domain Logic
|
||||
|
||||
- `src/domain/should-process-event.ts`
|
||||
- Loop guard (skip bot-originated events)
|
||||
- Repo enable/disable check
|
||||
- Label skip logic
|
||||
- Base branch filtering
|
||||
- `src/domain/dedupe-store.ts`
|
||||
- In-memory TTL dedupe store for idempotency
|
||||
|
||||
### Gitea Integration
|
||||
|
||||
- `src/gitea/client.ts`
|
||||
- Typed wrapper around Gitea REST endpoints
|
||||
- Pull details/files/reviews, create/delete review, patch pull
|
||||
- Optional content-file loading from repository
|
||||
- `src/gitea/review-api.ts`
|
||||
- Delete prior bot reviews
|
||||
- Post one consolidated review
|
||||
- Validate inline comments against changed-file paths and positions
|
||||
- Summary-only fallback if inline set is invalid
|
||||
- `src/gitea/reviewer-api.ts`
|
||||
- Remove bot from requested reviewers list
|
||||
|
||||
### Cursor Integration
|
||||
|
||||
- `src/cursor/review-agent.ts`
|
||||
- Calls Cursor SDK `Agent.prompt` in cloud runtime
|
||||
- Enforces review timeout
|
||||
- Extracts text from SDK response formats
|
||||
- `src/cursor/review-schema.ts`
|
||||
- Zod schema for strict review JSON contract:
|
||||
- `verdict`, `event`, `body`, `comments[]`
|
||||
|
||||
### Prompting and Config
|
||||
|
||||
- `src/prompt/build-review-prompt.ts`
|
||||
- Builds complete PR review prompt from title/body/files/patches/rules
|
||||
- `src/config/load-repo-config.ts`
|
||||
- Reads `.gitea/pr-review-bot.yml` when present
|
||||
- Loads optional repo-local rule files:
|
||||
- `AGENTS.md`
|
||||
- `docs/pr-review.md`
|
||||
- `.cursor/skills/pr-review/SKILL.md`
|
||||
- `.cursor/skills/pr-review/gitea.md`
|
||||
|
||||
### Orchestration and Utilities
|
||||
|
||||
- `src/run/review-runner.ts`
|
||||
- Main end-to-end review execution
|
||||
- Dedupe, retry wrappers, posting, reviewer self-removal
|
||||
- `src/run/retry.ts`
|
||||
- Exponential backoff retry helper for transient failures
|
||||
- `src/types/events.ts`
|
||||
- Gitea webhook payload typings
|
||||
|
||||
### Scripts and Deployment
|
||||
|
||||
- `scripts/dry-run.ts`
|
||||
- Manual run by `owner/repo/pr`
|
||||
- `Dockerfile`
|
||||
- Production container image
|
||||
- `docker-compose.yml`
|
||||
- Local/hosted compose deployment
|
||||
- `docs/setup.md`
|
||||
- Installation and webhook setup
|
||||
- `docs/operations.md`
|
||||
- Runtime behavior, failure handling, rollback
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Required:
|
||||
|
||||
- `CURSOR_API_KEY`
|
||||
- `GITEA_TOKEN`
|
||||
- `GITEA_BASE_URL`
|
||||
- `GITEA_BOT_LOGIN`
|
||||
- `WEBHOOK_SECRET`
|
||||
- `PORT`
|
||||
|
||||
Optional:
|
||||
|
||||
- `DEFAULT_BASE_BRANCH` (default: `main`)
|
||||
- `MAX_INLINE_COMMENTS` (default: `5`)
|
||||
- `REVIEW_TIMEOUT_MS` (default: `120000`)
|
||||
- `DEDUPE_TTL_SECONDS` (default: `1800`)
|
||||
|
||||
See `.env.example`.
|
||||
|
||||
## Review Output Contract
|
||||
|
||||
The Cursor response must be strict JSON:
|
||||
|
||||
- `verdict`: `approve | request_changes | comment`
|
||||
- `event`: `APPROVE | REQUEST_CHANGES | COMMENT`
|
||||
- `body`: string
|
||||
- `comments`: array of:
|
||||
- `path` (changed file path)
|
||||
- `new_position` (integer >= 1)
|
||||
- `body` (comment text)
|
||||
|
||||
Post-validation rules:
|
||||
|
||||
- Invalid path/position in inline comments => post summary-only review.
|
||||
- Inline comments are clamped to configured maximum.
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. Copy env template:
|
||||
- `cp .env.example .env`
|
||||
2. Fill secrets/tokens.
|
||||
3. Install:
|
||||
- `npm install`
|
||||
4. Run locally:
|
||||
- `npm run dev`
|
||||
5. Verify health:
|
||||
- `curl http://localhost:8787/healthz`
|
||||
|
||||
## Useful Commands
|
||||
|
||||
- Type check: `npm run check`
|
||||
- Build: `npm run build`
|
||||
- Start built app: `npm run start`
|
||||
- Dry run: `npm run dry-run -- <owner> <repo> <pr_number> [head_sha]`
|
||||
|
||||
## Operational Notes
|
||||
|
||||
- Keep bot credentials scoped to least privilege.
|
||||
- Do not log tokens or raw auth headers.
|
||||
- Dedupe is in-memory (resets on restart).
|
||||
- Best deployment model is a central service with org-level webhook and per-repo opt-out config.
|
||||
Reference in New Issue
Block a user