Skip to content

condevtools/pr-agent

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

60 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PR Agent

AI-powered code review service built with TypeScript + NestJS. This repository is now a pnpm monorepo: the backend service lives in backend/, and the Next.js frontend lives in frontend/.

中文文档

Table of Contents


Beta Status

  • PR Agent is currently in beta.
  • The only officially supported integration mode is GitHub App.
  • Plain GitHub Webhook and GitLab code paths may still exist in the repository, but they are not part of the supported deployment surface right now.

Features

Core Review

  • Automatic AI code review on PR open / update / merge
  • Inline comments with GitHub Suggested Changes
  • Report-mode summaries with risk assessment
  • Incremental review (only new commits since last review)
  • Mermaid change-structure diagrams in reports (directory/file visualization)
  • Secret leak detection in diffs (lightweight regex-based scanning)
  • Auto-labeling (bugfix / feature / refactor / docs / security)

Interactive Commands

  • /ai-review — trigger manual review (comment or report mode)
  • /ask <question> — multi-turn Q&A about the code
  • /checks [question] — diagnose CI failures
  • /generate_tests [focus] — generate test code
  • /changelog [--apply] — generate or commit changelog
  • /describe [--apply] — generate or update PR description
  • /improve [focus] — force improvement-focused review output
  • /add_doc [focus] (/add-doc) — documentation-only review suggestions
  • /reflect [goal] — ask AI to generate requirement/acceptance clarifying questions
  • /similar_issue [query] (/similar-issue) — find related issues in the same repository
  • /custom_prompt <prompt> — run a custom AI prompt against PR changes
  • /help_docs <question> — ask questions about project documentation (/docs directory)
  • /analyze — list all changed components with risk assessment
  • /compliance [focus] — compliance and security review
  • /improve_component <component> — improvement review scoped to a specific component
  • /generate_labels — auto-generate and apply PR labels from diff content
  • /similar_code [query] — detect duplicate or similar code patterns in diff
  • /auto_approve — conditional auto-approve based on AI risk assessment (default off)
  • /scan_repo_discussions — extract best practices from recent merged PR discussions
  • /feedback — provide learning signals to improve future reviews

Process Guardrails

  • .pr-agent.yml per-repo policy (remind or enforce mode)
  • Issue & PR template completeness checks
  • GitHub Check integration for branch protection (enforce mode)
  • Process guideline detection (.github/.gitlab workflows, templates, CODEOWNERS, CONTRIBUTING) with compliance suggestions
  • Issue creation/edit pre-check and PR pre-merge validation (GitHub)
  • Default issue auto-triage (feasibility + suggestions + similar issues + labels) when .pr-agent.yml is absent

Current Support

  • GitHub App only
  • Plain GitHub Webhook — unsupported in the current beta
  • GitLab Webhook — unsupported in the current beta
  • GitHub Actions — not supported

Multi-Provider AI

  • OpenAI
  • OpenAI-compatible (DeepSeek, etc.)
  • Anthropic (Claude)
  • Google Gemini

Review Triggers

Trigger Mode Dedup Window
PR opened (opened) comment / report (per config) 5 min
PR updated (synchronize) comment / report 5 min (per new commit SHA)
PR edited (edited) comment / report 5 min
PR merged (closed + merged) report 24h (configurable)
/ai-review comment command comment / report 5 min
/ai-review report report 5 min
/ai-review comment comment 5 min
Webhook header x-ai-mode (GitLab only, unsupported in current beta) report / comment 5 min
Issue created / edited pre-check (GitHub) + default auto-triage when policy file is missing 5 min
PR created / edited / synced pre-merge check (GitHub)

Roadmap & Process Assets

  • Competitive gap backlog: docs/roadmap/2026-02-19-competitive-gap-backlog.md
  • GitHub issue templates: .github/ISSUE_TEMPLATE/bug_report.md, .github/ISSUE_TEMPLATE/feature_request.md
  • GitHub PR template: .github/pull_request_template.md
  • GitLab issue templates: .gitlab/issue_templates/Bug.md, .gitlab/issue_templates/Feature.md
  • GitLab MR template: .gitlab/merge_request_templates/default.md

Recommended GitHub Flow baseline:

  1. Enable branch protection — require PR Agent Policy check and CI to pass.
  2. Set mode: enforce in .pr-agent.yml (start with core repositories, then roll out).
  3. Use standardized issue/PR templates to prevent missing requirements and test plans.

Architecture

Repository Topology

graph LR
    ROOT[pr-agent monorepo]
    ROOT --> BE[backend/<br/>NestJS + Probot + tests]
    ROOT --> FE[frontend/<br/>Next.js marketing / console]
    ROOT --> OPS[Docker / Compose<br/>backend deployment]
    ROOT --> NP[Nixpacks<br/>frontend deployment]
    ROOT --> DOCS[docs/<br/>roadmaps and process assets]
