mirror of
https://github.com/alibaba/open-code-review.git
synced 2026-07-09 17:28:58 +00:00
* feat(action): extract reusable OpenCodeReview PR review GitHub Action
Consolidate the reusable-action work into one commit:
- Add composite action (action.yml at repo root for GitHub Marketplace;
helper at scripts/github-actions/post-review-comments.js) porting the
sticky summary, incremental posting, and retry idempotency logic.
- Add unit tests covering the ported idempotency behavior.
- Switch the in-repo CI workflow to use the reusable action.
- Add and refine example reusable workflows for consumers.
* ci(workflow): point ocr-review at root action.yml and quote boolean inputs
- Fix uses: to ./ now that action.yml lives at the repo root.
- Quote sticky_summary/incremental/upload_artifacts as strings to
match action.yml's input declarations (composite-action inputs are
always strings) and silence actionlint.
- Enable upload_artifacts for this workflow.
* docs(examples): point reusable demo at root action.yml
The example workflow referenced alibaba/open-code-review/action@v1,
but action.yml now lives at the repo root, so the /action subpath no
longer resolves. Use alibaba/open-code-review@v1 and update the stale
action/README.md comment to point at the root action.yml.
* docs(examples): sync README to root action.yml references
The example README still pointed at the relocated/deleted locations:
action.yml is now at the repo root, so update all 11
alibaba/open-code-review/action@v1 references to
alibaba/open-code-review@v1, and repoint the action/ directory and
action/README.md links to the root action.yml.
* fix(examples): prevent unrelated PR comments from canceling ocr-review
GitHub Actions evaluates concurrency before the job-level if-condition.
The flat group mapped every issue_comment event on a PR into the review's
group, so any comment (even a skipped conversation reply) canceled any
in-progress review.
Match the reusable demo's conditional group: PR events and human-authored
/open-code-review/@open-code-review comments share a per-PR group, while
non-matching comments fall back to a unique noop-<run_id> group that can
never collide with a real review.
* fix(action): address code-review findings across reusable PR review
- post-review-comments: parse retry delays via parseNonNegInt (0/negative fix);
paginate findExistingSummaryComment through readAllPages; remove dead
rangeOf and hasIssueCommentWithId (plus duplicated comment block)
- action.yml: move ${{ }} interpolations into env: (resolve refs, PR_NUM,
ocr_version); fail fast on PR head fetch instead of swallowing errors
- workflows: add timeout-minutes: 30; gate issue_comment on
author_association; tighten pr-context if to == 'issue_comment'
* fix(action): harden review posting after code review
- pass incremental_overlap_threshold via env to avoid github-script injection
- capture ocr review exit code directly instead of &&/|| chain
- drop redundant SUMMARY_MARKER prepend in postSummary (callers already add it)
- align example job if-condition bot check with its concurrency group
* fix(action): always upload review artifacts and capture ocr exit code
* fix(action): merge posting statistics into the summary header
The PR summary issue comment used to present two overlapping breakdowns:
a leading "posted as inline / posted as summary" header and a trailing
"📊 Posting Statistics" block. Their definitions overlapped (the header's
"summary" count included failures the trailer also listed as failed), and
when incremental filtering skipped comments the header counts no longer
summed to the total, making the summary hard to interpret.
Merge them into a single header whose four counts (inline / summary /
skipped / failed) are mutually exclusive and sum to the total, and drop
the trailing Posting Statistics section. buildSummaryBody now takes an
options object.
* fix(action): support local action resolution in container/self-hosted setups
- Checkout trusted base + mark workspace safe for pull_request_target so
the local `uses: ./` action can be resolved and loaded
- Check for git/Node.js and install git when missing, making the
composite action resilient across runner images
- Move Setup Node.js earlier and make it conditional on availability
- Resolve post-review-comments helper at runtime via
GITHUB_ACTION_PATH falling back to GITHUB_WORKSPACE, fixing helper
lookup for local actions where the action path is a host path
invisible inside containers
* refactor(examples): consolidate github_actions demo to reusable action
Drop the inline-script full-control demo; the renamed ocr-review.yml
(from ocr-review-reusable.yml) is now the single demo, invoking
alibaba/open-code-review@main.
Sync the README to the current implementation:
- normalize action refs to @main; point self-hosted-runner users to the
repo's own workflow (noting uses: ./ is internal-only)
- document config via action inputs (posting modes: sticky/incremental)
- update the comment-trigger if with defensive bot/author_association
guards and the concurrency mirror
- fix Example Output to cover the summary comment + inline comments
- replace the non-existent OCR_DEBUG debugging with
artifacts/outputs/ACTIONS_STEP_DEBUG
- use --replace-all for safe.directory
* fix(action): harden withRetry against silent undefined return
withRetry's for loop had no terminal return/throw after the loop body.
Although the current loop invariant (last attempt always throws, and
parseNonNegInt guards against negative MAX_RETRIES) makes fall-through
unreachable, an async function that falls through resolves to undefined,
which would surface as a confusing downstream TypeError for the read-API
callers that rely on it.
Capture lastErr in the loop and add an explicit terminal throw so any
future break of the invariant fails loudly instead of silently returning
undefined.
* docs(readme): document the reusable GitHub Action in CI/CD section
* fix(action): restore language config via a language input
The old inline workflow ran `ocr config set language English`, but the
composite action's Configure OCR step only set llm.extra_body, with no
language input. Add a language input (default English) and write it via
`ocr config set language` so review output language is no longer left
to the tool's default.
Addresses #337 (discussion_r3550069843).
* fix(action): warn when incremental comment listing hits page cap
listExistingReviewComments silently dropped comments beyond its 10-page
cap, unlike readAllPages which logs when truncation occurs. Add the
same max-page-limit warning after the loop so a partial walk during
incremental dedup is visible in the logs.
Addresses #337 (discussion_r3550069871).
* docs(readme): sync GitHub Action section to localized READMEs
366 lines
20 KiB
Markdown
366 lines
20 KiB
Markdown
# OpenCodeReview - GitHub Actions Workflow
|
|
|
|
This directory provides a ready-to-use GitHub Actions workflow demo that integrates OpenCodeReview into your repository to automatically review Pull Requests and post inline review comments. Copy it into `.github/workflows/` and configure the required secrets/vars.
|
|
|
|
## Quick Start: `ocr-review.yml`
|
|
|
|
The simplest adoption path: this demo delegates every step — checkout, OCR install, review, comment posting, artifact upload — to the official reusable composite action at [`action.yml`](../../action.yml) via a single `uses: alibaba/open-code-review@main` step. It covers both automatic PR review (`pull_request_target: opened/synchronize/reopened`) and on-demand re-review via comments (`/open-code-review` or `@open-code-review`). No inline scripts to maintain — `@main` always runs the latest action; pin to a version tag or commit SHA when reproducibility matters.
|
|
|
|
```bash
|
|
mkdir -p .github/workflows
|
|
cp ocr-review.yml .github/workflows/ocr-review.yml
|
|
```
|
|
|
|
The core of the demo is a single action step:
|
|
|
|
```yaml
|
|
- uses: alibaba/open-code-review@main
|
|
with:
|
|
llm_url: ${{ secrets.OCR_LLM_URL }}
|
|
llm_auth_token: ${{ secrets.OCR_LLM_AUTH_TOKEN }}
|
|
llm_model: ${{ vars.OCR_LLM_MODEL }}
|
|
llm_use_anthropic: ${{ vars.OCR_LLM_USE_ANTHROPIC }}
|
|
```
|
|
|
|
See [`action.yml`](../../action.yml) for the full list of inputs, outputs, security guidance, and the four comment-posting modes (sticky summary + incremental).
|
|
|
|
## Running on a self-hosted runner
|
|
|
|
The demo above runs on GitHub-hosted runners (`runs-on: ubuntu-latest`) and pulls the action from `alibaba/open-code-review@main`. If you prefer to run OCR on your own self-hosted runner — to reach private network resources, keep LLM traffic on-prem, or avoid runner-minute costs — the OCR project itself does exactly this in its own CI.
|
|
|
|
See [`.github/workflows/ocr-review.yml`](../../.github/workflows/ocr-review.yml) for that workflow. It runs on `runs-on: self-hosted` inside a `node:24` container. One important caveat: it invokes the action with `uses: ./` only because `action.yml` lives in that same repository — that is an internal shortcut and will not resolve in your repo. As an external user, keep `uses: alibaba/open-code-review@main` (the runner fetches the action automatically); only the runner environment needs to change. What is worth borrowing from it:
|
|
|
|
- `runs-on: self-hosted`, optionally with a `container:` image such as `node:24` (the action needs Node.js; git is installed automatically if missing).
|
|
- Marking the workspace as a trusted git `safe.directory` when running inside a container (e.g. `git config --global --replace-all safe.directory '*'`) to avoid "dubious ownership" errors. Use `--replace-all` (not `--add`) so repeated runs across multiple self-hosted actions replace rather than accumulate entries in the global git config.
|
|
- Pinning action inputs explicitly (`sticky_summary`, `incremental`, `upload_artifacts`, `llm_extra_body`, etc.).
|
|
|
|
The action performs its own full `fetch-depth: 0` checkout of the PR internally, so no extra checkout step is needed for the review diff. Adapt the runner settings to your environment and secret layout.
|
|
|
|
## How It Works
|
|
|
|
```
|
|
PR Created/Updated → GitHub Actions Triggered → OCR Reviews Diff → Comments Posted on PR
|
|
OR
|
|
Comment with trigger keyword ↗
|
|
```
|
|
|
|
1. When a PR is opened, the workflow triggers (uses `pull_request_target` for fork secret access).
|
|
2. Alternatively, when a comment containing `/open-code-review` or `@open-code-review` is posted on a PR, the workflow triggers.
|
|
3. The reusable action installs OCR, fetches the PR head blobs, computes `git merge-base`, and runs `ocr review --from <merge-base> --to <head> --format json`.
|
|
4. It parses the JSON output and posts inline review comments on the PR via the Pull Request Review API, plus a summary comment (an issue comment on the PR).
|
|
|
|
## Setup
|
|
|
|
### Configure secrets and variables
|
|
|
|
Go to your repository's **Settings → Secrets and variables → Actions**.
|
|
|
|
**Secrets:**
|
|
|
|
| Secret | Required | Description |
|
|
|--------|----------|-------------|
|
|
| `OCR_LLM_URL` | Yes | LLM API endpoint URL (e.g., `https://api.openai.com/v1/chat/completions`) |
|
|
| `OCR_LLM_AUTH_TOKEN` | Yes | API authentication token (mapped to env `OCR_LLM_TOKEN` internally) |
|
|
|
|
**Variables:**
|
|
|
|
| Variable | Required | Description |
|
|
|----------|----------|-------------|
|
|
| `OCR_LLM_MODEL` | Yes | Model name |
|
|
| `OCR_LLM_USE_ANTHROPIC` | Yes | `true` for Anthropic Claude, `false` for OpenAI-compatible |
|
|
|
|
> **Note:** `GITHUB_TOKEN` is automatically provided by GitHub Actions with the required `pull-requests: write` permission. The action also sets `llm.extra_body` to disable thinking mode for compatibility with various LLM providers.
|
|
|
|
## Customization
|
|
|
|
> These knobs are action inputs — they apply to the demo workflow and any workflow calling `alibaba/open-code-review@main`.
|
|
|
|
See [`action.yml`](../../action.yml) for the full input list. Workflow-level settings (triggers, keywords) are edited in the workflow file itself.
|
|
|
|
### Change the trigger events
|
|
|
|
Modify the `on.pull_request_target.types` array in the workflow file:
|
|
|
|
```yaml
|
|
on:
|
|
pull_request_target:
|
|
types: [opened, synchronize, reopened, ready_for_review]
|
|
```
|
|
|
|
### Customize comment trigger keywords
|
|
|
|
By default the workflow also re-reviews on demand when a PR comment starts with `/open-code-review` or `@open-code-review`. The `if` condition is more defensive than a bare keyword check — it gates comment triggers so only authorized humans can spend LLM quota:
|
|
|
|
```yaml
|
|
if: |
|
|
github.event_name == 'pull_request_target'
|
|
|| (
|
|
github.event_name == 'issue_comment'
|
|
&& github.event.issue.pull_request
|
|
&& github.event.comment.user.type != 'Bot'
|
|
&& (
|
|
github.event.comment.author_association == 'MEMBER'
|
|
|| github.event.comment.author_association == 'OWNER'
|
|
|| github.event.comment.author_association == 'COLLABORATOR'
|
|
)
|
|
&& (
|
|
startsWith(github.event.comment.body, '/open-code-review')
|
|
|| startsWith(github.event.comment.body, '@open-code-review')
|
|
)
|
|
)
|
|
```
|
|
|
|
Each clause guards against a different abuse vector:
|
|
|
|
- `github.event.issue.pull_request` — the comment must be on a PR, not a regular issue.
|
|
- `github.event.comment.user.type != 'Bot'` — ignore bot comments. `GITHUB_TOKEN` already suppresses events from comments it posted, but a PAT or GitHub App token would not, so this is a safety net against self-triggering loops.
|
|
- `author_association == 'MEMBER' | 'OWNER' | 'COLLABORATOR'` — only repository collaborators can trigger a (billable) re-review, preventing arbitrary commenters from draining LLM quota.
|
|
- The `startsWith(...)` pair — the actual trigger keywords.
|
|
|
|
To change the keywords, edit only that final pair (e.g. `/review` and `@mybot`), or swap `startsWith` for `contains` to match a substring anywhere in the comment body. Keep the preceding guards intact.
|
|
|
|
The same predicate is mirrored in the workflow's `concurrency.group`: matching events share a per-PR group (`ocr-<pr_number>`) so a new review cancels any stale one, while non-matching comments land in a unique `noop-<run_id>` group and are skipped instantly without disrupting a running review. If you change the keywords in `if`, mirror the change in `concurrency.group` too.
|
|
|
|
### Use a specific OCR version
|
|
|
|
```yaml
|
|
- uses: alibaba/open-code-review@main
|
|
with:
|
|
ocr_version: 1.0.0
|
|
```
|
|
|
|
### Add custom review rules
|
|
|
|
```yaml
|
|
- uses: alibaba/open-code-review@main
|
|
with:
|
|
rule: ./my-rules.json
|
|
```
|
|
|
|
> Security: do not point `rule` at a file sourced from the PR branch when secrets are in scope; use a trusted rules file from your base branch.
|
|
|
|
### Control comment posting (sticky summary & incremental)
|
|
|
|
The action posts a summary issue comment plus inline review comments. Two inputs select the posting mode (combined, they give the four modes referenced above); a third tunes the incremental overlap test:
|
|
|
|
| Input | Default | Description |
|
|
|-------|---------|-------------|
|
|
| `sticky_summary` | `'true'` | Update an existing summary comment in place instead of posting a new one each run. |
|
|
| `incremental` | `'false'` | Only append inline comments whose `(path, line range)` does not overlap an existing bot review comment. History is never deleted (non-destructive). |
|
|
| `incremental_overlap_threshold` | `'0.6'` | IoU threshold `incremental` uses to decide whether a multi-line comment overlaps an existing one. Two single-line comments match on the same line; single- vs multi-line never match. Ignored unless `incremental` is `'true'`. |
|
|
|
|
```yaml
|
|
- uses: alibaba/open-code-review@main
|
|
with:
|
|
sticky_summary: 'true'
|
|
incremental: 'true'
|
|
incremental_overlap_threshold: '0.75'
|
|
```
|
|
|
|
> `sticky_summary` and `incremental` must be quoted strings (`'true'`/`'false'`); the action compares them as strings, so an unquoted YAML boolean will not match.
|
|
|
|
### Adjust retry and delay settings
|
|
|
|
When posting review comments individually (fallback mode), the action honors GitHub rate-limit headers (`retry-after`, `x-ratelimit-*`) with exponential backoff. The retry strategy follows GitHub's documented guidance for REST API rate limits — see [Rate limits for the REST API](https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2026-03-10) for details on primary/secondary rate limits and recommended retry behavior:
|
|
|
|
- **Primary rate limit exhausted** (`x-ratelimit-remaining=0`): wait until `x-ratelimit-reset`.
|
|
- **Secondary rate limit with a `retry-after` header**: wait exactly that long.
|
|
- **Secondary rate limit with no header**: wait at least one minute, then use exponential backoff on continued failures.
|
|
|
|
These are environment variables read by the posting module with sensible defaults; set them at the **job `env:` level** to tune (they propagate into the action):
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `OCR_RETRY_BASE_DELAY` | `60000` | Base delay (ms) for exponential backoff when no retry header is present |
|
|
| `OCR_RETRY_MAX_DELAY` | `300000` | Maximum delay (ms) cap applied to every computed wait |
|
|
| `OCR_MAX_RETRIES` | `3` | Maximum retry attempts per comment when rate-limited |
|
|
| `OCR_SUCCESS_DELAY` | `2000` | Delay (ms) after a successful comment post |
|
|
| `OCR_FAILURE_DELAY` | `1000` | Delay (ms) after a non-retryable failure |
|
|
| `OCR_LOW_REMAINING_THRESHOLD` | `3` | When x-ratelimit-remaining is at or below this value, proactively increase request spacing |
|
|
| `OCR_LOW_REMAINING_SPACING` | `10000` | Request spacing (ms) used when remaining quota is low |
|
|
| `OCR_READ_SUCCESS_DELAY` | `500` | Delay (ms) after a successful read API call (`listReviews` / `listReviewComments` / `listIssueComments`) used for the idempotency check. Reads are cheaper than writes, so the default is shorter |
|
|
| `OCR_READ_LOW_REMAINING_SPACING` | `5000` | Request spacing (ms) for read calls when remaining quota is low |
|
|
|
|
For example, to raise the per-comment retry count to 5, set `OCR_MAX_RETRIES` on the **job's** `env:` — not on the `uses:` step. A composite action does not forward the caller's step-level `env:` into its internal steps' process environment, so a step-level value would be silently ignored; the job-level value is inherited by the action's comment-posting step and read via `process.env`:
|
|
|
|
```yaml
|
|
jobs:
|
|
code-review:
|
|
runs-on: ubuntu-latest
|
|
env:
|
|
OCR_MAX_RETRIES: 5
|
|
steps:
|
|
- uses: alibaba/open-code-review@main
|
|
with:
|
|
llm_url: ${{ secrets.OCR_LLM_URL }}
|
|
# ...other inputs
|
|
```
|
|
|
|
These variables are optional. See GitHub's [Rate limits for the REST API](https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api).
|
|
|
|
#### Idempotency: avoiding duplicate review comments
|
|
|
|
When the batch `createReview` call fails with a `5xx` error, the request may still have landed on the GitHub server (the response was simply lost). Before retrying per-comment, the action queries existing reviews and review comments — each tagged with a per-run HTML comment (e.g. `<!-- ocr-<runId>-<attempt>-<token> -->`) — and only retries the comments that are actually missing. This prevents duplicate review posts.
|
|
|
|
The summary comment is deduplicated too: in sticky mode (the default) the action finds the existing summary by its persistent marker and updates it in place rather than posting a new one; in non-sticky mode it reuses this run's summary if it already exists. If the read API is unavailable, it skips posting the summary rather than risking a duplicate.
|
|
|
|
If the read API itself is unavailable (rate-limited or `5xx`), the check returns *unknown* rather than assuming the comment was not posted. In that case the action **skips retrying** to avoid risking a duplicate, and surfaces the uncertainty in the summary instead of silently producing duplicates.
|
|
|
|
### Limit LLM concurrency
|
|
|
|
```yaml
|
|
- uses: alibaba/open-code-review@main
|
|
with:
|
|
review_concurrency: 5
|
|
```
|
|
|
|
### Provide background context
|
|
|
|
```yaml
|
|
- uses: alibaba/open-code-review@main
|
|
with:
|
|
background: ${{ github.event.pull_request.title }}
|
|
```
|
|
|
|
Particularly useful when PR titles follow semantic conventions (e.g., `feat(auth): add OAuth2 support`).
|
|
|
|
> Note: `github.event.pull_request.title` is only present on `pull_request_target` events, so it is empty for comment-triggered re-reviews. To cover both trigger types, have the pr-context step also output the title and fall back to it:
|
|
>
|
|
> ```yaml
|
|
> # inside the pr-context script (which only runs for issue_comment):
|
|
> core.setOutput('title', pullRequest.title);
|
|
> ```
|
|
> ```yaml
|
|
> - uses: alibaba/open-code-review@main
|
|
> with:
|
|
> background: ${{ steps.pr-context.outputs.title || github.event.pull_request.title }}
|
|
> ```
|
|
|
|
### Customize the review comment author with GitHub App
|
|
|
|
By default, review comments are posted using the built-in `GITHUB_TOKEN`, which appears as `github-actions[bot]`. You can customize this by creating a GitHub App and using its credentials instead.
|
|
|
|
For more details about GitHub Apps, see the [GitHub Apps documentation](https://docs.github.com/en/apps).
|
|
|
|
#### Step 1: Create a GitHub App
|
|
|
|
1. Go to your organization or personal account **Settings → Developer settings → GitHub Apps → New GitHub App**
|
|
2. Fill in the following:
|
|
- **GitHub App name**: e.g., `OpenCodeReview Bot`
|
|
- **Homepage URL**: Your repository or documentation URL
|
|
- **Webhook**: Uncheck "Active" (not needed for this use case)
|
|
3. Under **Repository permissions**, set:
|
|
- **Pull requests**: Read and write
|
|
- **Contents**: Read-only (for fetching diffs)
|
|
- **Metadata**: Read-only (required)
|
|
4. Click **Create GitHub App**
|
|
|
|
#### Step 2: Generate a Private Key
|
|
|
|
1. After creating the app, scroll down to **Private keys**
|
|
2. Click **Generate a private key**
|
|
3. Download and save the `.pem` file securely
|
|
|
|
Note your App ID from the app settings page.
|
|
|
|
#### Step 3: Install the App
|
|
|
|
1. In the left sidebar, click **Install App**
|
|
2. Select the repositories where you want to use OCR
|
|
3. After installation, note the **Installation ID** from the URL (e.g., `https://github.com/settings/installations/12345` → Installation ID is `12345`)
|
|
|
|
#### Step 4: Configure Repository Secrets
|
|
|
|
Add the following secrets to your repository (**Settings → Secrets and variables → Actions**):
|
|
|
|
| Secret | Description |
|
|
|--------|-------------|
|
|
| `GITHUB_APP_ID` | Your GitHub App's ID |
|
|
| `GITHUB_APP_PRIVATE_KEY` | Contents of the `.pem` file (including `-----BEGIN RSA PRIVATE KEY-----` and `-----END RSA PRIVATE KEY-----`) |
|
|
| `GITHUB_APP_INSTALLATION_ID` | (Optional) The Installation ID from Step 3 — only needed for apps with multiple installations |
|
|
|
|
#### Step 5: Pass the App token to the action
|
|
|
|
Mint a token with `actions/create-github-app-token` and pass it via the `github_token` input:
|
|
|
|
```yaml
|
|
- name: Get GitHub App Token
|
|
id: app-token
|
|
uses: actions/create-github-app-token@main
|
|
with:
|
|
app-id: ${{ secrets.GITHUB_APP_ID }}
|
|
private-key: ${{ secrets.GITHUB_APP_PRIVATE_KEY }}
|
|
|
|
- uses: alibaba/open-code-review@main
|
|
with:
|
|
github_token: ${{ steps.app-token.outputs.token }}
|
|
llm_url: ${{ secrets.OCR_LLM_URL }}
|
|
llm_auth_token: ${{ secrets.OCR_LLM_AUTH_TOKEN }}
|
|
llm_model: ${{ vars.OCR_LLM_MODEL }}
|
|
llm_use_anthropic: ${{ vars.OCR_LLM_USE_ANTHROPIC }}
|
|
```
|
|
|
|
Now review comments will be posted with your custom GitHub App identity (e.g., `OpenCodeReview Bot`), providing a more professional and distinguishable appearance in your PRs.
|
|
|
|
## Example Output
|
|
|
|
The action posts two kinds of output on the PR: a **summary issue comment** (in the PR conversation) and **inline review comments** (in the "Files changed" tab).
|
|
|
|
### Summary comment
|
|
|
|
A single comment — updated in place on each run when `sticky_summary` is `'true'` (the default) — carries the review outcome and posting statistics.
|
|
|
|
- ✅ No issues: `✅ **OpenCodeReview**: No comments generated. Looks good to me.`
|
|
- 🔍 Issues found: a header line plus per-outcome counts, for example:
|
|
|
|
```markdown
|
|
🔍 **OpenCodeReview** found **3** issue(s) in this PR.
|
|
- ✅ Successfully posted inline: 2 comment(s)
|
|
- 📝 In summary (no line info): 1 comment(s)
|
|
```
|
|
|
|
The counts are mutually exclusive and sum to the total: `inline` (landed as review inline comments), `summary` (no line info, rendered in the summary body), `skipped` (suppressed by incremental overlap filtering), and `failed` (had line info but could not be posted). Any warnings are appended as a bulleted list.
|
|
|
|
### Inline comments
|
|
|
|
Comments with valid line info are posted as PR review comments in "Files changed". Each carries the review content plus, when a fix is available, a GitHub-native `suggestion` block so reviewers can apply it with one click:
|
|
|
|
````markdown
|
|
**Suggestion:**
|
|
```suggestion
|
|
// Fixed code here
|
|
```
|
|
````
|
|
|
|
Comments that have no line info, or that could not be posted inline (e.g. their line fell outside the current diff), are rendered in the summary body instead — each under a `### 📄 <path>` heading, with a collapsible `<details>` "💡 Suggested Change" (Before/After) when a fix is available.
|
|
|
|
## Supported LLM Providers
|
|
|
|
OCR supports both OpenAI and Anthropic API formats:
|
|
|
|
- **OpenAI-compatible APIs** (default):
|
|
- OpenAI (GPT-4o, GPT-4, etc.)
|
|
- Azure OpenAI
|
|
- Self-hosted models (vLLM, Ollama, etc.)
|
|
- **Anthropic APIs** (set variable `OCR_LLM_USE_ANTHROPIC=true`, i.e. `llm_use_anthropic: true`):
|
|
- Anthropic Claude models
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
1. **Job fails / "Failed to parse OCR output"**: When `ocr review` exits non-zero the action fails the job with that exit code (the comment-posting step is skipped); a zero exit with malformed JSON surfaces as a parse error in the summary. In both cases, check that `OCR_LLM_URL` and `OCR_LLM_AUTH_TOKEN` are set correctly, then inspect the uploaded `ocr-stderr.log` artifact (also printed in the "Run OpenCodeReview" step log) for the underlying error.
|
|
2. **"Cannot find merge-base"**: The action fetches full history (`fetch-depth: 0`) and the PR head (`git fetch origin pull/<n>/head`); if this still fails, ensure `permissions: contents: read` is set and the base branch is accessible (e.g., not deleted).
|
|
3. **Review comments not on the expected lines**: Comments are attached to the PR head commit. If a comment's line falls outside the current diff (the PR was force-pushed or updated mid-review), GitHub rejects the inline post and the comment is rendered in the summary instead. The workflow's concurrency group cancels stale runs on new pushes.
|
|
4. **No summary or comments at all**: Confirm the job's `permissions` include `pull-requests: write`, and that `github_token` (defaults to `${{ github.token }}`) is not overridden with a token lacking those scopes.
|
|
|
|
### Debugging
|
|
|
|
The action does not use an `OCR_DEBUG` flag. To diagnose a run:
|
|
|
|
- **Artifacts**: with `upload_artifacts: 'true'` (the default), the raw `ocr-result.json` and `ocr-stderr.log` are uploaded as workflow artifacts named `ocr-review-result-<run_id>-<run_attempt>`. Download them from the run's **Artifacts** section.
|
|
- **Step log**: the "Run OpenCodeReview" step prints both the JSON result and stderr to the workflow log.
|
|
- **Action outputs**: the step exposes `comments_total`, `comments_inline`, `comments_skipped`, `comments_failed`, and `summary_comment_url` outputs — inspect them in the job's step outputs.
|
|
- **GitHub step debug**: for verbose Actions runner diagnostics, enable the repository secret `ACTIONS_STEP_DEBUG=true` (standard GitHub Actions mechanism).
|
|
|
|
To stop uploading the raw artifacts, set `upload_artifacts: 'false'`.
|