glreview 0.4.0
GitLab code review tracking for scientific software
License: MIT
Requires Python: >=3.10
Keywords: gitlab, code-review, scientific-software, ci-cd

# 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

```bash
pip install glreview
```

For AI-assisted review features, also install [Claude Code](https://claude.ai/code).

## Quick Start

### 1. Configure source patterns

Add to `pyproject.toml`:

```toml
[tool.glreview]
sources = ["src/**/*.py"]
exclude = ["**/test_*.py", "**/_version.py"]
```

### 2. Set up GitLab authentication

```bash
export GITLAB_PRIVATE_TOKEN=glpat-xxxxxxxxxxxx

# For self-hosted GitLab:
export GITLAB_URL=https://gitlab.example.com
```

### 3. Initialize

```bash
glreview init
```

This creates `.glreview/registry.json`. Commit it to version control.

### 4. Start reviewing

```bash
# 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

```bash
# 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

```bash
# 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:

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# Run review (prints findings to terminal)
glreview claude-review src/module.py

# Post findings to GitLab issue
glreview claude-review src/module.py --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

```bash
# 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
```

### Updating context

```bash
# 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:

```bash
# 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

Automatically sync the registry and generate reports on every push.

### Setup

1. Create a Project Access Token (Settings → Access Tokens) with `write_repository` scope
2. Add as CI variable: `PUSH_TOKEN`
3. Add to `.gitlab-ci.yml`:

```yaml
review-sync:
  script:
    - pip install glreview
    - git config user.email "ci@$CI_SERVER_HOST"
    - git config user.name "GitLab CI"
    - git remote set-url origin "https://oauth2:${PUSH_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git"
    - git checkout $CI_COMMIT_BRANCH
    - glreview sync
    - glreview report --format markdown --output REVIEW_COVERAGE.md
    - git add .glreview/ REVIEW_COVERAGE.md
    - 'git diff --cached --quiet || git commit -m "chore: update review registry"'
    - git push origin HEAD:$CI_COMMIT_BRANCH -o ci.skip
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
```

Run `glreview ci-config` for complete configuration including MR checks and release gates.

### CI checks

```bash
# Fail if reviewed files have uncommitted registry changes
glreview check

# Use in CI to gate merges
glreview check --strict
```

## Configuration Reference

Full `pyproject.toml` options:

```toml
[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 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) |
| `check` | CI check for uncommitted changes |
| `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 |
| `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