Loading

High-Level Overview

graph TB
    subgraph Platforms
        GH_APP[GitHub App<br/>Probot]
        GH_WH[GitHub Webhook]
        GL_WH[GitLab Webhook]
    end

    subgraph NestJS Application
        direction TB
        CTRL[Controllers<br/>Route & Validate]
        SVC[Services<br/>Signature Verify & Dispatch]
        INT[Integration Layer<br/>GitHub / GitLab Adapters]
        RE[Review Engine<br/>AI Reviewer + Patch Parser]
        RR[Report Renderer<br/>Markdown + Suggestions]
    end

    subgraph External
        AI[AI Providers<br/>OpenAI / Anthropic / Gemini]
        GH_API[GitHub API]
        GL_API[GitLab API]
        NOTIFY[Notifications<br/>Slack / Discord / WeChat]
    end

    GH_APP -->|Webhook Event| CTRL
    GH_WH -->|Webhook Event| CTRL
    GL_WH -->|Webhook Event| CTRL
    CTRL --> SVC
    SVC --> INT
    INT --> RE
    RE -->|LLM Call| AI
    RE --> RR
    RR -->|Post Comment / Report| GH_API
    RR -->|Post Comment / Report| GL_API
    INT -.->|Optional| NOTIFY
Loading

Request Processing Flow

sequenceDiagram
    participant P as Platform (GitHub/GitLab)
    participant C as Controller
    participant S as Service
    participant D as Deduplication
    participant I as Integration
    participant A as AI Reviewer
    participant R as Report Renderer

    P->>C: Webhook Event
    C->>S: Validate signature & parse payload
    S->>D: Check dedup (FNV hash, 5min window)
    alt Duplicate
        D-->>S: Skip (already processed)
    else New request
        D-->>S: Proceed
        S->>I: Dispatch to platform handler
        I->>I: Fetch diff, file contents, policy
        I->>A: Send context + diff to AI model
        A-->>I: Structured review result (Zod-validated)
        I->>R: Format report / inline comments
        R->>P: Post review via API
        I-->>P: Optional notification webhook
    end
Loading

Module Dependency Graph

graph LR
    subgraph NestJS Modules
        APP[AppModule]
        GH[GithubModule]
        GL[GitlabModule]
        GHA[GithubAppModule]
    end

    subgraph Integration Layer
        GHR[github-review]
        GHW[github-webhook]
        GHP[github-policy]
        GHC[github-content]
        GLR[gitlab-review]
        NTF[notification]
    end

    subgraph Core
        REV[ai-reviewer]
        PAT[patch parser]
        RPT[report-renderer]
        POL[review-policy]
        DDP[dedupe]
        HTTP[http client]
        STA[runtime-state]
        SEC[secret-patterns]
        CACHE[cache]
    end

    APP --> GH
    APP --> GL
    APP --> GHA

    GH --> GHR
    GH --> GHW
    GHA --> GHR

    GHR --> GHP
    GHR --> GHC
    GHR --> REV
    GHR --> RPT
    GHR --> NTF

    GLR --> REV
    GLR --> RPT
    GLR --> NTF
    GL --> GLR

    REV --> PAT
    REV --> POL
    REV --> HTTP

    GHR --> DDP
    GLR --> DDP
    DDP --> STA
    GHR --> SEC
    GLR --> SEC
    GHP --> CACHE
Loading

Detailed Request Flow

The following diagram traces every request path — from webhook entry through event routing, command parsing, the common review engine, and output delivery.

