@alibaba-group/open-code-review 1.2.5 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ja-JP.md CHANGED
@@ -117,27 +117,33 @@ sudo cp dist/opencodereview /usr/local/bin/ocr
117
117
  # オプションA: 対話的な設定
118
118
  ocr config set llm.url https://api.anthropic.com/v1/messages
119
119
  ocr config set llm.auth_token your-api-key-here
120
- ocr config set llm.auth_header x-api-key
121
120
  ocr config set llm.model claude-opus-4-6
122
121
  ocr config set llm.use_anthropic true
123
122
 
124
123
  # オプションB: 環境変数(最優先)
125
124
  export OCR_LLM_URL=https://api.anthropic.com/v1/messages
126
125
  export OCR_LLM_TOKEN=your-api-key-here
127
- export OCR_LLM_AUTH_HEADER=x-api-key
128
126
  export OCR_LLM_MODEL=claude-opus-4-6
129
127
  export OCR_USE_ANTHROPIC=true
130
128
  ```
131
129
 
132
130
  設定は`~/.opencodereview/config.json`に保存されます。
133
131
 
134
- Anthropicでは、標準の`sk-ant-*` APIキーは`x-api-key`を使用し、OAuthトークンは`authorization`を使用します。`llm.auth_header` / `OCR_LLM_AUTH_HEADER`を省略した場合、OCRは既存の`authorization` bearer-token動作を維持します。
132
+ **`auth_header`(オプション):** Anthropic使用時にAPIキーを送信するHTTPヘッダーを制御します。省略時のデフォルトは`authorization`(Bearerトークン)です。標準の`sk-ant-*` APIキーを使用する場合は、`x-api-key`に設定する必要があります:
133
+
134
+ ```bash
135
+ ocr config set llm.auth_header x-api-key
136
+ # または
137
+ export OCR_LLM_AUTH_HEADER=x-api-key
138
+ ```
139
+
140
+ サポートされる値:`x-api-key`、`authorization`(エイリアス:`bearer`)。それ以外の値はエラーになります。
135
141
 
136
142
  また、Claude Codeの環境変数(`ANTHROPIC_BASE_URL`、`ANTHROPIC_AUTH_TOKEN`、`ANTHROPIC_MODEL`)とも互換性があり、`~/.zshrc` / `~/.bashrc`からこれらのexportをパースします。
137
143
 
138
144
  > **CC-Switchユーザー向けの注意**: [CC-Switch](https://github.com/farion1231/cc-switch)を[ルーティングサービス](https://www.ccswitch.io/en/docs?section=proxy&item=service)有効で使用している場合、追加設定なしで`llm.url`をCC-Switchのプロキシアドレスに向けることができます:
139
145
  > - **Claude**プロバイダーの場合: `llm.url`を`http://127.0.0.1:15721`に設定
140
- > - **CodeX**プロバイダーの場合: `llm.url`を`http://127.0.0.1:15721/v1`に設定
146
+ > - **Codex**プロバイダーの場合: `llm.url`を`http://127.0.0.1:15721/v1`に設定
141
147
  > - `llm.model`はプロバイダー設定に応じて設定
142
148
  > - `llm.auth_token`は任意の値で構いません
143
149
  > - `extra_body`設定は引き続き有効です
@@ -290,6 +296,7 @@ ocr review \
290
296
  | `--concurrency` | — | `8` | ファイルレビューの最大同時実行数 |
291
297
  | `--timeout` | — | `10` | 同時実行タスクのタイムアウト(分) |
292
298
  | `--audience` | — | `human` | `human`(進捗を表示)または`agent`(サマリーのみ) |
299
+ | `--background` | `-b` | — | レビューのための任意の要件/ビジネスコンテキスト。`--commit`使用時に未指定の場合、コミットメッセージから自動取得 |
293
300
  | `--rule` | — | — | カスタムJSONレビュールールへのパス |
294
301
  | `--max-tools` | — | 組み込み値 | ファイルごとのツール呼び出しラウンドの上限。テンプレートのデフォルトより大きい場合のみ有効 |
295
302
  | `--max-git-procs` | — | 組み込み値 | gitサブプロセスの最大同時実行数 |
@@ -311,6 +318,9 @@ ocr review --from main --to my-feature --concurrency 4
311
318
  # 特定のコミットを詳細なJSON出力でレビュー
312
319
  ocr review --commit abc123 --format json --audience agent
313
320
 
321
+ # 要件コンテキストを提供してより的確なレビューを実施
322
+ ocr review --background "ログインAPIにレート制限を追加"
323
+
314
324
  # カスタムレビュールールを使用
315
325
  ocr review --rule /path/to/my-rules.json
316
326
 
package/README.ko-KR.md CHANGED
@@ -117,27 +117,33 @@ sudo cp dist/opencodereview /usr/local/bin/ocr
117
117
  # Option A: 대화형 config
118
118
  ocr config set llm.url https://api.anthropic.com/v1/messages
