@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 +14 -4
- package/README.ko-KR.md +14 -4
- package/README.md +17 -5
- package/README.zh-CN.md +14 -4
- package/examples/github_actions/README.md +6 -6
- package/examples/github_actions/ocr-review.yml +24 -12
- package/examples/gitlab_ci/.gitlab-ci.yml +41 -20
- package/examples/gitlab_ci/README.md +10 -8
- package/package.json +1 -1
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
|
|
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
|
-
> - **
|
|
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
|
|
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
|
-
> - **
|
|
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
|
-
|
|
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 **
|
|
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 "
|
|
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
|
-
|
|
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
|
-
> - 如果路由的是 **
|
|
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,
|
|
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
|
|
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.
|
|
49
|
+
Modify the `on.pull_request_target.types` array in the workflow file:
|
|
50
50
|
|
|
51
51
|
```yaml
|
|
52
52
|
on:
|
|
53
|
-
|
|
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 == '
|
|
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 == '
|
|
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
|
|
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 == '
|
|
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 != '
|
|
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.
|
|
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
|
|
83
|
-
|
|
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
|
-
|
|
97
|
+
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
|
|
86
98
|
else
|
|
87
99
|
BASE_REF="${{ steps.pr-context.outputs.base_ref }}"
|
|
88
|
-
|
|
100
|
+
HEAD_SHA="${{ steps.pr-context.outputs.head_sha }}"
|
|
89
101
|
fi
|
|
90
102
|
|
|
91
|
-
echo "Reviewing PR: ${
|
|
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 "
|
|
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 === '
|
|
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
|
|
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 "
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
96
|
-
"start_sha": start_sha
|
|
97
|
-
"head_sha": head_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={
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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` |
|
|
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`
|
|
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
|
|
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
|
|
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
|
|
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",
|
|
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
|