alibaba/OpenCodeReview PR Review
AI-powered GitHub PR review with inline comments, sticky summary, and incremental non-destructive posting.
View on GitHubTrust Signals
- Scorecard Score
- not yet scored
- Maintenance Recency
- Activelast commit Jul 10, 2026
- License
- Apache 2.0
Pinned Snippet
uses: alibaba/open-code-review@802af6b461d17408856fac0d07a18f9b17d6d38c # v1.7.7tags can be moved; commit SHAs can't. why a SHA?
Inputs
| name | description | required | default |
|---|---|---|---|
| llm_url | LLM API endpoint URL (mapped to env OCR_LLM_URL). | yes | — |
| llm_auth_token | LLM auth token (mapped to env OCR_LLM_TOKEN). | yes | — |
| llm_model | Model name (mapped to env OCR_LLM_MODEL). | yes | — |
| llm_use_anthropic | Selects the LLM protocol (mapped to env OCR_USE_ANTHROPIC). An explicitly supplied empty string, true, 1, or yes selects Anthropic case-insensitively; every other value selects the OpenAI-compatible protocol, preserving the CLI environment contract. | yes | — |
| llm_auth_header | Custom auth header name (mapped to env OCR_LLM_AUTH_HEADER). | no | — |
| llm_extra_headers | Extra headers "K=V,K=V" (mapped to env OCR_LLM_EXTRA_HEADERS). | no | — |
| llm_extra_body | extra_body JSON for LLM requests. No env var exists for this, so it is written via `ocr config set llm.extra_body`. The default disables thinking mode for compatibility with various LLM providers; override it with provider-specific JSON when a model needs different behavior. An explicit reasoning_effort key here wins over the llm_reasoning_effort input. | no | {"thinking": {"type": "disabled"}} |
| llm_reasoning_effort | Reasoning depth for the model (one of: minimal, low, medium, high, max; case-insensitive), merged into the request body as reasoning_effort via llm.extra_body — no CLI support beyond the published versions is needed. OpenAI-compatible protocols only (e.g. GLM-5.x, OpenAI reasoning models); the Anthropic API rejects unknown body fields, so the action fails fast when this is set on the Anthropic protocol — steer Anthropic thinking through an explicit llm_extra_body key instead. Empty (default) sends nothing. An explicit reasoning_effort key in llm_extra_body wins over this input. | no | "" |
| language | Review output language, written via `ocr config set language` (e.g. English, Chinese). No env var exists for this. | no | English |
| llm_timeout | LLM request timeout in seconds (mapped to env OCR_LLM_TIMEOUT). | no | 300 |
| review_task_timeout | Per-file/concurrent-task timeout in integer minutes, from 1 through 120. | no | 15 |
| github_token | GitHub token used to post review comments. | no | ${{ github.token }} |
| ocr_version | npm version spec for @alibaba-group/open-code-review (v1.9.6 or newer required). | no | latest |
| review_concurrency | Value passed to `ocr review --concurrency`. | no | — |
| background | Value passed to `ocr review --background`. | no | — |
| rule | Path to a custom rules JSON file passed to `ocr review --rule`. | no | — |
| effort | Review effort preset passed to `ocr review --effort`. One of: low, medium, high (case-insensitive). Empty keeps the CLI default (the configured value, or medium). Requires OpenCodeReview v1.10.0 or newer. | no | "" |
| max_tokens_budget | Total token cap passed to `ocr review --max-tokens-budget`. Base-10 integer; empty or 0 means unlimited. Once the cap is exceeded, dispatch stops, skipped files are reported as failed(budget), partial results are still published, and the review exits 0. | no | "" |
| stream_progress | Stream live [ocr] review progress to the workflow log (human audience on stderr) instead of staying silent until the run finishes. One of: true, false (case-insensitive); empty falls back to false. false (default) keeps the silent agent-audience run with stderr captured to a log file. Requires OpenCodeReview v1.9.8 or newer when enabled. | no | false |
| upload_artifacts | Upload raw JSON result and stderr as workflow artifacts. Must be the literal string 'true' or 'false' (quoted); the step gates on a string comparison, so an unquoted YAML boolean will not match. | no | true |
| sticky_summary | Summary dimension. true = update an existing summary comment in place (sticky) instead of posting a new one each run. | no | true |
| incremental | Incremental dimension. true = only append inline comments whose (path, line range) does not overlap an existing bot review comment. History is never deleted (non-destructive). | no | false |
| incremental_overlap_threshold | IoU (intersection-over-union) threshold used by incremental mode to decide whether a new multi-line comment overlaps an existing one. Two single-line comments match when on the same line; single- vs multi-line never match. Value in (0, 1]; ignored unless incremental is true. | no | 0.6 |
| review_comment_batch_size | Maximum number of inline comments packed into a single createReview call. Large reviews are split into sequential batches of at most this size so a single request never exceeds GitHub's practical limits (a prior run failed after posting 71 inline comments in one request). Integer >= 1; values below 1 or non-numeric fall back to the default (50). | no | 50 |
| route_severity_below | Optional severity threshold that routes findings at-or-below it from inline comments to the PR summary (fail-open: never drops a finding). One of: critical, high, medium, low. For example, 'low' routes only low-severity findings, while 'medium' routes medium AND low. An empty or unknown value disables severity routing (findings stay inline). Findings with an empty or unknown severity are never routed by this policy and keep their normal placement. | no | "" |
| route_categories | Optional comma-separated list of categories routed from inline comments to the PR summary (fail-open: never drops a finding). Categories are case-insensitive and drawn from: bug, security, performance, maintainability, test, style, documentation, other. For example, 'style,documentation' routes those categories to the summary. Unknown category tokens are ignored. Findings with an empty or unknown category are never routed by this policy and keep their normal placement. Combine with route_severity_below to route on either condition. | no | "" |
| checkpoint_range | Cross-push checkpoints. true = a run that reviewed everything it selected records the head it covered in its sticky summary comment, and the next run reviews only <checkpoint>..<new head> instead of <merge-base>..<new head>. Fail-closed: if anything is in doubt — the summary is missing or was not posted by this token, the marker is unreadable, the base moved, the configuration changed, or git cannot prove the checkpoint is an ancestor of the new head — the full range is reviewed exactly as it is today. Requires sticky_summary; ignored without it. | no | false |
| full_review | Force one full review even when checkpoint_range is enabled (reason 'manual_full_review'). Use it to re-review a PR from the merge-base without turning checkpointing off; the run still records a new checkpoint. | no | false |
| base_ref | Override the base ref. Provide this (and head_sha) when invoking from a non-PR event such as issue_comment. | no | — |
| head_sha | Override the head commit SHA (use with base_ref for comment triggers). | no | — |
| node_version | Node.js version for actions/setup-node. | no | 24 |
Outputs
| name | description |
|---|---|
| comments_total | Total number of review comments generated by OCR. |
| comments_inline | Number of inline comments successfully posted. |
| comments_skipped | Number of inline comments skipped by incremental mode (overlap with history). |
| comments_routed | Number of inline-eligible comments routed to the PR summary by the route_severity_below / route_categories policy. Mutually exclusive with comments_inline, comments_skipped, and comments_failed. |
| comments_failed | Number of inline comments that failed to post. |
| summary_comment_url | URL of the posted/updated summary comment, if any. |
| range_mode | 'checkpoint' when this run reviewed only the range since the previous checkpoint, 'full' when it reviewed from the merge-base. Empty when checkpoint_range is not enabled. |
| range_summary | The reviewed range plus the reason it was chosen, e.g. "full (base_changed)" or "checkpoint (ok): <from>..<to>". Empty when checkpoint_range is not enabled. |
| range_reason | Why that mode was chosen: 'ok', 'same_head_noop', or one of the fail-closed reasons ('base_changed', 'config_changed', 'not_ancestor', …). Empty when checkpoint_range is not enabled. |
| range_from | The commit this run reviewed from, or empty when it reviewed from the merge-base (every 'full' run, and every run with checkpoint_range off). |
| range_to | The head this run reviewed up to. Empty when checkpoint_range is not enabled. |
| checkpoint_before | The head recorded by the checkpoint this run read, whether or not it was used. Empty when no usable marker was read. |
| ancestry | The ancestry verdict on the checkpoint that was read: 'ancestor', 'not_ancestor', 'unknown_object', 'error', or empty when it was not probed. |
| source_run | The workflow run id that wrote the checkpoint this run read, if any. |
| checkpoint_after | The head this run recorded as the new checkpoint, or empty when it did not advance one (incomplete run, a finding failed to post, or the summary did not publish). |