119
119
  ocr config set llm.auth_token your-api-key-here
120
- ocr config set llm.auth_header x-api-key
121
120
  ocr config set llm.model claude-opus-4-6
122
121
  ocr config set llm.use_anthropic true
123
122
 
124
123
  # Option B: 환경 변수(가장 높은 우선순위)
125
124
  export OCR_LLM_URL=https://api.anthropic.com/v1/messages
126
125
  export OCR_LLM_TOKEN=your-api-key-here
127
- export OCR_LLM_AUTH_HEADER=x-api-key
128
126
  export OCR_LLM_MODEL=claude-opus-4-6
129
127
  export OCR_USE_ANTHROPIC=true
130
128
  ```
131
129
 
132
130
  config는 `~/.opencodereview/config.json`에 저장됩니다.
133
131
 
134
- Anthropic에서는 표준 `sk-ant-*` API key `x-api-key`를 사용하고, OAuth token은 `authorization`을 사용합니다. `llm.auth_header` / `OCR_LLM_AUTH_HEADER`를 생략하면 OCR은 기존 `authorization` bearer-token 동작을 유지합니다.
132
+ **`auth_header` (선택사항):** Anthropic 사용 API key 전송할 HTTP header를 제어합니다. 생략하면 기본값은 `authorization` (Bearer token)입니다. 표준 `sk-ant-*` API key를 사용하는 경우 `x-api-key`로 설정해야 합니다:
133
+
134
+ ```bash
135
+ ocr config set llm.auth_header x-api-key
136
+ # 또는
137
+ export OCR_LLM_AUTH_HEADER=x-api-key
138
+ ```
139
+
140
+ 지원되는 값: `x-api-key`, `authorization` (별칭: `bearer`). 그 외 값은 오류로 처리됩니다.
135
141
 
136
142
  Claude Code 환경 변수(`ANTHROPIC_BASE_URL`, `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_MODEL`)와도 호환되며, `~/.zshrc` / `~/.bashrc`의 export도 파싱합니다.
137
143
 
138
144
  > **CC-Switch 사용자 참고**: [CC-Switch](https://github.com/farion1231/cc-switch)를 [routing service](https://www.ccswitch.io/en/docs?section=proxy&item=service)와 함께 사용한다면, 추가 설정 없이 `llm.url`을 CC-Switch proxy 주소로 지정할 수 있습니다.
139
145
  > - **Claude** provider: `llm.url`을 `http://127.0.0.1:15721`로 설정
140
- > - **CodeX** provider: `llm.url`을 `http://127.0.0.1:15721/v1`로 설정
146
+ > - **Codex** provider: `llm.url`을 `http://127.0.0.1:15721/v1`로 설정
141
147
  > - provider 설정에 맞게 `llm.model` 설정
142
148
  > - `llm.auth_token`은 아무 값이나 사용할 수 있음
143
149
  > - `extra_body` 설정은 그대로 적용됨
@@ -290,6 +296,7 @@ ocr review \
290
296
  | `--concurrency` | - | `8` | 최대 동시 파일 리뷰 수 |
291
297
  | `--timeout` | - | `10` | 동시 task timeout(분) |
292
298
  | `--audience` | - | `human` | `human`(progress 표시) 또는 `agent`(summary only) |
299
+ | `--background` | `-b` | - | 리뷰를 위한 선택적 요구사항/비즈니스 컨텍스트. `--commit` 사용 시 미지정이면 commit message에서 자동 추출 |
293
300
  | `--rule` | - | - | custom JSON review rules 경로 |
294
301
  | `--max-tools` | - | built-in | 파일별 최대 tool call round. template default보다 클 때만 적용 |
295
302
  | `--max-git-procs` | - | built-in | 최대 동시 git subprocess 수 |
@@ -311,6 +318,9 @@ ocr review --from main --to my-feature --concurrency 4
311
318
  # 특정 commit을 verbose JSON output으로 리뷰
312
319
  ocr review --commit abc123 --format json --audience agent
313
320
 
321
+ # 요구사항 컨텍스트를 제공하여 더 정확한 리뷰 수행
322
+ ocr review --background "로그인 API에 rate limiting 추가"
323
+
314
324
  # custom review rules 사용
315
325
  ocr review --rule /path/to/my-rules.json
316
326
 
package/README.md CHANGED
@@ -117,27 +117,33 @@ sudo cp dist/opencodereview /usr/local/bin/ocr
117
117
  # Option A: Interactive config
118
118
  ocr config set llm.url https://api.anthropic.com/v1/messages
119
119
  ocr config set llm.auth_token your-api-key-here
120
- ocr config set llm.auth_header x-api-key
121
120
  ocr config set llm.model claude-opus-4-6
122
121
  ocr config set llm.use_anthropic true
123
122
 
124
123
  # Option B: Environment variables (highest priority)
125
124
  export OCR_LLM_URL=https://api.anthropic.com/v1/messages
126
125
  export OCR_LLM_TOKEN=your-api-key-here