flowchart LR
    subgraph E["Entry Endpoints (NestJS + Probot)"]
        E1["/api/github/webhooks<br/>GithubAppBootstrapService"]
        E2["/github/trigger<br/>GithubWebhookController"]
        E3["/gitlab/trigger<br/>GitlabWebhookController"]
        E4["/github/replay/:eventId<br/>/gitlab/replay/:eventId"]
        E5["/health /metrics /webhook/events"]
    end

    subgraph GHA["GitHub App Event Routing (backend/src/app.ts)"]
        A1["issues.opened, issues.edited<br/>runGitHubIssuePolicyCheck"]
        A2["pull_request.opened, edited, synchronize<br/>runGitHubPullRequestPolicyCheck"]
        A3["resolveGitHubPullRequestAutoReviewPolicy"]
        A4["pull_request.closed (merged)<br/>resolveGitHubReviewBehaviorPolicy"]
        A5["issue_comment.created (PR + Issue)<br/>handleGitHubIssueCommentCommand"]
        A6["pull_request_review_thread<br/>recordGitHubFeedbackSignal"]
    end

    subgraph GHW["Plain GitHub Webhook (backend/src/integrations/github/github-webhook.ts)"]
        B1["handlePlainGitHubWebhook"]
        B2["verifyWebhookSignature + payload schema"]
        B3["pull_request / issues / issue_comment / review_thread dispatch"]
        B4["runGitHubPullRequestPolicyCheck + runGitHubIssuePolicyCheck"]
        B5["handleGitHubIssueCommentCommand"]
    end

    subgraph GLW["GitLab Webhook (backend/src/integrations/gitlab/gitlab-review.ts)"]
        C1["runGitLabWebhook"]
        C2["verify token + payload schema"]
        C3["handleGitLabMergeRequestWebhook"]
        C4["handleGitLabNoteWebhook"]
        C5["resolveGitLabReviewPolicy (.pr-agent.yml)"]
    end

    subgraph CMD["Command Parsing Surface"]
        D1["parseReviewCommand"]
        D2["parseAsk / parseMention / parseChecks / parseGenerateTests"]
        D3["parseDescribe / parseChangelog"]
        D4["parseImprove / parseAddDoc / parseReflect / parseSimilarIssue / parseFeedback"]
    end

    subgraph CORE["Common Review Engine"]
        R1["runGitHubReview / runGitLabReview"]
        R2["dedupe + rate-limit + incremental head + feedback signals"]
        R3["collect context: diff/files/ci/policy"]
        R4["analyzePullRequest / answerPullRequestQuestion"]
        R5["patch parser + hunk prioritize + line mapping"]
        R6["secret scan + auto label"]
    end

    subgraph OUT["Output + Ops"]
        O1["buildReportCommentMarkdown"]
        O2["buildIssueCommentMarkdown"]
        O3["createComment / notes / managed upsert"]
        O4["publishNotification (optional)"]
        O5["pr_agent_* metrics + replay store"]
    end

    E1 --> A1
    E1 --> A2 --> A3 --> R1
    E1 --> A4 --> R1
    E1 --> A5
    E1 --> A6

    E2 --> B1 --> B2 --> B3
    B3 --> B4 --> R1
    B3 --> B5

    E3 --> C1 --> C2
    C2 --> C3 --> C5 --> R1
    C2 --> C4 --> C5

    A5 --> D1
    A5 --> D2
    A5 --> D3
    A5 --> D4
    B5 --> D1
    B5 --> D2
    B5 --> D3
    B5 --> D4
    C4 --> D1
    C4 --> D2
    C4 --> D3
    C4 --> D4

    D1 --> R1
    D2 --> R4
    D3 --> R4
    D4 --> R1

    R1 --> R2 --> R3 --> R4 --> R5
    R4 --> R6
    R5 --> O1 --> O3
    R5 --> O2 --> O3
    R6 --> O3
    O3 --> O4

    E4 --> B1
    E4 --> C1
    E5 --> O5
    E2 --> O5
    E3 --> O5
    O3 -. feedback signals .-> R2
Loading

Tech Stack

Layer Technology
Runtime Node.js 22 (Alpine)
Language TypeScript 5.7 (ES2022, strict mode)
Framework NestJS 11
HTTP Server Express 4
GitHub App Probot 13
AI Client OpenAI SDK 4 (also used for compatible providers)
Validation Zod 3
State Store In-memory / JSON file / SQLite (Node.js built-in node:sqlite)
Container Docker (multi-stage build)

Project Structure

pr-agent/
├── backend/
│   ├── src/
│   │   ├── main.ts                 # NestJS bootstrap & server startup
│   │   ├── app.ts                  # Probot event handlers (GitHub App)
│   │   ├── app.module.ts           # Root NestJS module
│   │   ├── common/                 # Filters and shared request types
│   │   ├── core/                   # Runtime state, cache, env, i18n, HTTP
│   │   ├── integrations/           # GitHub / GitLab / notify adapters
│   │   ├── modules/                # NestJS webhook, health, replay modules
│   │   └── review/                 # AI review engine and report rendering
│   ├── tests/                      # Backend test suite
│   ├── package.json
│   └── tsconfig.json
├── frontend/
│   ├── app/                        # Next.js App Router pages and layouts
│   ├── components/                 # Frontend UI components
│   ├── public/                     # Static assets
│   ├── package.json
│   └── next.config.ts
├── docs/                           # Product docs, roadmaps, process assets
├── data/                           # Local/runtime persisted state mount
├── secrets/                        # Local private key mount (not committed)
├── Dockerfile                      # Backend container image
├── docker-compose.yml              # Backend deployment and local ops
├── nixpacks.toml                   # Root Nixpacks entry for frontend
├── package.json                    # Workspace scripts
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── turbo.json
├── README-zh.md
└── README.md

Workspace Notes

  • The repository root .env is shared by local backend development and Docker Compose.
  • backend/ is the deployable review service. frontend/ is deployed separately when using root nixpacks.toml.
  • Persistent backend state defaults to /data/pr-agent/... inside containers and data/pr-agent/... on the host.

Backend Path Aliases

The backend package uses Node.js ESM subpath imports (configured in backend/tsconfig.json and backend/package.json):

