GitLab code review tracking for scientific software
Project description
glreview
Track code review coverage with git-level precision. Know exactly which modules have been reviewed, at which commit, and what changed since.
The Problem
Code review is usually per-PR, but that doesn't answer: "Has this module ever been thoroughly reviewed?" Teams maintaining critical software need to know:
- Which files have never been reviewed?
- Which reviews are stale because the code changed?
- How much of the codebase has review coverage?
glreview tracks review status per-module, persisted in git, integrated with GitLab issues.
What It Looks Like
$ glreview status
Review Status
─────────────────────────────────────────────────────
Reviewed: 12 modules (2,450 lines) ██████████░░ 48%
In Progress: 2 modules (380 lines)
Needs Review: 11 modules (1,890 lines)
Stale (changed since review):
src/core/engine.py changed 3 days ago
src/utils/helpers.py changed 1 week ago
In Progress:
src/api/handlers.py issue #142, @alice
Needs Review:
src/auth/oauth.py 245 lines
src/core/scheduler.py 189 lines
src/api/middleware.py 156 lines
Installation
Prerequisites: Python 3.9+, git repository, GitLab project
pip install glreview
For AI-assisted review features, also install Claude Code.
Quick Start
1. Configure source patterns
Add to pyproject.toml:
[tool.glreview]
sources = ["src/**/*.py"]
exclude = ["**/test_*.py", "**/_version.py"]
2. Set up GitLab authentication
export GITLAB_PRIVATE_TOKEN=glpat-xxxxxxxxxxxx
# For self-hosted GitLab:
export GITLAB_URL=https://gitlab.example.com
3. Initialize
glreview init
This creates .glreview/registry.json. Commit it to version control.
4. Start reviewing
# See what needs review
glreview status
# Start a review (creates GitLab issue)
glreview start src/mymodule.py --assignee @reviewer
# After reviewer closes the issue, sign off
glreview signoff src/mymodule.py
# Commit the updated registry
git add .glreview/ && git commit -m "review: src/mymodule.py"
Core Workflow
Review lifecycle
┌─────────────┐
│ needs_review│◄──────────────────┐
└──────┬──────┘ │
│ start │ cancel (or code changes)
▼ │
┌─────────────┐ │
│ in_progress │───────────────────┤
└──────┬──────┘ │
│ signoff │
▼ │
┌─────────────┐ │
│ reviewed │───────────────────┘
└─────────────┘
Starting a review
# Basic - creates GitLab issue
glreview start src/module.py
# With assignee
glreview start src/module.py --assignee @alice
# Link to existing issue instead of creating new
glreview start src/module.py --issue "https://gitlab.com/.../issues/42"
Signing off
# Standard signoff (verifies GitLab issue is closed)
glreview signoff src/module.py
# Skip issue verification
glreview signoff src/module.py --skip-verify
# With explicit reviewer name
glreview signoff src/module.py --reviewer @bob
Handling changes during review
If code changes while a review is in progress:
# See what changed
glreview diff src/module.py --since-start
# Option 1: Acknowledge changes and sign off anyway
glreview signoff src/module.py --acknowledge
# Option 2: Cancel and restart at current commit
glreview cancel src/module.py --restart
Viewing diffs
# Changes since last review (deciding whether to re-review)
glreview diff src/module.py
# Changes during current review (before signing off)
glreview diff src/module.py --since-start
# Open in GitLab web UI
glreview diff src/module.py --web
AI-Assisted Review (Optional)
glreview integrates with Claude Code for automated code analysis. This is entirely optional - the core workflow works without it.
Setup
# Verify Claude CLI is installed
claude --version
# Generate project context (one-time)
glreview claude-init
This creates .glreview/context.json with project conventions, module relationships, and test file mappings. Commit it to version control.
Running AI review
# Run review and post findings to GitLab issue
glreview claude-review src/module.py
# Print findings to terminal only (don't post)
glreview claude-review src/module.py --no-post
# Preview the prompt without running
glreview claude-review src/module.py --dry-run
Reviews evaluate six criteria:
- Correctness - Logic errors, wrong results, unhandled edge cases
- Error Handling - Input validation, failure handling, resource leaks
- Code Quality - DRY, organization, naming, appropriate abstractions
- Testing - Coverage, meaningful assertions, edge cases
- Documentation - Non-obvious decisions explained, API documented
- Risk - Security, performance, data integrity (when applicable)
Each finding is rated OK, SUGGESTED, or REQUIRED.
Fixing issues
# Interactive - choose which items to fix
glreview claude-fix src/module.py
# Batch - fix all REQUIRED items automatically
glreview claude-fix src/module.py --batch
# Create a merge request with the fixes
glreview claude-fix src/module.py --batch --create-mr
# Specify a target branch for the MR
glreview claude-fix src/module.py --batch --create-mr --target-branch develop
The --create-mr flag automates the full workflow: creates a branch (fix/review-{module}-{issue}), commits the changes, pushes to origin, and opens a GitLab merge request that references the review issue. In interactive mode, you'll be prompted to confirm before the MR is created.
Updating context
# After significant codebase changes
glreview claude-sync
# View context for a module
glreview claude-context src/module.py
Batch Operations
Start reviews for multiple modules at once:
# Start reviews for all modules needing review
glreview batch-start
# Preview what would happen
glreview batch-start --dry-run
# Also run Claude review for each (posts to issues)
glreview batch-start --claude-review
CI Integration
Validate review coverage in your pipeline with glreview ci. No push tokens or git plumbing required — the registry is committed by developers as part of their normal workflow.
Setup
- Keep
.glreview/committed in your repo (runglreview synclocally when adding/removing source files) - Add to
.gitlab-ci.yml:
review:
stage: review
image: python:3.12
script:
- pip install glreview
- glreview ci --report REVIEW_COVERAGE.md
artifacts:
paths:
- REVIEW_COVERAGE.md
Run glreview ci-config for a complete example including release gates.
Enforcing coverage
# Block releases without 100% review coverage
glreview ci --fail-under 100
Staleness checks
# Fail if reviewed files have changed since last review
glreview check
Configuration Reference
Full pyproject.toml options:
[tool.glreview]
# Source file patterns (required)
sources = ["src/**/*.py", "lib/**/*.py"]
# Patterns to exclude
exclude = ["**/test_*.py", "**/_version.py", "**/conftest.py"]
# Registry file location (default: .glreview/registry.json)
registry = ".glreview/registry.json"
# Default labels for created issues
issue_labels = ["review::pending", "team::backend"]
# Custom issue template (Jinja2)
issue_template = ".glreview/issue_template.md"
# Reviewer teams (use with --assignee @team/security)
[tool.glreview.teams]
security = ["@alice", "@bob"]
frontend = ["@carol", "@dave"]
# Custom instructions injected into Claude prompts (optional)
[tool.glreview.claude]
fix_instructions = """
After making fixes:
- Run `python -m pytest tests/ -x` to verify nothing is broken
- Run `ruff check src/` for lint compliance
"""
review_instructions = """
This project uses numpy-style docstrings.
All public functions must have type annotations.
"""
Custom issue templates
Create a Jinja2 template with access to these variables:
| Variable | Description |
|---|---|
path |
Module path |
lines |
Line count |
current_commit |
Current git commit |
previous_commit |
Last reviewed commit (re-reviews) |
diff_url |
GitLab compare URL (re-reviews) |
classes |
List of public classes |
functions |
List of public functions |
Commands
| Command | Description |
|---|---|
init |
Initialize glreview in a project |
status |
Show review progress and what needs attention |
start PATH |
Start a review, create GitLab issue |
signoff PATH |
Sign off on completed review |
cancel PATH |
Cancel review (--restart to restart at HEAD) |
diff PATH |
Show changes since last review |
sync |
Sync registry with filesystem changes |
list |
List all tracked modules |
report |
Generate coverage report (markdown/json/badge) |
ci |
Run sync + coverage check for CI pipelines |
check |
CI check for changes to reviewed files |
batch-start |
Start reviews for all pending modules |
reviewers |
List configured reviewers |
ci-config |
Print recommended CI configuration |
claude-review PATH |
Run AI code review |
claude-fix PATH |
Fix issues from AI review (--create-mr to open MR) |
claude-init |
Generate AI project context |
claude-sync |
Update AI context |
claude-context |
View AI context |
Use glreview COMMAND --help for detailed options.
Troubleshooting
"Module not found in registry"
Run glreview sync to add new files, or check your sources patterns in pyproject.toml.
"GitLab API not available"
Set GITLAB_PRIVATE_TOKEN. For self-hosted GitLab, also set GITLAB_URL.
"Issue not closed"
Close the GitLab issue before signing off. Use --skip-verify to bypass this check.
"File changed during review"
Code was modified after start. Use --acknowledge to sign off anyway, or cancel --restart to restart.
Claude commands not working Install Claude Code CLI: https://claude.ai/code
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file glreview-0.5.1.tar.gz.
File metadata
- Download URL: glreview-0.5.1.tar.gz
- Upload date:
- Size: 133.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7fc1888ebbbcb1de8ab3ef5168e0dbb5f52e580c912168a80a8a9422c4da0915
|
|
| MD5 |
287d3c89dca63092a18721833f70e211
|
|
| BLAKE2b-256 |
7d9508543f26e3b4d306bc657aaa48128ff10edac8dc4003edaec1afd1c4a0b3
|
File details
Details for the file glreview-0.5.1-py3-none-any.whl.
File metadata
- Download URL: glreview-0.5.1-py3-none-any.whl
- Upload date:
- Size: 70.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a3b2ffe7a9289c82673918581db814ee55a40f0be4e093dcc44d011168a56444
|
|
| MD5 |
4870b5a258837689636063f2816db62d
|
|
| BLAKE2b-256 |
04b03b95255054f3563bf57bac78588db07675d26bb04739aefa4e0008e52cf0
|