127
- export OCR_LLM_AUTH_HEADER=x-api-key
128
126
  export OCR_LLM_MODEL=claude-opus-4-6
129
127
  export OCR_USE_ANTHROPIC=true
130
128
  ```
131
129
 
132
130
  Config is stored in `~/.opencodereview/config.json`.
133
131
 
134
- For Anthropic, standard `sk-ant-*` API keys use `x-api-key`; OAuth tokens use `authorization`. If `llm.auth_header` / `OCR_LLM_AUTH_HEADER` is omitted, OCR keeps the existing `authorization` bearer-token behavior.
132
+ **`auth_header` (optional):** Controls which HTTP header carries the API key when using Anthropic. Defaults to `authorization` (Bearer token) if omitted. If you use a standard `sk-ant-*` API key, you must set it to `x-api-key`:
133
+
134
+ ```bash
135
+ ocr config set llm.auth_header x-api-key
136
+ # or
137
+ export OCR_LLM_AUTH_HEADER=x-api-key
138
+ ```
139
+
140
+ Supported values: `x-api-key`, `authorization` (alias: `bearer`). Other values are rejected with an error.
135
141
 
136
142
  It is also compatible with Claude Code environment variables (`ANTHROPIC_BASE_URL`, `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_MODEL`) and parses `~/.zshrc` / `~/.bashrc` for those exports.
137
143
 
138
144
  > **Note for CC-Switch Users**: If you are using [CC-Switch](https://github.com/farion1231/cc-switch) with [routing service](https://www.ccswitch.io/en/docs?section=proxy&item=service) enabled, you can point `llm.url` to the CC-Switch proxy address without additional configuration:
139
145
  > - For **Claude** provider: set `llm.url` to `http://127.0.0.1:15721`
140
- > - For **CodeX** provider: set `llm.url` to `http://127.0.0.1:15721/v1`
146
+ > - For **Codex** provider: set `llm.url` to `http://127.0.0.1:15721/v1`
141
147
  > - Set `llm.model` according to your provider settings
142
148
  > - `llm.auth_token` can be any value
143
149
  > - `extra_body` settings still apply
@@ -255,10 +261,12 @@ The core command for CI integration:
255
261
  ```bash
256
262
  ocr review \
257
263
  --from "origin/main" \
258
- --to "origin/feature-branch" \
264
+ --to "<commit_sha>" \
259
265
  --format json
260
266
  ```
261
267
 
268
+ The `--from` flag accepts a branch ref (e.g., `origin/main`) or commit SHA as the base, while `--to` accepts a commit SHA or branch ref as the head. In CI environments, using commit SHA for `--to` is recommended to correctly handle fork PRs/MRs where the source branch doesn't exist on the origin remote.
269
+
262
270
  The `--format json` flag outputs machine-readable results suitable for parsing in CI scripts.
263
271
 
264
272
  See the [`examples/`](./examples/) directory for integration examples:
@@ -290,6 +298,7 @@ See the [`examples/`](./examples/) directory for integration examples:
290
298
  | `--concurrency` | — | `8` | Max concurrent file reviews |
291
299
  | `--timeout` | — | `10` | Concurrent task timeout in minutes |
292
300
  | `--audience` | — | `human` | `human` (show progress) or `agent` (summary only) |
301
+ | `--background` | `-b` | — | Optional requirement/business context for the review; auto-filled from commit message when using `--commit` |
293
302
  | `--rule` | — | — | Path to custom JSON review rules |
294
303
  | `--max-tools` | — | built-in | Max tool call rounds per file; only takes effect when greater than template default |
295
304
  | `--max-git-procs` | — | built-in | Max concurrent git subprocesses |
@@ -311,6 +320,9 @@ ocr review --from main --to my-feature --concurrency 4
311
320
  # Review a specific commit with verbose JSON output
312
321
  ocr review --commit abc123 --format json --audience agent
313
322
 
323
+ # Provide requirement context for more targeted review
324
+ ocr review --background "Adding rate limiting to the login API"
325
+
314
326
  # Use custom review rules
315
327
  ocr review --rule /path/to/my-rules.json
316
328
 
package/README.zh-CN.md CHANGED
@@ -117,27 +117,33 @@ sudo cp dist/opencodereview /usr/local/bin/ocr
117
117
  # 方式 A:交互式配置
118
118
  ocr config set llm.url https://api.anthropic.com/v1/messages
119
119
  ocr config set llm.auth_token your-api-key-here
120
- ocr config set llm.auth_header x-api-key
121
120
  ocr config set llm.model claude-opus-4-6
122
121
  ocr config set llm.use_anthropic true
123
122
 
124
123
  # 方式 B:环境变量(优先级最高)
125
124
  export OCR_LLM_URL=https://api.anthropic.com/v1/messages
126
125
  export OCR_LLM_TOKEN=your-api-key-here
127
- export OCR_LLM_AUTH_HEADER=x-api-key
128
126
  export OCR_LLM_MODEL=claude-opus-4-6