Alias Maps to
#core backend/src/core/index.ts
#review backend/src/review/index.ts
#integrations/github backend/src/integrations/github/index.ts
#integrations/gitlab backend/src/integrations/gitlab/index.ts
#integrations/notify backend/src/integrations/notify/index.ts

Getting Started

Prerequisites

  • Node.js >= 22
  • pnpm >= 10

Local Development

# Install workspace dependencies
pnpm install

# Prepare env file at repository root
cp .env.example .env

# Start backend locally (reads ../.env from backend package)
pnpm dev:backend

# Start frontend locally
pnpm dev:frontend

# Build backend for production
pnpm --filter backend build

# Start built backend
pnpm --filter backend start

The backend listens on port 3000 by default (configurable via PORT). The frontend also defaults to 3000 when run separately.

Health Check

curl http://localhost:3000/health
curl http://localhost:3000/health?deep=true   # Tests AI provider connectivity
curl http://localhost:3000/github/health       # GitHub config status

Configuration

Environment Variables

Copy .env.example and fill in the required values. The supported minimal configuration is:

  • .env.github-app.min.example — GitHub App minimum

Legacy minimal examples for plain GitHub Webhook and GitLab remain in the repository for reference only; they are not part of the supported beta deployment path.

AI Provider

graph LR
    ENV[AI_PROVIDER env var]
    ENV -->|openai| OAI[OpenAI<br/>OPENAI_API_KEY + OPENAI_MODEL]
    ENV -->|openai-compatible| OC[OpenAI-Compatible<br/>OPENAI_BASE_URL + OPENAI_COMPATIBLE_MODEL]
    ENV -->|anthropic| ANT[Anthropic<br/>ANTHROPIC_API_KEY + ANTHROPIC_MODEL]
    ENV -->|gemini| GEM[Gemini<br/>GEMINI_API_KEY + GEMINI_MODEL]
Loading

OpenAI (default)

AI_PROVIDER=openai
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4.1-mini

OpenAI-Compatible (e.g., DeepSeek)

AI_PROVIDER=openai-compatible
OPENAI_BASE_URL=https://api.deepseek.com/v1
OPENAI_COMPATIBLE_API_KEY=...
OPENAI_COMPATIBLE_MODEL=deepseek-chat

Anthropic

AI_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...
ANTHROPIC_MODEL=claude-3-5-haiku-latest
ANTHROPIC_MAX_TOKENS=8192

Gemini

AI_PROVIDER=gemini
GEMINI_API_KEY=...
GEMINI_MODEL=gemini-2.0-flash

State Persistence

Backend Env Value Use Case
Memory memory (default) Stateless containers, dev
JSON File file Simple single-instance
SQLite sqlite (recommended) Production single-instance
RUNTIME_STATE_BACKEND=sqlite
RUNTIME_STATE_SQLITE_FILE=/data/pr-agent/runtime-state.sqlite3

Notifications (Optional)

Supports WeChat (WeCom), Slack, Discord, and generic JSON webhooks:

NOTIFY_WEBHOOK_URL=https://hooks.slack.com/services/...
NOTIFY_WEBHOOK_FORMAT=slack   # wecom | slack | discord | generic

Key Tuning Parameters

AI provider tuning

Variable Default Description
AI_HTTP_TIMEOUT_MS 30000 (30s) HTTP timeout for AI review requests
AI_ASK_HTTP_TIMEOUT_MS 60000 (60s) HTTP timeout for /ask command (longer for multi-turn Q&A)
AI_HTTP_RETRIES 2 Number of retries on transient AI provider failures
AI_HTTP_RETRY_BACKOFF_MS 400 Retry backoff base delay for AI provider requests (ms)
AI_MAX_CONCURRENCY 4 Max concurrent AI requests
AI_MAX_QUEUE_SIZE 200 Max queued AI requests before rejecting new work
AI_SHUTDOWN_DRAIN_TIMEOUT_MS 15000 (15s) Graceful shutdown drain timeout for in-flight AI tasks
AI_DEBUG_LOGS false Log AI request/response payloads for debugging
HEALTHCHECK_AI_TIMEOUT_MS 5000 (5s) Timeout for deep health check AI probe
HEALTHCHECK_AI_LIVE_PROBE false Perform actual API call for GET /health?deep=true instead of config-only check

AI_CONCURRENCY_LIMIT is no longer used. Use AI_MAX_CONCURRENCY and AI_MAX_QUEUE_SIZE instead.

Global runtime and command limits

Variable Default Description
WEBHOOK_BODY_LIMIT 1mb Global Express body-parser limit for webhook requests (returns 413 when exceeded)
COMMAND_RATE_LIMIT_MAX 10 Max command invocations per user per PR/MR per window
COMMAND_RATE_LIMIT_WINDOW_MS 3600000 (1h) Command rate-limit window

GitHub-specific

