# How to Integrate with Gerrit Code Review System: OpenCodeReview Integration Guide

> Integrate with Gerrit code review using OpenCodeReview. Discover our Python script for easy Gerrit ReviewInput payload conversion and REST API posting. Streamline your code review process.

- Repository: [Alibaba/open-code-review](https://github.com/alibaba/open-code-review)
- Tags: how-to-guide
- Published: 2026-08-03

---

**OpenCodeReview provides a Python helper script that converts `ocr review --format json` output into Gerrit ReviewInput payloads and posts them via the REST API.**

Integrating OpenCodeReview with the Gerrit code review system enables automated AI-powered code analysis results to appear directly in your Gerrit changes. The alibaba/open-code-review repository ships a complete integration in [`examples/gerrit_ci/post_review.py`](https://github.com/alibaba/open-code-review/blob/main/examples/gerrit_ci/post_review.py) that handles authentication, payload mapping, error recovery, and retry logic.

## Prerequisites for Gerrit Integration

Before running the integration, ensure you have:

- **OpenCodeReview CLI** (`ocr`) installed and producing JSON review output
- **Gerrit HTTP password** (not your account password) from *Settings → HTTP Password*
- Python 3 environment with `requests` or standard library `urllib`

The integration targets Gerrit's `/a/` authenticated REST endpoints, which require preemptive Basic authentication to avoid 401 rejection cycles.

## Core Architecture: Three Integration Layers

The [`post_review.py`](https://github.com/alibaba/open-code-review/blob/main/post_review.py) script operates through three coordinated layers:

### 1. OCR Results to Gerrit Payload Mapping

The `build_review_input()` function (see [[`post_review.py`](https://github.com/alibaba/open-code-review/blob/main/post_review.py), lines 94-104](https://github.com/alibaba/open-code-review/blob/main/examples/gerrit_ci/post_review.py#L94-L104)) transforms OpenCodeReview JSON into Gerrit's `ReviewInput` schema:

```python

# Example OCR JSON structure consumed by the mapper

{
  "file_path": {
    "line_number": {
      "severity": "WARNING",
      "message": "Potential null pointer dereference"
    }
  }
}

```

This mapping:
- Groups inline comments by file path
- Constructs a summary message with change-level statistics
- Formats the `ReviewInput` dictionary with `comments` and `labels` fields

### 2. HTTP Transport with Authentication

The `make_poster()` function (see [[`post_review.py`](https://github.com/alibaba/open-code-review/blob/main/post_review.py), lines 14-33](https://github.com/alibaba/open-code-review/blob/main/examples/gerrit_ci/post_review.py#L14-L33)) creates a callable that POSTs to:

```text
POST {GERRIT_URL}/a/changes/{change}/revisions/{revision}/review

```

Key transport features:
- **Preemptive Basic Auth**: Base64-encoded credentials in the `Authorization` header before any 401 challenge
- **XSSI protection handling**: `strip_xssi()` (see [[`post_review.py`](https://github.com/alibaba/open-code-review/blob/main/post_review.py), lines 80-86](https://github.com/alibaba/open-code-review/blob/main/examples/gerrit_ci/post_review.py#L80-L86)) removes Gerrit's `)]}'` JSON prefix
- **Message truncation**: `truncate_message()` (see [[`post_review.py`](https://github.com/alibaba/open-code-review/blob/main/post_review.py), lines 88-92](https://github.com/alibaba/open-code-review/blob/main/examples/gerrit_ci/post_review.py#L88-L92)) enforces Gerrit's 16 KB summary limit

### 3. CLI Orchestration and Error Recovery

The `main()` entry point (see [[`post_review.py`](https://github.com/alibaba/open-code-review/blob/main/post_review.py), lines 48-70](https://github.com/alibaba/open-code-review/blob/main/examples/gerrit_ci/post_review.py#L48-L70)) provides:

| Error Code | Behavior |
|------------|----------|
| 401/403 | Exit with credential error message |
| 404 | Report change not found |
| 409 | Silent exit (change closed/abandoned) |
| 400 + inline comments | **Automatic fallback** to `fold_comments()` (see [[`post_review.py`](https://github.com/alibaba/open-code-review/blob/main/post_review.py), lines 53-71](https://github.com/alibaba/open-code-review/blob/main/examples/gerrit_ci/post_review.py#L53-L71))—moves all findings to summary message |

## Running the Gerrit Integration

### Basic CLI Usage

```bash

# Generate OCR review output first

ocr review --format json > review.json

# Post to Gerrit

python3 examples/gerrit_ci/post_review.py \
    --gerrit-url https://gerrit.mycompany.com \
    --change 12345 \
    --revision current \
    --user gitbot \
    --password $GERRIT_HTTP_PASSWORD \
    --input review.json

```

### Dry-Run Mode for Debugging

Validate your payload without posting:

```bash
python3 examples/gerrit_ci/post_review.py \
    --dry-run \
    --input review.json

```

This activates `make_dry_run_poster()` (see [[`post_review.py`](https://github.com/alibaba/open-code-review/blob/main/post_review.py), lines 64-71](https://github.com/alibaba/open-code-review/blob/main/examples/gerrit_ci/post_review.py#L64-L71)) to print the generated `ReviewInput` JSON.

### Environment Variable Configuration

For Gerrit-triggered CI jobs, omit flags and use standard environment variables:

```bash
export GERRIT_URL=https://gerrit.mycompany.com
export GERRIT_CHANGE_NUMBER=12345
export GERRIT_HTTP_USER=gitbot
export GERRIT_HTTP_PASSWORD=...   # From Gerrit Settings → HTTP Password

python3 examples/gerrit_ci/post_review.py --input review.json

```

The script derives `GERRIT_URL` from `GERRIT_CHANGE_URL` if the former is unset (see [[`post_review.py`](https://github.com/alibaba/open-code-review/blob/main/post_review.py), lines 52-58](https://github.com/alibaba/open-code-review/blob/main/examples/gerrit_ci/post_review.py#L52-L58)).

## Retry Strategy and Reliability

The integration implements production-grade retry logic:

- `MAX_ATTEMPTS = 3` (see [[`post_review.py`](https://github.com/alibaba/open-code-review/blob/main/post_review.py), line 48](https://github.com/alibaba/open-code-review/blob/main/examples/gerrit_ci/post_review.py#L48))
- **Exponential backoff**: `_sleep(0.5 * (2 ** attempt))`
- **Conditional retry**: Only HTTP 5xx and connection errors trigger retry; 4xx client errors fail immediately
- **Timeout propagation**: Network timeouts surface immediately to prevent duplicate review posts

## Summary

- **Primary integration file**: [`examples/gerrit_ci/post_review.py`](https://github.com/alibaba/open-code-review/blob/main/examples/gerrit_ci/post_review.py) provides complete Gerrit bridge functionality
- **Authentication**: Requires Gerrit HTTP password with preemptive Basic Auth encoding
- **Payload mapping**: `build_review_input()` converts OCR JSON to Gerrit `ReviewInput` schema
- **Error resilience**: Automatic comment folding on HTTP 400, change-state checking for 409
- **Operational modes**: Full posting, dry-run debugging, and environment-driven configuration

## Frequently Asked Questions

### What Gerrit credentials does the integration require?

The [`post_review.py`](https://github.com/alibaba/open-code-review/blob/main/post_review.py) script requires a **Gerrit HTTP password**, not your standard account password. Generate this from *Gerrit Settings → HTTP Password*. The script encodes these credentials in Base64 and includes them preemptively in the `Authorization` header, because Gerrit's `/a/` authenticated endpoints may reject unauthenticated requests without a proper 401 challenge-response cycle.

### How does the integration handle Gerrer's 16 KB message limit?

The `truncate_message()` function (see [[`post_review.py`](https://github.com/alibaba/open-code-review/blob/main/post_review.py), lines 88-92](https://github.com/alibaba/open-code-review/blob/main/examples/gerrit_ci/post_review.py#L88-L92)) automatically clips summary messages exceeding 16,000 bytes. If inline comments push the total payload over limits, the fallback `fold_comments()` mechanism moves all findings into the summary text rather than individual line comments, ensuring the review still posts successfully.

### Can I test the integration without posting to a live Gerrit server?

Yes. Use the `--dry-run` flag to activate `make_dry_run_poster()`, which prints the complete `ReviewInput` JSON to stdout without making any HTTP requests. This mode validates OCR output parsing, payload construction, and message truncation without side effects.

### What happens if Gerrit rejects inline comments for a specific change?

When Gerrit returns HTTP 400 with inline comments, the integration automatically invokes `fold_comments()` (see [[`post_review.py`](https://github.com/alibaba/open-code-review/blob/main/post_review.py), lines 53-71](https://github.com/alibaba/open-code-review/blob/main/examples/gerrit_ci/post_review.py#L53-L71)). This failure-recovery path restructures the payload: all file-line specific comments are concatenated into the summary message, and a clean `ReviewInput` without inline comments is retried. No manual intervention or duplicate CLI invocation is required.