129
127
  export OCR_USE_ANTHROPIC=true
130
128
  ```
131
129
 
132
130
  配置存储于 `~/.opencodereview/config.json`。
133
131
 
134
- 对于 Anthropic,标准 `sk-ant-*` API key 使用 `x-api-key`;OAuth token 使用 `authorization`。如果未配置 `llm.auth_header` / `OCR_LLM_AUTH_HEADER`,OCR 会保留现有的 `authorization` bearer-token 行为。
132
+ **`auth_header`(可选):** 控制使用 Anthropic 时通过哪个 HTTP header 传递 API key。省略时默认为 `authorization`(Bearer token)。如果你使用标准 `sk-ant-*` API key,需要将其设为 `x-api-key`:
133
+
134
+ ```bash
135
+ ocr config set llm.auth_header x-api-key
136
+ # 或
137
+ export OCR_LLM_AUTH_HEADER=x-api-key
138
+ ```
139
+
140
+ 支持的值:`x-api-key`、`authorization`(别名:`bearer`)。其他值会直接报错。
135
141
 
136
142
  同时兼容了 Claude Code 环境变量(`ANTHROPIC_BASE_URL`、`ANTHROPIC_AUTH_TOKEN`、`ANTHROPIC_MODEL`),并解析 `~/.zshrc` / `~/.bashrc` 中的相关导出。
137
143
 
138
144
  > **CC-Switch 用户特别提醒**:如果你使用 [CC-Switch](https://github.com/farion1231/cc-switch) 并开启了[路由服务](https://www.ccswitch.io/zh/docs?section=proxy&item=service),可以将 `llm.url` 配置成 CC-Switch 启动的代理地址,无需额外配置:
139
145
  > - 如果路由的是 **Claude** 供应商:设置 `llm.url` 为 `http://127.0.0.1:15721`
140
- > - 如果路由的是 **CodeX** 供应商:设置 `llm.url` 为 `http://127.0.0.1:15721/v1`
146
+ > - 如果路由的是 **Codex** 供应商:设置 `llm.url` 为 `http://127.0.0.1:15721/v1`
141
147
  > - `llm.model` 根据你的供应商设置进行配置
142
148
  > - `llm.auth_token` 可以设置成任意值
143
149
  > - `extra_body` 设置依然生效
@@ -290,6 +296,7 @@ ocr review \
290
296
  | `--concurrency` | — | `8` | 最大并发文件审查数 |
291
297
  | `--timeout` | — | `10` | 并发任务超时时间(分钟) |
292
298
  | `--audience` | — | `human` | `human`(显示进度)或 `agent`(仅输出摘要) |
299
+ | `--background` | `-b` | — | 可选的需求/业务背景信息;使用 `--commit` 时如未指定则自动从 commit message 中提取 |
293
300
  | `--rule` | — | — | 自定义 JSON 审查规则路径 |
294
301
  | `--max-tools` | — | 内置默认 | 每个文件的最大工具调用轮次;仅在大于模板默认值时生效 |
295
302
  | `--max-git-procs` | — | 内置默认 | 最大并发 git 子进程数 |
@@ -311,6 +318,9 @@ ocr review --from main --to my-feature --concurrency 4
311
318
  # 审查特定提交并以 JSON 格式输出详细信息
312
319
  ocr review --commit abc123 --format json --audience agent
313
320
 
321
+ # 提供需求背景以获得更有针对性的审查
322
+ ocr review --background "为登录 API 添加限流"
323
+
314
324
  # 使用自定义审查规则
315
325
  ocr review --rule /path/to/my-rules.json
316
326
 
@@ -10,10 +10,10 @@ PR Created/Updated → GitHub Actions Triggered → OCR Reviews Diff → Comment
10
10
  Comment with trigger keyword ↗
11
11
  ```
12
12
 
13
- 1. When a PR is opened, synchronized, or reopened, the workflow triggers
13
+ 1. When a PR is opened, the workflow triggers (uses `pull_request_target` for fork secret access)
14
14
  2. Alternatively, when a comment containing `/open-code-review` or `@open-code-review` is posted on a PR, the workflow triggers
15
15
  3. It installs OCR via `npm install -g @alibaba-group/open-code-review`
16
- 4. Runs `ocr review --from origin/<base> --to origin/<head> --format json` to analyze the diff
16
+ 4. Runs `ocr review --from origin/<base> --to <head_sha> --format json` to analyze the diff (uses commit SHA to support fork PRs)
17
17
  5. Parses the JSON output and posts inline review comments on the PR using GitHub's Pull Request Review API
18
18
 
19
19
  ## Setup
@@ -46,11 +46,11 @@ Go to your repository's **Settings → Secrets and variables → Actions** and a
46
46
 
47
47
  ### Change the trigger events
48
48
 
49
- Modify the `on.pull_request.types` array in the workflow file:
49
+ Modify the `on.pull_request_target.types` array in the workflow file:
50
50
 
51
51
  ```yaml
52
52
  on:
