# Gerrit Code Review Extractor (`datamule/gerrit-code-review-extractor`) Actor

Point at any Gerrit code-review server (Android, Chromium, OpenStack, Wikimedia, GerritHub, self-hosted) and get one structured row per change: subject, status, owner, review labels, insertions/deletions, comments and merge history. Also lists projects and server info.

- **URL**: https://apify.com/datamule/gerrit-code-review-extractor.md
- **Developed by:** [Datamule](https://apify.com/datamule) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.35 / 1,000 records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Gerrit Code Review Extractor

Point at **any** Gerrit code-review server and get clean, structured rows —
one per change (code review), project, or server. Gerrit is the self-hosted
code-review server behind **Android, Chromium, and Go**, and adopted by
**OpenStack, Wikimedia, ONAP, LineageOS, Eclipse, GerritHub** and countless
corporate and university deployments. Every Gerrit speaks the identical REST
API and leaves anonymous read on for public projects, so this one actor works
against all of them — no per-server scraper, no login.

### What it does

Three modes, chosen by the **Run mode** field:

- **changes** (default) — one row per code-review change matching your query
  (`status:open` by default). Columns: project, change number, subject, status,
  owner, branch, insertions/deletions, comment counts, work-in-progress flag,
  and (with options) review labels, a submit-label summary, and message counts.
- **projects** — the server's project/repository inventory, one row per project
  (name, state, parent, description).
- **server** — one row per server describing its version and authentication
  model.

Point it at several servers at once and it runs each in turn; a URL that isn't
a Gerrit (a login page, or a host that migrated to GitLab/Gitea) is skipped
with a warning instead of failing the whole run.

### Example input

```json
{
  "sources": ["https://review.opendev.org"],
  "mode": "changes",
  "query": "status:open",
  "options": ["LABELS", "DETAILED_ACCOUNTS"],
  "maxRecords": 20
}
````

Other ready-to-run servers: `https://review.gerrithub.io` (GerritHub),
`https://gerrit.onap.org`, `https://gerrit.osmocom.org`, and any self-hosted
instance. Some servers sit at a `/r` mount (`https://gerrit.wikimedia.org`) —
paste either form, the `/r` path is auto-detected.

> **Note on datacenter IPs.** A few very large Google-hosted servers
> (`android-review`, `chromium-review`, `go-review` on `googlesource.com`) and
> some others block datacenter IP ranges, so they respond from a laptop but not
> from a cloud datacenter. When running on the platform, prefer an independent
> server such as `review.opendev.org`, or supply auth for a gated one.

#### Query examples (changes mode)

- `status:open` — all open changes
- `status:merged` — recently merged changes
- `project:platform/frameworks/base status:open` — one project's open changes
- `owner:self status:open` — (with auth) your own open changes
- `after:2026-01-01 status:merged` — merged since a date
- `is:wip` — work-in-progress changes

### Output

One flat row per record. Change rows carry `_type/_source/_mode/_software/ _serverVersion` metadata plus the flattened change fields and a lossless `_raw`
copy of the original API entry (capped for size). Reviewer/owner **emails** and
the full attention-set live only inside `_raw`, never as top-level columns.

### Pricing

Pay-per-event: one **record** charge per emitted row. The ready-to-run default targets OpenDev and caps the first run at 20 rows; raise `maxRecords` deliberately for larger exports.

### Notes

- Anonymous read is used by default. For a private or rate-limited server you
  may supply a `bearer` token, a `cookie`, or `extraHeaders` — these are never
  logged and are never required for public data.
- The actor reads every field by key presence, so servers on different Gerrit
  versions (which populate different optional fields) all work without error.

# Actor input Schema

## `sources` (type: `array`):

One or more Gerrit code-review server base URLs. Every Gerrit server speaks the identical REST API, so one actor works against any of them: https://review.opendev.org (OpenStack), https://review.gerrithub.io (GerritHub), https://gerrit.onap.org , https://gerrit.osmocom.org , or any self-hosted / corporate / university instance. Some servers sit at a /r mount (e.g. https://gerrit.wikimedia.org) — paste either form, the /r path is auto-detected. Anonymous read is on for public servers, so no login is needed. NOTE: a few large Google-hosted servers (android-review / chromium-review / go-review .googlesource.com) and some others block datacenter IP ranges, so they answer locally but not from Apify's cloud — prefer an independent server like review.opendev.org.

## `mode` (type: `string`):

What to extract from each server. changes (default) = one row per code-review change matching the query. projects = the server's project/repository inventory, one row per project. server = one row per server describing its version and authentication model.

## `query` (type: `string`):

CHANGES MODE. The Gerrit search expression passed to /changes/?q=. Defaults to status:open. Supports the full Gerrit query grammar: status:merged, status:abandoned, project:platform/frameworks/base, owner:someone@example.com, branch:main, after:2026-01-01, is:wip, label:Code-Review=+2, and combinations (space = AND, OR for alternatives). Ignored in projects/server mode.

## `options` (type: `array`):

CHANGES MODE. Extra Gerrit detail options — each ADDS columns and all work anonymously. LABELS adds per-label review scores (Code-Review, Verified, ...) and a submitLabel summary. MESSAGES adds an inline-message count. DETAILED\_ACCOUNTS populates the change owner's name. CURRENT\_REVISION adds the current commit sha. SUBMITTABLE adds the submittable flag. Reviewer emails and message bodies are kept only inside the lossless \_raw field, never as columns.

## `maxRecords` (type: `integer`):

A GLOBAL cap on the number of rows to emit across all sources (each row is one change/project/server and one billable event). Pagination stops as soon as the cap is reached, so a small value is a cheap, deterministic sample. Defaults to 20 for a fast, bounded first run. Raise it deliberately for larger exports; broad queries on large servers can return many records.

## `bearer` (type: `string`):

Optional access token for a private / registration-required / rate-limited server (sent as Authorization: Bearer \*\*\*). Not required for public servers. Never logged.

## `cookie` (type: `string`):

Optional raw Cookie header value for a session-gated server. Not required for public servers. Never logged.

## `extraHeaders` (type: `object`):

Optional extra HTTP headers as a JSON object, e.g. {"x-api-key": "..."} for gated servers. Not required for public data. Header values are never logged.

## Actor input object example

```json
{
  "sources": [
    "https://review.opendev.org"
  ],
  "mode": "changes",
  "query": "status:open",
  "options": [],
  "maxRecords": 20
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "sources": [
        "https://review.opendev.org"
    ],
    "query": "status:open",
    "maxRecords": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("datamule/gerrit-code-review-extractor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "sources": ["https://review.opendev.org"],
    "query": "status:open",
    "maxRecords": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("datamule/gerrit-code-review-extractor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "sources": [
    "https://review.opendev.org"
  ],
  "query": "status:open",
  "maxRecords": 20
}' |
apify call datamule/gerrit-code-review-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=datamule/gerrit-code-review-extractor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Gerrit Code Review Extractor",
        "description": "Point at any Gerrit code-review server (Android, Chromium, OpenStack, Wikimedia, GerritHub, self-hosted) and get one structured row per change: subject, status, owner, review labels, insertions/deletions, comments and merge history. Also lists projects and server info.",
        "version": "0.1",
        "x-build-id": "jhgifUZzTzamTxXQ6"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/datamule~gerrit-code-review-extractor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-datamule-gerrit-code-review-extractor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/datamule~gerrit-code-review-extractor/runs": {
            "post": {
                "operationId": "runs-sync-datamule-gerrit-code-review-extractor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/datamule~gerrit-code-review-extractor/run-sync": {
            "post": {
                "operationId": "run-sync-datamule-gerrit-code-review-extractor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "sources"
                ],
                "properties": {
                    "sources": {
                        "title": "Gerrit server URLs",
                        "type": "array",
                        "description": "One or more Gerrit code-review server base URLs. Every Gerrit server speaks the identical REST API, so one actor works against any of them: https://review.opendev.org (OpenStack), https://review.gerrithub.io (GerritHub), https://gerrit.onap.org , https://gerrit.osmocom.org , or any self-hosted / corporate / university instance. Some servers sit at a /r mount (e.g. https://gerrit.wikimedia.org) — paste either form, the /r path is auto-detected. Anonymous read is on for public servers, so no login is needed. NOTE: a few large Google-hosted servers (android-review / chromium-review / go-review .googlesource.com) and some others block datacenter IP ranges, so they answer locally but not from Apify's cloud — prefer an independent server like review.opendev.org.",
                        "default": [
                            "https://review.opendev.org"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "mode": {
                        "title": "Run mode",
                        "enum": [
                            "changes",
                            "projects",
                            "server"
                        ],
                        "type": "string",
                        "description": "What to extract from each server. changes (default) = one row per code-review change matching the query. projects = the server's project/repository inventory, one row per project. server = one row per server describing its version and authentication model.",
                        "default": "changes"
                    },
                    "query": {
                        "title": "Gerrit search query (MODE: changes)",
                        "type": "string",
                        "description": "CHANGES MODE. The Gerrit search expression passed to /changes/?q=. Defaults to status:open. Supports the full Gerrit query grammar: status:merged, status:abandoned, project:platform/frameworks/base, owner:someone@example.com, branch:main, after:2026-01-01, is:wip, label:Code-Review=+2, and combinations (space = AND, OR for alternatives). Ignored in projects/server mode.",
                        "default": "status:open"
                    },
                    "options": {
                        "title": "Detail options (MODE: changes)",
                        "type": "array",
                        "description": "CHANGES MODE. Extra Gerrit detail options — each ADDS columns and all work anonymously. LABELS adds per-label review scores (Code-Review, Verified, ...) and a submitLabel summary. MESSAGES adds an inline-message count. DETAILED_ACCOUNTS populates the change owner's name. CURRENT_REVISION adds the current commit sha. SUBMITTABLE adds the submittable flag. Reviewer emails and message bodies are kept only inside the lossless _raw field, never as columns.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "LABELS",
                                "DETAILED_LABELS",
                                "MESSAGES",
                                "DETAILED_ACCOUNTS",
                                "CURRENT_REVISION",
                                "SUBMITTABLE",
                                "SUBMIT_REQUIREMENTS",
                                "WEB_LINKS"
                            ],
                            "enumTitles": [
                                "LABELS (review scores)",
                                "DETAILED_LABELS",
                                "MESSAGES (count)",
                                "DETAILED_ACCOUNTS (owner name)",
                                "CURRENT_REVISION (commit sha)",
                                "SUBMITTABLE",
                                "SUBMIT_REQUIREMENTS",
                                "WEB_LINKS"
                            ]
                        },
                        "default": []
                    },
                    "maxRecords": {
                        "title": "Max records (global cap)",
                        "minimum": 1,
                        "type": "integer",
                        "description": "A GLOBAL cap on the number of rows to emit across all sources (each row is one change/project/server and one billable event). Pagination stops as soon as the cap is reached, so a small value is a cheap, deterministic sample. Defaults to 20 for a fast, bounded first run. Raise it deliberately for larger exports; broad queries on large servers can return many records.",
                        "default": 20
                    },
                    "bearer": {
                        "title": "Bearer token",
                        "type": "string",
                        "description": "Optional access token for a private / registration-required / rate-limited server (sent as Authorization: Bearer ***). Not required for public servers. Never logged."
                    },
                    "cookie": {
                        "title": "Cookie header",
                        "type": "string",
                        "description": "Optional raw Cookie header value for a session-gated server. Not required for public servers. Never logged."
                    },
                    "extraHeaders": {
                        "title": "Extra request headers",
                        "type": "object",
                        "description": "Optional extra HTTP headers as a JSON object, e.g. {\"x-api-key\": \"...\"} for gated servers. Not required for public data. Header values are never logged."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
