revbot (portmanteau from review and robot) runs Semgrep (https://semgrep.dev) against the source branch of every open merge request in a GitLab project or group, then posts the findings as inline comments on the lines that were actually modified by the MR.
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-06-10 14:50:28 +02:00
.forgejo/workflows chore: add release workflow 2026-04-18 11:38:27 +02:00
.gitignore feature: initial working version 2026-04-18 11:18:22 +02:00
app.go feat: adds all-issues flag 2026-06-10 14:50:28 +02:00
diff.go feature: initial working version 2026-04-18 11:18:22 +02:00
git.go feature: initial working version 2026-04-18 11:18:22 +02:00
gitlab.go feat: adds all-issues flag 2026-06-10 14:50:28 +02:00
go.mod feature: initial working version 2026-04-18 11:18:22 +02:00
go.sum feature: initial working version 2026-04-18 11:18:22 +02:00
LICENSE.txt add license 2026-04-18 19:26:13 +02:00
main.go feat: adds all-issues flag 2026-06-10 14:50:28 +02:00
README.md doc: add mascot at README.md 2026-04-18 19:59:31 +02:00
revbot_mascot.png doc: add mascot at README.md 2026-04-18 19:59:31 +02:00
semgrep.go feature: initial working version 2026-04-18 11:18:22 +02:00

revbot

The revbot mascot

revbot runs Semgrep against the source branch of every open merge request in a GitLab project or group, then posts the findings as inline comments on the lines that were actually modified by the MR.

How it works

  1. List MRs — fetches all open merge requests for the given project or group via the GitLab API.
  2. Extract modified lines — parses the unified diff of each MR to identify the exact line numbers added by that MR. Findings on context or removed lines are ignored.
  3. Clone & scan — shallow-clones the MR source branch into a temporary directory and runs semgrep scan with the provided configuration.
  4. Post comments — for each Semgrep finding that falls on a modified line, posts an inline discussion note on the MR. If a note from revbot already exists on that line it is skipped, so re-running the tool is safe and idempotent.
  5. Clean up — the temporary clone is removed after each MR regardless of outcome.

Requirements

  • Go 1.25+ (to build from source)
  • git in PATH
  • semgrep in PATH (1.x recommended)
  • A GitLab personal access token with the api scope

Installation

git clone <this repo>
cd revbot
go build -o revbot .

Usage

revbot --token TOKEN --project PROJECT --semgrep-config CONFIG [options]
revbot --token TOKEN --group   GROUP   --semgrep-config CONFIG [options]

--project and --group are mutually exclusive.

Flags

Flag Required Default Description
--token yes GitLab personal access token (api scope)
--project one of Project ID or path, e.g. mygroup/myrepo
--group one of Group ID or path; scans every project in the group
--semgrep-config yes Path to a Semgrep YAML rules file
--gitlab-url no https://gitlab.com Base URL for self-hosted GitLab instances

Examples

Scan all open MRs in a single project:

revbot \
  --token        glpat-xxxx \
  --project      mygroup/myrepo \
  --semgrep-config .semgrep/rules.yaml

Scan all open MRs across an entire group:

revbot \
  --token        glpat-xxxx \
  --group        mygroup \
  --semgrep-config .semgrep/rules.yaml

Point at a self-hosted GitLab instance:

revbot \
  --gitlab-url   https://gitlab.mycompany.com \
  --token        glpat-xxxx \
  --project      mygroup/myrepo \
  --semgrep-config .semgrep/rules.yaml

Comment format

Each comment is prefixed with an invisible HTML marker (<!-- revbot -->) that revbot uses to detect its own previous comments. The visible content shows the rule ID, the finding message, and the offending code snippet:

**[python.lang.security.audit.exec-detected]** Use of exec detected.
exec(user_input)

Idempotency

Running revbot multiple times against the same MR is safe. Before posting, the tool fetches all existing notes on the MR and skips any file+line combination that already carries a revbot comment. This means it will not flood a MR with duplicate annotations if triggered repeatedly.