53
- pull_request:
53
+ pull_request_target:
54
54
  types: [opened, synchronize, reopened, ready_for_review]
55
55
  ```
56
56
 
@@ -60,7 +60,7 @@ By default, the workflow triggers when a PR comment starts with `/open-code-revi
60
60
 
61
61
  ```yaml
62
62
  if: |
63
- github.event_name == 'pull_request' ||
63
+ github.event_name == 'pull_request_target' ||
64
64
  (github.event_name == 'issue_comment' && github.event.issue.pull_request && startsWith(github.event.comment.body, '/review')) ||
65
65
  (github.event_name == 'issue_comment' && github.event.issue.pull_request && startsWith(github.event.comment.body, '@mybot'))
66
66
  ```
@@ -69,7 +69,7 @@ Or use a more flexible pattern with `contains` to trigger on any comment contain
69
69
 
70
70
  ```yaml
71
71
  if: |
72
- github.event_name == 'pull_request' ||
72
+ github.event_name == 'pull_request_target' ||
73
73
  (github.event_name == 'issue_comment' && github.event.issue.pull_request && contains(github.event.comment.body, '/review'))
74
74
  ```
75
75
 
@@ -4,7 +4,7 @@
4
4
  # and posts review comments directly on the PR.
5
5
  #
6
6
  # Triggers:
7
- # - PR opened, synchronized, or reopened
7
+ # - PR opened (uses pull_request_target for fork secret access)
8
8
  # - Comment on PR containing '/open-code-review' or '@open-code-review'
9
9
  #
10
10
  # Required secrets:
@@ -18,8 +18,15 @@
18
18
 
19
19
  name: OpenCodeReview PR Review
20
20
 
21
+ concurrency:
22
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
23
+ cancel-in-progress: true
24
+
21
25
  on:
22
- pull_request:
26
+ # Use pull_request_target instead of pull_request so that secrets are
27
+ # available even for PRs from forks. This is safe because OCR only reads
28
+ # the diff and does not execute any code from the PR.
29
+ pull_request_target:
23
30
  types: [opened]
24
31
  issue_comment:
25
32
  types: [created]
@@ -33,13 +40,13 @@ jobs:
33
40
  runs-on: ubuntu-latest
34
41
  # Run on PR events, or on comments starting with trigger keywords
35
42
  if: |
36
- github.event_name == 'pull_request' ||
43
+ github.event_name == 'pull_request_target' ||
37
44
  (github.event_name == 'issue_comment' && github.event.issue.pull_request && startsWith(github.event.comment.body, '/open-code-review')) ||
38
45
  (github.event_name == 'issue_comment' && github.event.issue.pull_request && startsWith(github.event.comment.body, '@open-code-review'))
39
46
  steps:
40
47
  - name: Get PR context
41
48
  id: pr-context
42
- if: github.event_name != 'pull_request'
49
+ if: github.event_name != 'pull_request_target'
43
50
  uses: actions/github-script@v7
44
51
  with:
45
52
  script: |
@@ -58,7 +65,10 @@ jobs:
58
65
  uses: actions/checkout@v4
59
66
  with:
60
67
  fetch-depth: 0 # Full history needed for merge-base diff
61
- ref: ${{ github.event_name != 'pull_request' && steps.pr-context.outputs.head_sha || '' }}
68
+ ref: ${{ github.event.pull_request.head.sha || steps.pr-context.outputs.head_sha }}
69
+
70
+ - name: Fetch PR head ref (ensures fork commits are available)
71
+ run: git fetch origin pull/${{ github.event.pull_request.number || github.event.issue.number }}/head
62
72
 
63
73
  - name: Setup Node.js
64
74
  uses: actions/setup-node@v4
@@ -79,21 +89,23 @@ jobs:
79
89
  - name: Run OpenCodeReview
80
90
  id: review
81
91
  run: |
82
- # Get base and head refs from PR context (different for comment triggers)
83
- if [ "${{ github.event_name }}" = "pull_request" ]; then
92
+ # Get base ref and head SHA from PR context (different for comment triggers)
93
+ # Note: We use HEAD_SHA instead of origin/${HEAD_REF} to support fork PRs,
94
+ # because fork branches don't exist on the origin remote.
95
+ if [ "${{ github.event_name }}" = "pull_request_target" ]; then
84
96
  BASE_REF="${{ github.event.pull_request.base.ref }}"
85
- HEAD_REF="${{ github.event.pull_request.head.ref }}"
97
+ HEAD_SHA="${{ github.event.pull_request.head.sha }}"
86
98
  else
87
99
  BASE_REF="${{ steps.pr-context.outputs.base_ref }}"
88
- HEAD_REF="${{ steps.pr-context.outputs.head_ref }}"
100
+ HEAD_SHA="${{ steps.pr-context.outputs.head_sha }}"
89
101
  fi
90
102
 
91
- echo "Reviewing PR: ${HEAD_REF} against ${BASE_REF}"
103
+ echo "Reviewing PR: ${HEAD_SHA} against origin/${BASE_REF}"
92
104
 
