DEV Community

Luna Commsnet
Luna Commsnet

Posted on

Building a Gitea-First Code Review Tool in Go

Building a Gitea-First Code Review Tool in Go


1. The Problem: Gitea Has No Code Review Automation

If you self-host Gitea, you already know why: it's lightweight, fast, and doesn't require a GitHub enterprise budget. But there's a gap. GitHub has CodeRabbit, Graphite, and GitHub's own Copilot code review. GitLab has its own analysis. Gitea? Nothing.

You're left with two options:

  1. Manual review — read every diff yourself, every time
  2. CI-only checks — linting and tests run in Actions/Act Runner, but nobody looks at the semantic content of changes

Neither catches what a good code review catches: security vulnerabilities introduced in a PR, hardcoded secrets, deprecated patterns, or logic bugs that pass linting.

That's why I built Repository Detective — a Gitea-first code review tool that combines deterministic scanners with optional LLM analysis.


2. Architecture: Deterministic First, LLM Second

The key design decision: deterministic scanners run first, LLM analysis runs second on flagged files only.

This isn't "AI reviews your code." It's "scanners find candidates, then LLM validates and explains them with proof-of-concept."

Why This Order Matters

Approach Problem
LLM-only Hallucinations, no verifiable evidence, vibes-based findings
Scanner-only No context, false positives, developer ignores noisy alerts
Scanner → LLM Scanners find real candidates, LLM validates and writes PoC

Pipeline Stages

Push/PR → Webhook → Diff Extraction
                           ↓
                    Stage 1: Deterministic Scanners
                    (Trivy, Grype, golangci-lint, ruff, shellcheck)
                           ↓
                    Stage 2: LLM Analysis (optional, off by default)
                    (OpenAI-compatible endpoint, only on flagged files)
                           ↓
                    Stage 3: Issue Creation
                    (Gitea issues with severity, file:line, code snippet, PoC)
Enter fullscreen mode Exit fullscreen mode

3. Tech Stack

Component Choice Why
Language Go Single binary, fast, Gitea is Go too
Webhooks Native Gitea webhook Push and PR events
Scanners Trivy, Grype, golangci-lint, ruff, shellcheck Best-in-class, open source
LLM Any OpenAI-compatible endpoint Privacy: runs on your infrastructure
Container Docker + docker-compose Easy self-hosted deploy
License AGPL-3.0 Community open source, commercial tiers available

4. Quick Start

# docker-compose.minimal.yml — included in repo
version: "3.8"
services:
  repository-detective:
    image: ghcr.io/commstech/repository-detective:latest
    ports:
      - "8080:8080"
    environment:
      - GITEA_URL=https://your-gitea-instance.com
      - GITEA_TOKEN=your-webhook-secret
      - WEBHOOK_SECRET=your-webhook-secret
    volumes:
      - ./data:/app/data
Enter fullscreen mode Exit fullscreen mode
# 1. Start the container
docker compose up -d

# 2. Add webhook in Gitea repo settings
#    URL: http://your-server:8080/webhook
#    Content type: application/json
#    Secret: your-webhook-secret
#    Trigger: Push events, Pull request events

# 3. Push code. Issues appear automatically.
Enter fullscreen mode Exit fullscreen mode

5. What It Catches

Example Finding (created as Gitea issue)

🔍 Repository Detective Finding
Severity: HIGH
File: internal/auth/handler.go
Line: 47

Issue: API token compared with == instead of hmac.Equal
       This allows timing side-channel attacks.

Evidence:
  if r.Header.Get("Authorization") == expectedToken {

Proof of Concept:
  An attacker can measure response time differences
  to brute-force the token character by character.

Recommended Fix:
  if hmac.Equal([]byte(r.Header.Get("Authorization")),
                 []byte(expectedToken)) {
Enter fullscreen mode Exit fullscreen mode

This is the kind of finding that scanners alone miss (it's not a known CVE pattern) and LLM-only tools hallucinate (without scanner context). The combination catches real issues with verifiable evidence.


6. Privacy-First Design

  • LLM is off by default. You can run scanner-only mode with zero external API calls.
  • When LLM is enabled, it only sends flagged file diffs (not your entire codebase) to the endpoint you configure.
  • Self-hosted LLM supported. Point it at your local Ollama, vLLM, or any OpenAI-compatible server. Your code never leaves your infrastructure.
  • No telemetry, no phone-home, no analytics. Repository Detective doesn't report back anywhere.

7. Open Core Model

Tier Price Features
Community Free (AGPL-3.0) All scanners, webhook integration, Gitea issues, single repo
Pro $100/instance/month Multi-repo, custom scanner configs, Slack/Discord notifications, priority fixes
Enterprise Contact us SSO/OIDC, audit trail, on-prem LLM bundle, custom integrations, SLA

The community tier is fully functional. No paywalled security features. The paid tiers add convenience and scale.


8. Roadmap

  • [x] Gitea webhook integration (push + PR)
  • [x] Trivy, Grype, golangci-lint, ruff, shellcheck
  • [x] Optional LLM analysis with PoC generation
  • [x] Gitea issue creation with severity tagging
  • [x] Docker deployment
  • [ ] GitHub support (next priority)
  • [ ] Slack/Discord/Telegram notifications (Pro tier)
  • [ ] Multi-repo dashboard (Pro tier)
  • [ ] SSO/OIDC (Enterprise tier)
  • [ ] SBOM generation and drift detection

9. Links


10. Feedback Wanted

I'm building this because Gitea users deserve code review tooling too. If you self-host Gitea, I want to know:

  1. What scanners would you add to the pipeline?
  2. Does the LLM-optional approach work for your security posture?
  3. What's missing for you to deploy this today?

Open issues on GitHub or start a discussion. I'm actively developing based on user feedback.


Repository Detective is AGPL-3.0 open source. Self-host your code review.

Top comments (0)