Variable Default Description
GITHUB_MERGED_DEDUPE_TTL_MS 86400000 (24h) Dedup window for merged + report events
GITHUB_FEEDBACK_SIGNAL_TTL_MS 2592000000 (30d) Feedback signal retention window
GITHUB_INCREMENTAL_STATE_TTL_MS 604800000 (7d) Incremental review SHA cache lifetime
GITHUB_POLICY_CONFIG_CACHE_TTL_MS 300000 (5min) .pr-agent.yml cache for policy/review behavior
GITHUB_POLICY_COMMENT_DEDUPE_TTL_MS 600000 (10min) Dedup window for policy reminder comments
GITHUB_ISSUE_AUTO_TRIAGE_ENABLED true Enable default issue auto-triage on issues.opened/edited when no .pr-agent.yml exists
GITHUB_ISSUE_AUTO_TRIAGE_AUTO_LABELS true Add inferred labels for default issue auto-triage
GITHUB_ISSUE_AUTO_TRIAGE_DEDUPE_TTL_MS 300000 (5min) Dedup window for issue auto-triage comments
GITHUB_ISSUE_AUTO_TRIAGE_SIMILAR_LIMIT 5 Max number of similar issues shown in auto-triage output
GITHUB_ISSUE_TRIAGE_DISABLE_AI false Skip AI call and use fallback triage summary only
GITHUB_WEBHOOK_MAX_BODY_BYTES 10485760 (10MB) Extra hard cap for /github/trigger payload size
GITHUB_WEBHOOK_SKIP_SIGNATURE false Debug-only signature bypass; forbidden when NODE_ENV=production

GitLab-specific

Variable Default Description
GITLAB_MERGED_DEDUPE_TTL_MS 86400000 (24h) Merged + report event dedup window
GITLAB_INCREMENTAL_STATE_TTL_MS 604800000 (7d) Incremental review SHA cache
GITLAB_FEEDBACK_SIGNAL_TTL_MS 2592000000 (30d) Feedback learning signal retention
GITLAB_POLICY_CONFIG_CACHE_TTL_MS 300000 (5min) .pr-agent.yml policy cache
GITLAB_CHANGELOG_PATH CHANGELOG.md File path for /changelog --apply
GITLAB_WEBHOOK_MAX_BODY_BYTES 10485760 (10MB) Extra hard cap for /gitlab/trigger payload size
GITLAB_REQUIRE_WEBHOOK_SECRET false Require GITLAB_WEBHOOK_SECRET, otherwise reject unsigned webhooks
ALLOW_INSECURE_GITLAB_HTTP false Allow http:// GitLab base URL for local testing only

Tuning guidance:

  • MERGED_DEDUPE_TTL_MS — Controls the dedup window for merged + report events to prevent duplicate reviews on webhook retries. Increase to 48h–72h if you experience frequent webhook redelivery; decrease to 1h–6h if you need faster re-trigger. This only affects merged auto-triggers; manual /ai-review commands use the short (5 min) dedup window.
  • FEEDBACK_SIGNAL_TTL_MS — Controls how long /feedback and review-thread resolved/unresolved signals are retained. Increase to 60–90d for teams with slower review cadence; decrease to 7–14d if review rules change frequently.
  • COMMAND_RATE_LIMIT_* — Controls abuse protection for comment commands. Increase limits for very active repos; lower limits if bots/users spam command threads.

See .env.example for the baseline variable reference; advanced runtime knobs are listed above.


Deployment

Docker (Recommended)

graph LR
    subgraph Docker Build
        B1[Stage 1: Build<br/>node:22-alpine<br/>pnpm install + backend build]
        B2[Stage 2: Runtime<br/>node:22-alpine<br/>prod deps only]
        B1 -->|COPY dist/| B2
    end
    B2 -->|Expose 3000| SRV[pr-agent container]
Loading

Build & Run

docker build -t pr-agent:latest .
docker run -d \
  --name pr-agent \
  -p 3000:3000 \
  --env-file .env \
  -v ./data:/data \
  pr-agent:latest

Docker Compose

# Start
docker compose up -d --build

# View logs
docker compose logs -f pr-agent

# Restart
docker compose restart pr-agent

# Stop
docker compose down

The docker-compose.yml mounts:

  • ./data:/data — persistent state (SQLite, event store)
  • ./secrets/github-app.private-key.pem:/run/secrets/github-app-private-key.pem:ro — GitHub App private key

Nixpacks (Frontend Only)

The root nixpacks.toml is for deploying frontend/ from the repository root. It does not build or start the backend service.

  • Install: pnpm install --frozen-lockfile
  • Build: pnpm --filter frontend build
  • Start: pnpm --filter frontend start

Production Deployment Checklist