93
105
  # Run OCR in range mode with JSON output
94
106
  ocr review \
95
107
  --from "origin/${BASE_REF}" \
96
- --to "origin/${HEAD_REF}" \
108
+ --to "${HEAD_SHA}" \
97
109
  --format json \
98
110
  > /tmp/ocr-result.json 2>/tmp/ocr-stderr.log || true
99
111
 
@@ -150,7 +162,7 @@ jobs:
150
162
  let commitSha;
151
163
 
152
164
  // Get commit SHA from event context
153
- if (context.eventName === 'pull_request') {
165
+ if (context.eventName === 'pull_request_target') {
154
166
  commitSha = context.payload.pull_request.head.sha;
155
167
  } else {
156
168
  // For comment events, we need to fetch the PR
@@ -2,20 +2,30 @@
2
2
  #
3
3
  # This pipeline automatically reviews Merge Requests using OpenCodeReview
4
4
  # and posts review comments (discussions) directly on the MR diff.
5
+ # Supports both same-repo and forked MR scenarios.
5
6
  #
6
7
  # Required CI/CD Variables (Settings → CI/CD → Variables):
7
8
  # OCR_LLM_URL - LLM API endpoint (e.g., https://api.openai.com/v1/chat/completions)
8
9
  # OCR_LLM_AUTH_TOKEN - Authentication token for the LLM API (mark as "Masked")
9
- # GITLAB_API_TOKEN - GitLab Personal/Project Access Token with "api" scope
10
10
  #
11
11
  # Optional CI/CD Variables:
12
12
  # OCR_LLM_MODEL - Model name (default: gpt-4o)
13
+ # GITLAB_API_TOKEN - GitLab Personal/Project Access Token with "api" scope
14
+ # (falls back to CI_JOB_TOKEN if not set)
15
+ #
16
+ # Fork MR Support:
17
+ # The script uses CI_COMMIT_SHA as the diff target to correctly resolve the
18
+ # source commit from forked repos. For some GitLab versions, you may need to enable:
19
+ # Project Settings → CI/CD → General pipelines →
20
+ # "Run pipelines in the parent project for merge requests from forked projects"
13
21
 
14
22
  stages:
15
23
  - review
16
24
 
17
25
  code-review:
18
26
  stage: review
27
+ interruptible: true
28
+ resource_group: mr-review-$CI_MERGE_REQUEST_IID
19
29
  image: node:20
20
30
  only:
21
31
  - merge_requests
@@ -27,7 +37,7 @@ code-review:
27
37
 
28
38
  # Configure OCR
29
39
  - mkdir -p ~/.open-code-review
30
- # Gitlab CI/CD does not support setting variables with value length less than 8, so you can't set use_anthropic as a CI variable
40
+ # Gitlab CI/CD does not support configuring variables with value length less than 8, so you can't set use_anthropic as a CI variable
31
41
  - |
32
42
  ocr config set llm.url $OCR_LLM_URL
33
43
  ocr config set llm.auth_token $OCR_LLM_AUTH_TOKEN
@@ -35,13 +45,14 @@ code-review:
35
45
  ocr config set llm.use_anthropic false
36
46
  ocr config set llm.extra_body '{"thinking": {"type": "disabled"}}'
37
47
 
38
- # Run OCR review
48
+ # Run OCR review (use CI_COMMIT_SHA for --to to support both same-repo and forked MRs)
39
49
  - |
40
50
  echo "Reviewing MR: ${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME} against ${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}"
41
51
  ocr review \
42
52
  --from "origin/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}" \
43
- --to "origin/${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}" \
53
+ --to "${CI_COMMIT_SHA}" \
44
54
  --format json \
55
+ --audience agent \
45
56
  > /tmp/ocr-result.json 2>/tmp/ocr-stderr.log || true
46
57
  echo "OCR review completed."
47
58
  cat /tmp/ocr-result.json
@@ -58,18 +69,27 @@ code-review:
58
69
  GITLAB_URL = os.environ.get("CI_SERVER_URL", "https://gitlab.com")
59
70
  PROJECT_ID = os.environ["CI_PROJECT_ID"]
60
71
  MR_IID = os.environ["CI_MERGE_REQUEST_IID"]
61
- API_TOKEN = os.environ["GITLAB_API_TOKEN"]
72
+ # Fall back to CI_JOB_TOKEN for fork MR pipelines where GITLAB_API_TOKEN is unavailable
73
+ API_TOKEN = os.environ.get("GITLAB_API_TOKEN") or os.environ.get("CI_JOB_TOKEN", "")
62
74
  SOURCE_BRANCH = os.environ["CI_MERGE_REQUEST_SOURCE_BRANCH_NAME"]
63
75
  TARGET_BRANCH = os.environ["CI_MERGE_REQUEST_TARGET_BRANCH_NAME"]
64
76
  COMMIT_SHA = os.environ["CI_COMMIT_SHA"]
65
77
 
78
+ if not API_TOKEN:
79
+ print("ERROR: No API token available (GITLAB_API_TOKEN or CI_JOB_TOKEN). Cannot post comments.", file=sys.stderr)
80
+ sys.exit(1)
81
+
66
82
  API_BASE = f"{GITLAB_URL}/api/v4/projects/{PROJECT_ID}/merge_requests/{MR_IID}"
67
83
 
84
+ # Determine auth header: PRIVATE-TOKEN for personal/project tokens, JOB-TOKEN for CI_JOB_TOKEN
85
+ USE_JOB_TOKEN = not os.environ.get("GITLAB_API_TOKEN")
86
+ AUTH_HEADER = "JOB-TOKEN" if USE_JOB_TOKEN else "PRIVATE-TOKEN"
87
+
68
88
  def api_request(endpoint, data=None, method="POST"):
69
89
  """Make a GitLab API request."""
70
90
  url = f"{API_BASE}{endpoint}"
71
91
  headers = {
72
- "PRIVATE-TOKEN": API_TOKEN,
92
+ AUTH_HEADER: API_TOKEN,
73
93
  "Content-Type": "application/json"
74
94
  }
75
95
  body = json.dumps(data).encode("utf-8") if data else None
@@ -85,16 +105,16 @@ code-review:
85
105
  """Post a general note/comment on the MR."""
86
106
  return api_request("/notes", {"body": body})
87
107
 
88
- def post_discussion(path, line, body, base_sha=None, start_sha=None, head_sha=None):
108
+ def post_discussion(path, line, body, base_sha, start_sha, head_sha):
89
109
  """Post an inline discussion on a specific file/line in the MR diff."""
90
110
  position = {
91
111
  "position_type": "text",
92
112
  "new_path": path,
93
113
  "old_path": path,
94
114
  "new_line": line,
95
- "base_sha": base_sha or TARGET_BRANCH,
96
- "start_sha": start_sha or TARGET_BRANCH,
97
- "head_sha": head_sha or COMMIT_SHA,
115
+ "base_sha": base_sha,
116
+ "start_sha": start_sha,
117
+ "head_sha": head_sha,
98
118
  }
99
119
  data = {
100
120
  "body": body,
@@ -138,7 +158,7 @@ code-review:
138
158
 
139
159
  # --- Main ---
140
160
 
141
- # Read OCR result
161
+ # Read OCR result (skip first line which is summary, not JSON)
142
162
  try:
143
163
  with open("/tmp/ocr-result.json", "r") as f:
144
164
  result = json.load(f)
@@ -168,7 +188,7 @@ code-review:
168
188
  diff_refs = None
169
189
  try:
170
190
  versions_url = f"{API_BASE}/versions"
171
- req = urllib.request.Request(versions_url, headers={"PRIVATE-TOKEN": API_TOKEN})
191
+ req = urllib.request.Request(versions_url, headers={AUTH_HEADER: API_TOKEN})
172
192
  with urllib.request.urlopen(req) as resp:
173
193
  versions = json.loads(resp.read().decode("utf-8"))
174
194
  if versions:
@@ -191,15 +211,11 @@ code-review:
191
211
  start_line = comment.get("start_line", end_line)
192
212
  body = format_comment(comment)
193
213
 
194
- if not path or not end_line:
214
+ if not path or not end_line or not diff_refs:
195
215
  failed_comments.append(comment)
196
216
  continue
197
217
 
198
- kwargs = {}
199
- if diff_refs:
200
- kwargs = diff_refs
201
-
202
- result_resp = post_discussion(path, end_line, body, **kwargs)
218
+ result_resp = post_discussion(path, end_line, body, **diff_refs)
203
219
  if result_resp:
204
220
  success_count += 1
205
221
  else:
@@ -214,8 +230,13 @@ code-review:
214
230
  fallback_body += format_comment_fallback(comment) + "\n\n---\n\n"
215
231
  post_note(fallback_body)
216
232
 
217
- # Post summary
218
- summary = f"🔍 **OpenCodeReview** found **{len(comments)}** issue(s) in this MR."
233
+ # Post summary last
234
+ total_count = len(comments)
235
+ failed_count = len(failed_comments)
236
+ summary = f"🔍 **OpenCodeReview** found **{total_count}** issue(s) in this MR."
237
+ if total_count > 0:
238
+ summary += f"\n- ✅ {success_count} posted as inline comment(s)"
239
+ summary += f"\n- 📝 {failed_count} posted as summary (missing line info)"
219
240
  if warnings:
220
241
  summary += f"\n\n⚠️ {len(warnings)} warning(s) occurred during review."
221
242
  post_note(summary)
@@ -10,7 +10,7 @@ MR Created/Updated → GitLab Pipeline Triggered → OCR Reviews Diff → Discus
10
10
 
11
11
  1. When a Merge Request is opened or updated, the pipeline triggers
12
12
  2. It installs OCR via npm in a `node:20` Docker image
13
- 3. Runs `ocr review --from origin/<target> --to origin/<source> --format json` to analyze the diff
13
+ 3. Runs `ocr review --from origin/<target> --to <commit_sha> --format json --audience agent` to analyze the diff (uses commit SHA to support fork MRs)
14
14
  4. Parses the JSON output and posts inline discussions on the MR using GitLab's Discussions API
15
15
 
16
16
  ## Setup
@@ -39,7 +39,7 @@ Go to your project's **Settings → CI/CD → Variables** and add:
39
39
  | `OCR_LLM_URL` | Yes | No | LLM API endpoint URL (e.g., `https://api.openai.com/v1/chat/completions`) |
40
40
  | `OCR_LLM_AUTH_TOKEN` | Yes | Yes | API authentication token |
41
41
  | `OCR_LLM_MODEL` | No | No | Model name (defaults to `gpt-4o`) |
42
- | `GITLAB_API_TOKEN` | Yes | Yes | GitLab access token with `api` scope |
42
+ | `GITLAB_API_TOKEN` | No | Yes | GitLab access token with `api` scope (falls back to `CI_JOB_TOKEN` if not set) |
43
43
 
44
44
  > **Note:** GitLab CI/CD does not support variables with values shorter than 8 characters, so `use_anthropic` cannot be set as a CI variable. The pipeline sets it to `false` by default. If you need to use Anthropic Claude models, you'll need to modify the `.gitlab-ci.yml` script directly.
45
45
  >
@@ -53,7 +53,7 @@ You need a token with `api` scope to post discussions on MRs. Options:
53
53
  - **Personal Access Token**: User Settings → Access Tokens → Create with `api` scope
54
54
  - **Group Access Token**: For organization-wide usage
55
55
 
56
- > **Note:** The built-in `CI_JOB_TOKEN` does NOT have sufficient permissions to create MR discussions, which is why a separate token is needed.
56
+ > **Note:** The built-in `CI_JOB_TOKEN` has limited API scope and may not support all discussion features (e.g., creating new threads on older GitLab versions). If `GITLAB_API_TOKEN` is not set, the pipeline falls back to `CI_JOB_TOKEN` automatically — but for best results, a dedicated token with `api` scope is recommended.
57
57
  >
58
58
  > **Tip:** For Project Access Tokens and Group Access Tokens, the token name determines the bot name shown in MR discussions. For example, naming your token `OpenCodeReview Bot` will make review comments appear as posted by `OpenCodeReview Bot`.
59
59
 
@@ -95,7 +95,7 @@ Use the `--rule` flag to pass a custom rules JSON file:
95
95
 
96
96
  ```yaml
97
97
  script:
98
- - ocr review --rule ./my-rules.json --from origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME --to origin/$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
98
+ - ocr review --rule ./my-rules.json --from origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME --to $CI_COMMIT_SHA
99
99
  ```
100
100
 
101
101
  ### Limit concurrency
@@ -104,7 +104,7 @@ Adjust the `--concurrency` flag for large MRs to control the number of concurren
104
104
 
105
105
  ```yaml
106
106
  script:
107
- - ocr review --concurrency 5 --from origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME --to origin/$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
107
+ - ocr review --concurrency 5 --from origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME --to $CI_COMMIT_SHA
108
108
  ```
109
109
 
110
110
  ### Provide background context
@@ -113,7 +113,7 @@ Use the `--background` flag to pass additional context that helps OCR better und
113
113
 
114
114
  ```yaml
115
115
  script:
116
- - ocr review --background "$CI_MERGE_REQUEST_TITLE" --from origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME --to origin/$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
116
+ - ocr review --background "$CI_MERGE_REQUEST_TITLE" --from origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME --to $CI_COMMIT_SHA
117
117
  ```
118
118
 
119
119
  This is particularly useful when your MR titles follow semantic conventions (e.g., `feat(auth): add OAuth2 support`) that clearly summarize what the MR implements. The background information helps OCR provide more relevant and context-aware review comments.
@@ -168,11 +168,13 @@ script:
168
168
 
169
169
  # No existing review found - run OCR
170
170
  print("🔍 No existing OCR review found. Running review...")
171
+ COMMIT_SHA = os.environ["CI_COMMIT_SHA"]
171
172
  result = subprocess.run([
172
173
  "ocr", "review",
173
174
  "--from", f"origin/{TARGET_BRANCH}",
174
- "--to", f"origin/{SOURCE_BRANCH}",
175
- "--format", "json"
175
+ "--to", COMMIT_SHA,
176
+ "--format", "json",
177
+ "--audience", "agent"
176
178
  ], capture_output=True, text=True)
177
179
 
178
180
  # Save output for the posting script
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alibaba-group/open-code-review",
3
- "version": "1.2.5",
3
+ "version": "1.3.0",
4
4
  "description": "OpenCodeReview CLI — AI-powered code review tool",
5
5
  "bin": {
6
6
  "ocr": "bin/ocr.js"