graph TD
    A[Choose Platform Mode] -->|GitHub App| B1[Create GitHub App]
    A -->|Plain Webhook| B2[Generate PAT Token]
    A -->|GitLab| B3[Generate API Token]

    B1 --> C[Configure AI Provider]
    B2 --> C
    B3 --> C

    C --> D[Set State Backend = sqlite]
    D --> E[Deploy Container]
    E --> F[Configure Webhook URL]
    F --> G[Verify Health Endpoints]
    G --> H[Test with /ai-review Command]
Loading
  1. Use GitHub App integration mode — this is the only supported integration in the current beta
  2. Configure AI provider — Set AI_PROVIDER and the corresponding API key / model
  3. Enable state persistence — Use RUNTIME_STATE_BACKEND=sqlite for production
  4. Deploy the container — Docker, Docker Compose, Render, Railway, Fly.io, or K8s
  5. Set webhook URL to https://<domain>/api/github/webhooks
  6. Verify via health endpoints and a test /ai-review comment

Quick Deployment Reference

This is a compact deployment path for Render/Railway/Fly.io/Docker/K8s.

  1. Use GitHub App mode
  2. Use minimal environment variables

GitHub App minimum (.env.github-app.min.example)

APP_ID=123456
PRIVATE_KEY_PATH=/run/secrets/github-app-private-key.pem
# PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\\n...\\n-----END RSA PRIVATE KEY-----\\n"
WEBHOOK_SECRET=replace-with-webhook-secret
AI_PROVIDER=openai
OPENAI_API_KEY=replace-with-openai-key
OPENAI_MODEL=gpt-4.1-mini

Recommended single-instance extras

RUNTIME_STATE_BACKEND=sqlite
RUNTIME_STATE_SQLITE_FILE=/data/pr-agent/runtime-state.sqlite3
WEBHOOK_EVENT_STORE_ENABLED=false
WEBHOOK_REPLAY_ENABLED=false

Temporary replay settings for debugging

WEBHOOK_EVENT_STORE_ENABLED=true
WEBHOOK_REPLAY_ENABLED=true
WEBHOOK_REPLAY_TOKEN=replace-with-strong-random-token
  1. Start backend application
pnpm install --frozen-lockfile
pnpm --filter backend build
pnpm --filter backend start

The backend listens on PORT (default 3000).

  1. Configure webhook address
    • GitHub App: https://<domain>/api/github/webhooks
  2. Docker one-liner
docker build -t pr-agent:latest .
docker run -d --name pr-agent -p 3000:3000 --env-file .env pr-agent:latest
  1. Verification checklist
    • GET /health
    • GET /github/health
    • GET /metrics
    • Test PR/MR commands: /ai-review, /ai-review comment
    • Webhook failure response includes structured fields: error/type/status/path/method/timestamp

If replay is enabled:

  • GET /webhook/events
  • POST /github/replay/:eventId
  • Header: x-pr-agent-replay-token: <WEBHOOK_REPLAY_TOKEN>

Nginx Reverse Proxy

There is no committed deploy/nginx/ sample in this repository; use the snippet below as a baseline:

server {
    listen 443 ssl;
    server_name pr-agent.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Platform Integration

GitHub App (Only Supported Mode)

  1. Create a GitHub App with the following permissions:
    • Pull requests: Read & write
    • Issues: Read & write
    • Contents: Read & write (required for /changelog --apply)
    • Checks: Read & write (required for mode=enforce)
    • Metadata: Read-only
  2. Subscribe to events:
    • Pull request (opened / edited / synchronize / closed)
    • Issues (opened / edited)
    • Issue comment
    • Pull request review thread (resolved / unresolved, for feedback learning)
  3. Set webhook URL to https://<domain>/api/github/webhooks
  4. Configure environment variables:
APP_ID=123456
PRIVATE_KEY_PATH=/run/secrets/github-app-private-key.pem
# PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----\n"
WEBHOOK_SECRET=your-webhook-secret
  • GitHub App enablement condition (see backend/src/modules/github-app/github-app.bootstrap.service.ts): APP_ID + (PRIVATE_KEY or PRIVATE_KEY_PATH) + WEBHOOK_SECRET.
  • docker-compose.yml mounts the private key at ./secrets/github-app.private-key.pem:/run/secrets/github-app-private-key.pem:ro. If secrets/ or the PEM file is missing, docker compose up will fail.
  • Recommended local prep: mkdir -p secrets data. Docker usually auto-creates data, but pre-creating it is more predictable.

If APP_ID + PRIVATE_KEY (+ WEBHOOK_SECRET) are not configured, GitHub App mode is disabled and the beta deployment is considered incomplete.

Unsupported Integrations In Current Beta

  • Plain GitHub Webhook is not a supported deployment target right now.
  • GitLab Webhook is not a supported deployment target right now.

Commands

All commands are triggered via PR/MR comments. Commands marked with (PR only) require Pull Request context (diff, CI checks) and will not work in Issue comments.

Command Description
/ai-review (PR only) Trigger AI review (defaults to report when no mode is provided)
/ai-review report (PR only) Force report mode (summary comment)
/ai-review comment (PR only) Force comment mode (inline comments)
/ai-review --mode=report / --mode=comment (PR only) Flag-style mode override (same effect as positional mode)
/ask <question> Ask about the PR or Issue (multi-turn conversation)
@bot-name <question> @mention the bot to ask a question (set GITHUB_APP_SLUG or GITHUB_BOT_LOGIN)
/checks [question] (PR only) Analyze CI check failures
/generate_tests [focus] (PR only) Generate test code for changes
/changelog [focus] (PR only) Generate changelog entry
/changelog --apply [focus] (PR only) Generate and commit changelog to repo
/describe (PR only) Generate PR/MR description
/describe --apply (PR only) Generate and update PR/MR description
/improve [focus] (PR only) Run review in improvement-only mode
/add_doc [focus] / /add-doc [focus] (PR only) Generate documentation-only suggestions
/reflect [goal] (PR only) Generate clarifying requirement/acceptance questions
/similar_issue [query] / /similar-issue [query] Search related issues in the same repository
/custom_prompt <prompt> (PR only) Run a custom AI prompt against PR changes
/help_docs <question> Ask questions about project documentation (/docs directory)
/analyze (PR only) List all changed components with risk assessment
/compliance [focus] (PR only) Compliance and security review
/improve_component <component> (PR only) Improvement review scoped to a specific component
/generate_labels (PR only) Auto-generate and apply PR labels from diff content
/similar_code [query] (PR only) Detect duplicate or similar code patterns in diff
/auto_approve (PR only) Conditional auto-approve based on AI risk assessment (default off)
/scan_repo_discussions (PR only) Extract best practices from recent merged PR discussions
/feedback resolved|dismissed|up|down [note] Provide review quality feedback

Additional aliases are supported, for example: /ai-review ask ..., /ai-review checks ..., /ai-review generate-tests ..., /ai-review add-doc .... Policy toggles in .pr-agent.yml exist for /describe, /ask, /checks, /generate_tests, /changelog, /feedback, /improve, /add_doc, /custom_prompt, /help_docs, /analyze, /compliance, /similar_code, /auto_approve, /scan_repo_discussions; /reflect depends on askCommandEnabled; /improve_component depends on improveCommandEnabled; /generate_labels depends on autoLabelEnabled.

Note: /ask, /feedback, /similar_issue, /help_docs, and @mention work in both Issue and PR comments. For Issue comments, no diff or CI context is provided, but the Issue title and body are passed to the AI as context. Set GITHUB_APP_SLUG (GitHub App slug) or GITHUB_BOT_LOGIN (exact bot login) to enable @mention detection. Mentions with and without the [bot] suffix are both supported.


Repository Policy

Add .pr-agent.yml to the repository root to configure per-repo behavior:

mode: remind          # remind = comment only, enforce = fail GitHub Check

issue:
  enabled: true
  minBodyLength: 20
  requiredSections:
    - Summary
    - Steps to Reproduce
    - Expected Behavior

pullRequest:
  enabled: true
  minBodyLength: 20
  requireLinkedIssue: false
  requiredSections:
    - Summary
    - Test Plan

review:
  enabled: true
  mode: comment         # comment | report
  onOpened: true        # Review on PR open
  onEdited: false
  onSynchronize: true   # Review on new commits
  describeEnabled: true
  describeAllowApply: false
  checksCommandEnabled: true
  includeCiChecks: true
  askCommandEnabled: true
  generateTestsCommandEnabled: true
  changelogCommandEnabled: true
  changelogAllowApply: false
  feedbackCommandEnabled: true
  improveCommandEnabled: true
  addDocCommandEnabled: true
  customPromptCommandEnabled: true
  helpDocsCommandEnabled: true
  analyzeCommandEnabled: true
  complianceCommandEnabled: true
  similarCodeCommandEnabled: true
  autoApproveCommandEnabled: false   # default off for safety
  scanRepoDiscussionsCommandEnabled: true
  secretScanEnabled: true
  autoLabelEnabled: true
  secretScanCustomPatterns:  # optional extra secret regex patterns
    - "(?i)my_internal_token_[a-z0-9]{16,}"
  customRules:
    - All public APIs must have type annotations
    - No new `any` types allowed

GitLab currently reads only the review: section from .pr-agent.yml. Top-level mode, issue, and pullRequest checks are enforced in GitHub policy flows.

Modes:

  • remind — posts a comment noting missing fields; does not block merge
  • enforce — creates a failing GitHub Check (PR Agent Policy) that can be required in branch protection rules

Template fallback behavior:

  • When requiredSections is not configured, section headings are automatically extracted from repository templates:
    • Issue: .github/ISSUE_TEMPLATE/* or .github/ISSUE_TEMPLATE.md
    • PR: .github/pull_request_template.md or .github/PULL_REQUEST_TEMPLATE.md
  • If no templates exist, built-in defaults are used (Issue: Summary / Steps to Reproduce / Expected Behavior; PR: Summary / Test Plan / Related Issue).

Review field reference:

Field Description
enabled / mode Enable AI review and set default mode (comment / report)
onOpened / onEdited / onSynchronize Control which PR events auto-trigger review
describeEnabled Enable /describe command
describeAllowApply Allow /describe --apply to directly update PR description
checksCommandEnabled Enable /checks command
includeCiChecks Include CI check results in AI context
askCommandEnabled Enable /ask command
generateTestsCommandEnabled Enable /generate_tests command
changelogCommandEnabled Enable /changelog command
changelogAllowApply Allow /changelog --apply to commit directly to the repo
feedbackCommandEnabled Enable /feedback command
improveCommandEnabled Enable /improve command
addDocCommandEnabled Enable /add_doc (/add-doc) command
customPromptCommandEnabled Enable /custom_prompt command
helpDocsCommandEnabled Enable /help_docs command
analyzeCommandEnabled Enable /analyze command
complianceCommandEnabled Enable /compliance command
similarCodeCommandEnabled Enable /similar_code command
autoApproveCommandEnabled Enable /auto_approve command (default off for safety)
scanRepoDiscussionsCommandEnabled Enable /scan_repo_discussions command
secretScanEnabled Scan diffs for potential secret leaks and post security warnings
secretScanCustomPatterns Additional repository-specific secret regex patterns
autoLabelEnabled Auto-add PR labels based on change content
customRules Team-specific review rules (natural language); enforced in both reviews and Q&A

Observability

Metrics

Prometheus-format metrics are exposed at GET /metrics:

  • pr_agent_webhook_requests_total — webhook request count by platform & event
  • pr_agent_webhook_results_total — results by platform & outcome (ok/error)
  • pr_agent_webhook_replay_total — replay execution outcomes
  • pr_agent_webhook_store_writes_total — persisted debug-event write count
  • pr_agent_webhook_store_trim_total — debug-event store trim operations
  • pr_agent_health_checks_total — health endpoint call count
  • pr_agent_http_errors_total — global HTTP error count
  • pr_agent_process_uptime_seconds — process uptime
  • pr_agent_ai_requests_active — active AI request count
  • pr_agent_ai_wait_queue_size — queued AI request count
  • pr_agent_ai_shutdown_requested — AI shutdown flag (0/1)
  • pr_agent_runtime_state_backend_info{backend=...} — selected runtime-state backend info gauge

Health Checks

Endpoint Purpose
GET /health Liveness probe
GET /health?deep=true Deep check (AI provider connectivity)
GET /github/health GitHub webhook config validation
GET /gitlab/health Legacy GitLab webhook config validation (unsupported in current beta)

Error Handling

Webhook errors return structured JSON. Known webhook errors (e.g. BadWebhookRequestError, WebhookAuthError) include a descriptive message; unrecognized internal errors are sanitized to "internal server error" to prevent information leakage.

{
  "ok": false,
  "error": "webhook secret verification failed",
  "type": "WebhookAuthError",
  "status": 401,
  "path": "/github/trigger",
  "method": "POST",
  "timestamp": "2026-01-01T00:00:00.000Z"
}

Payloads exceeding WEBHOOK_BODY_LIMIT (default 1mb) return 413 Payload Too Large.

Webhook Replay (Debug)

Enable temporarily for debugging:

WEBHOOK_EVENT_STORE_ENABLED=true
WEBHOOK_REPLAY_ENABLED=true
WEBHOOK_REPLAY_TOKEN=your-secret-token

Endpoints (require x-pr-agent-replay-token header):

  • GET /webhook/events — list stored events
  • POST /github/replay/:eventId — replay a GitHub event
  • POST /gitlab/replay/:eventId — replay a GitLab event

Resilience

  • HTTP Retry: exponential backoff (2 retries, 400ms base delay) on 408/429/5xx
  • Deduplication: FNV hash with 5-min window (24h for merged events)
  • Rate Limiting: per-scope limits to prevent API abuse
  • Graceful Shutdown: drains in-flight requests on SIGTERM/SIGINT

Testing

# Backend tests
pnpm test:backend

# Backend coverage
pnpm --filter backend test:coverage

# Backend type check
pnpm --filter backend check

# Frontend production build check
pnpm --filter frontend build

Backend tests use the Node.js built-in test runner (node:test). Recommended regression coverage includes:

  • AI concurrency control
  • Cache & dedup behavior
  • Diff parsing & hunk prioritization
  • GitHub/GitLab integration logic
  • HTTP retry & error handling
  • Policy validation
  • Notification adapters
  • NestJS module wiring

License

Private — see repository for details.

About

AI-powered code review bot for GitHub & GitLab — supports OpenAI, Anthropic, Gemini, and OpenAI-compatible providers. Built with TypeScript + NestJS.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Languages