coderev-cli 1.0.20 → 1.0.22
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.md +35 -0
- package/package.json +2 -1
- package/src/cli.js +118 -1
- package/templates/.gitlab-ci.yml +134 -0
- package/templates/github-action.yml +143 -0
package/README.md
CHANGED
|
@@ -736,6 +736,37 @@ coderev review --pr 42 --inline
|
|
|
736
736
|
- 执行内容:对比 PR 的 diff → coderev 审查 → 结果回贴到 PR 评论
|
|
737
737
|
- 效果:每个 PR 自动获得一份 AI 审查报告
|
|
738
738
|
|
|
739
|
+
或使用 GitHub Actions Marketplace 中的 Action:
|
|
740
|
+
|
|
741
|
+
```yaml
|
|
742
|
+
steps:
|
|
743
|
+
- uses: jishuanjimingtian/coderev@v1
|
|
744
|
+
with:
|
|
745
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
746
|
+
api-key: ${{ secrets.DEEPSEEK_API_KEY }}
|
|
747
|
+
```
|
|
748
|
+
|
|
749
|
+
### GitLab CI
|
|
750
|
+
|
|
751
|
+
使用 `coderev init --gitlab-ci` 一键生成配置,或直接将 `templates/.gitlab-ci.yml` 复制到项目根目录。
|
|
752
|
+
|
|
753
|
+
**变量配置**(GitLab → Settings → CI/CD → Variables):
|
|
754
|
+
|
|
755
|
+
| 变量 | 必填 | 说明 |
|
|
756
|
+
|------|------|------|
|
|
757
|
+
| `DEEPSEEK_API_KEY` | ✅ | AI 提供商的 API Key |
|
|
758
|
+
| `GITLAB_TOKEN` | 可选 | GitLab PAT(api scope),用于自动发布 MR 评论 |
|
|
759
|
+
| `CODEREV_CONFIDENCE` | 可选 | 置信度阈值,默认 60 |
|
|
760
|
+
| `CODEREV_MODE` | 可选 | 审查模式:full / security / bugs / quality |
|
|
761
|
+
| `CODEREV_BLAME` | 可选 | 启用 git blame:true / false |
|
|
762
|
+
| `CODEREV_BLOCK` | 可选 | 发现问题时阻塞 MR:true / false |
|
|
763
|
+
|
|
764
|
+
**工作流过程**:
|
|
765
|
+
1. MR 创建/更新时自动触发
|
|
766
|
+
2. 生成 MR diff → coderev 3 Agent 并行审查
|
|
767
|
+
3. 审查结果作为 MR 评论自动发布(需 GITLAB_TOKEN)
|
|
768
|
+
4. 如开启 `CODEREV_BLOCK`,发现问题时 pipeline 失败
|
|
769
|
+
|
|
739
770
|
### 自定义 CI 集成
|
|
740
771
|
|
|
741
772
|
在任意 CI 管道中:
|
|
@@ -805,6 +836,10 @@ A:可以,审查时加 `--no-cache` 参数即可跳过缓存。
|
|
|
805
836
|
A:在 `.coderevrc.json` 的 `rules.custom` 数组中添加。详见上方「自定义规则」章节。
|
|
806
837
|
|
|
807
838
|
---
|
|
839
|
+
## Contributing
|
|
840
|
+
|
|
841
|
+
欢迎贡献!详见 [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
842
|
+
|
|
808
843
|
## License
|
|
809
844
|
|
|
810
845
|
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coderev-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.22",
|
|
4
4
|
"description": "Multi-agent AI code review for git -- parallel agents with confidence scoring",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"files": [
|
|
37
37
|
"src/",
|
|
38
|
+
"templates/",
|
|
38
39
|
"README.md",
|
|
39
40
|
".env.example"
|
|
40
41
|
],
|
package/src/cli.js
CHANGED
|
@@ -639,7 +639,9 @@ fi
|
|
|
639
639
|
program
|
|
640
640
|
.command('init')
|
|
641
641
|
.description('Create a default coderev config file')
|
|
642
|
-
.
|
|
642
|
+
.option('--gitlab-ci', 'Generate a .gitlab-ci.yml template for GitLab CI/CD review')
|
|
643
|
+
.option('--github-action', 'Generate a GitHub Actions workflow for PR review')
|
|
644
|
+
.action((options) => {
|
|
643
645
|
const fs = require('fs');
|
|
644
646
|
const path = require('path');
|
|
645
647
|
const defaultConfig = {
|
|
@@ -708,6 +710,121 @@ build/
|
|
|
708
710
|
fs.writeFileSync(hintPath, hintContent);
|
|
709
711
|
console.log(chalk.green(`✔ Default .coderevhint created at ${hintPath}`));
|
|
710
712
|
}
|
|
713
|
+
|
|
714
|
+
// --gitlab-ci: generate GitLab CI template
|
|
715
|
+
if (options.gitlabCi) {
|
|
716
|
+
const ciPath = path.join(process.cwd(), '.gitlab-ci.yml');
|
|
717
|
+
if (fs.existsSync(ciPath)) {
|
|
718
|
+
console.log(chalk.yellow(`⚠ .gitlab-ci.yml already exists. Skipping.`));
|
|
719
|
+
} else {
|
|
720
|
+
const templatePath = path.join(__dirname, '..', 'templates', '.gitlab-ci.yml');
|
|
721
|
+
if (fs.existsSync(templatePath)) {
|
|
722
|
+
fs.copyFileSync(templatePath, ciPath);
|
|
723
|
+
console.log(chalk.green(`✔ GitLab CI template created at ${ciPath}`));
|
|
724
|
+
} else {
|
|
725
|
+
// Fallback: inline the template content
|
|
726
|
+
const ciContent = `# coderev — Multi-Agent AI Code Review for GitLab CI
|
|
727
|
+
# Quick start:
|
|
728
|
+
# 1. Set CI variable DEEPSEEK_API_KEY in GitLab → Settings → CI/CD → Variables
|
|
729
|
+
# 2. (Optional) Set GITLAB_TOKEN for auto-posting MR comments
|
|
730
|
+
|
|
731
|
+
stages:
|
|
732
|
+
- review
|
|
733
|
+
|
|
734
|
+
coderev-review:
|
|
735
|
+
stage: review
|
|
736
|
+
image: node:20-alpine
|
|
737
|
+
needs: []
|
|
738
|
+
rules:
|
|
739
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
|
740
|
+
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
741
|
+
when: never
|
|
742
|
+
before_script:
|
|
743
|
+
- npm install -g coderev-cli
|
|
744
|
+
- command -v git >/dev/null 2>&1 || apk add --no-cache git
|
|
745
|
+
script:
|
|
746
|
+
- |
|
|
747
|
+
if [ -n "$CI_MERGE_REQUEST_DIFF_BASE_SHA" ]; then
|
|
748
|
+
git diff $CI_MERGE_REQUEST_DIFF_BASE_SHA...$CI_COMMIT_SHA > /tmp/coderev-mr.diff
|
|
749
|
+
else
|
|
750
|
+
git diff HEAD~1 > /tmp/coderev-mr.diff
|
|
751
|
+
fi
|
|
752
|
+
- cat /tmp/coderev-mr.diff | coderev review --output markdown --ci --min-confidence 60 > /tmp/coderev-output.md
|
|
753
|
+
- cat /tmp/coderev-output.md
|
|
754
|
+
artifacts:
|
|
755
|
+
when: always
|
|
756
|
+
paths:
|
|
757
|
+
- /tmp/coderev-output.md
|
|
758
|
+
expire_in: 7 days
|
|
759
|
+
`;
|
|
760
|
+
fs.writeFileSync(ciPath, ciContent);
|
|
761
|
+
console.log(chalk.green(`✔ GitLab CI template created at ${ciPath}`));
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
console.log(chalk.blue(' Next steps:'));
|
|
765
|
+
console.log(chalk.blue(' 1. Go to GitLab → Settings → CI/CD → Variables'));
|
|
766
|
+
console.log(chalk.blue(' 2. Add variable DEEPSEEK_API_KEY with your API key'));
|
|
767
|
+
console.log(chalk.blue(' 3. (Optional) Add GITLAB_TOKEN with api scope for MR comments'));
|
|
768
|
+
console.log(chalk.blue(' 4. Push to GitLab — coderev runs on every MR!'));
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
// --github-action: generate GitHub Actions workflow
|
|
772
|
+
if (options.githubAction) {
|
|
773
|
+
const gaDir = path.join(process.cwd(), '.github', 'workflows');
|
|
774
|
+
const gaPath = path.join(gaDir, 'coderev.yml');
|
|
775
|
+
if (fs.existsSync(gaPath)) {
|
|
776
|
+
console.log(chalk.yellow(`⚠ ${gaPath} already exists. Skipping.`));
|
|
777
|
+
} else {
|
|
778
|
+
const templatePath = path.join(__dirname, '..', 'templates', 'github-action.yml');
|
|
779
|
+
if (fs.existsSync(templatePath)) {
|
|
780
|
+
fs.mkdirSync(gaDir, { recursive: true });
|
|
781
|
+
fs.copyFileSync(templatePath, gaPath);
|
|
782
|
+
console.log(chalk.green(`✔ GitHub Actions workflow created at ${gaPath}`));
|
|
783
|
+
} else {
|
|
784
|
+
// Fallback: write minimal workflow
|
|
785
|
+
const gaContent = `name: coderev AI Code Review
|
|
786
|
+
|
|
787
|
+
on:
|
|
788
|
+
pull_request:
|
|
789
|
+
types: [opened, synchronize, reopened]
|
|
790
|
+
|
|
791
|
+
permissions:
|
|
792
|
+
contents: read
|
|
793
|
+
pull-requests: write
|
|
794
|
+
|
|
795
|
+
jobs:
|
|
796
|
+
coderev:
|
|
797
|
+
runs-on: ubuntu-latest
|
|
798
|
+
timeout-minutes: 10
|
|
799
|
+
steps:
|
|
800
|
+
- uses: actions/checkout@v4
|
|
801
|
+
with:
|
|
802
|
+
fetch-depth: 0
|
|
803
|
+
- uses: actions/setup-node@v4
|
|
804
|
+
with:
|
|
805
|
+
node-version: 20
|
|
806
|
+
- run: npm install -g coderev-cli
|
|
807
|
+
- run: |
|
|
808
|
+
git diff \${{ github.event.pull_request.base.sha }}...\${{ github.event.pull_request.head.sha }} > /tmp/coderev-pr.diff
|
|
809
|
+
- env:
|
|
810
|
+
DEEPSEEK_API_KEY: \${{ secrets.DEEPSEEK_API_KEY }}
|
|
811
|
+
run: |
|
|
812
|
+
cat /tmp/coderev-pr.diff | coderev review --output markdown --ci --min-confidence 60 > /tmp/coderev-report.md
|
|
813
|
+
- uses: marocchino/sticky-pull-request-comment@v2
|
|
814
|
+
with:
|
|
815
|
+
header: coderev-review
|
|
816
|
+
path: /tmp/coderev-report.md
|
|
817
|
+
`;
|
|
818
|
+
fs.mkdirSync(gaDir, { recursive: true });
|
|
819
|
+
fs.writeFileSync(gaPath, gaContent);
|
|
820
|
+
console.log(chalk.green(`✔ GitHub Actions workflow created at ${gaPath}`));
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
console.log(chalk.blue(' Next steps:'));
|
|
824
|
+
console.log(chalk.blue(' 1. Go to GitHub → Settings → Secrets and variables → Actions'));
|
|
825
|
+
console.log(chalk.blue(' 2. Add secret DEEPSEEK_API_KEY with your API key'));
|
|
826
|
+
console.log(chalk.blue(' 3. Push to GitHub — coderev reviews every PR!'));
|
|
827
|
+
}
|
|
711
828
|
});
|
|
712
829
|
|
|
713
830
|
// ── Serve (GitHub App) ────────────────────────────────────────────
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# coderev — Multi-Agent AI Code Review for GitLab CI
|
|
3
|
+
# =============================================================================
|
|
4
|
+
#
|
|
5
|
+
# This template runs coderev on every merge request, using 3 parallel AI agents
|
|
6
|
+
# (Security / Bug / Quality) with confidence scoring.
|
|
7
|
+
#
|
|
8
|
+
# QUICK START:
|
|
9
|
+
# 1. Copy this file to your repo as .gitlab-ci.yml
|
|
10
|
+
# 2. Set CI variable DEEPSEEK_API_KEY in GitLab → Settings → CI/CD → Variables
|
|
11
|
+
# 3. (Optional) Set GITLAB_TOKEN for private repos or to post review comments
|
|
12
|
+
#
|
|
13
|
+
# VARIABLES (set in GitLab CI/CD Settings):
|
|
14
|
+
# DEEPSEEK_API_KEY (required) AI provider API key
|
|
15
|
+
# GITLAB_TOKEN (optional) GitLab PAT for posting MR comments (api scope)
|
|
16
|
+
# CODEREV_PROVIDER (optional) AI provider: deepseek | openai (default: deepseek)
|
|
17
|
+
# CODEREV_MODEL (optional) Model name (default: deepseek-chat)
|
|
18
|
+
# CODEREV_CONFIDENCE (optional) Min confidence 0-100 (default: 60)
|
|
19
|
+
# CODEREV_MODE (optional) Review mode: full | security | bugs | quality
|
|
20
|
+
# CODEREV_BLAME (optional) Enable git blame: "true" | "false" (default: false)
|
|
21
|
+
# CODEREV_BLOCK (optional) Block MR on issues: "true" | "false" (default: false)
|
|
22
|
+
# =============================================================================
|
|
23
|
+
|
|
24
|
+
stages:
|
|
25
|
+
- review
|
|
26
|
+
|
|
27
|
+
coderev-review:
|
|
28
|
+
stage: review
|
|
29
|
+
image: node:20-alpine
|
|
30
|
+
needs: []
|
|
31
|
+
rules:
|
|
32
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
|
33
|
+
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
34
|
+
when: never
|
|
35
|
+
before_script:
|
|
36
|
+
# Install coderev and dependencies
|
|
37
|
+
- npm install -g coderev-cli
|
|
38
|
+
# Ensure git is configured for diff generation
|
|
39
|
+
- command -v git >/dev/null 2>&1 || apk add --no-cache git
|
|
40
|
+
script:
|
|
41
|
+
# ── Generate MR diff ──
|
|
42
|
+
- |
|
|
43
|
+
echo "📋 Generating diff for merge request..."
|
|
44
|
+
if [ -n "$CI_MERGE_REQUEST_DIFF_BASE_SHA" ]; then
|
|
45
|
+
git diff $CI_MERGE_REQUEST_DIFF_BASE_SHA...$CI_COMMIT_SHA > /tmp/coderev-mr.diff
|
|
46
|
+
elif [ -n "$CI_MERGE_REQUEST_TARGET_BRANCH_SHA" ]; then
|
|
47
|
+
git diff $CI_MERGE_REQUEST_TARGET_BRANCH_SHA...$CI_COMMIT_SHA > /tmp/coderev-mr.diff
|
|
48
|
+
else
|
|
49
|
+
echo "⚠️ Could not determine MR base. Reviewing working tree..."
|
|
50
|
+
git diff HEAD~1 > /tmp/coderev-mr.diff
|
|
51
|
+
fi
|
|
52
|
+
echo "Debug: Diff saved ($(wc -c < /tmp/coderev-mr.diff) bytes)"
|
|
53
|
+
|
|
54
|
+
# ── Build CLI args ──
|
|
55
|
+
- |
|
|
56
|
+
CODEREV_ARGS=""
|
|
57
|
+
|
|
58
|
+
# Output format
|
|
59
|
+
CODEREV_ARGS="$CODEREV_ARGS --output markdown"
|
|
60
|
+
|
|
61
|
+
# Provider
|
|
62
|
+
PROVIDER="${CODEREV_PROVIDER:-deepseek}"
|
|
63
|
+
|
|
64
|
+
# Mode filter
|
|
65
|
+
case "${CODEREV_MODE:-full}" in
|
|
66
|
+
security) CODEREV_ARGS="$CODEREV_ARGS --audit" ;;
|
|
67
|
+
bugs) CODEREV_ARGS="$CODEREV_ARGS --agents bugs" ;;
|
|
68
|
+
quality) CODEREV_ARGS="$CODEREV_ARGS --agents quality" ;;
|
|
69
|
+
esac
|
|
70
|
+
|
|
71
|
+
# Confidence threshold
|
|
72
|
+
CONFIDENCE="${CODEREV_CONFIDENCE:-60}"
|
|
73
|
+
CODEREV_ARGS="$CODEREV_ARGS --min-confidence $CONFIDENCE"
|
|
74
|
+
|
|
75
|
+
# Git blame
|
|
76
|
+
if [ "${CODEREV_BLAME:-false}" = "true" ]; then
|
|
77
|
+
CODEREV_ARGS="$CODEREV_ARGS --blame"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# CI mode (block MR on issues)
|
|
81
|
+
if [ "${CODEREV_BLOCK:-false}" = "true" ]; then
|
|
82
|
+
CODEREV_ARGS="$CODEREV_ARGS --ci"
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
# ── Run coderev ──
|
|
86
|
+
- |
|
|
87
|
+
echo "🔍 Running coderev multi-agent review..."
|
|
88
|
+
export DEEPSEEK_API_KEY="${DEEPSEEK_API_KEY}"
|
|
89
|
+
export OPENAI_API_KEY="${OPENAI_API_KEY:-$DEEPSEEK_API_KEY}"
|
|
90
|
+
cat /tmp/coderev-mr.diff | coderev review $CODEREV_ARGS > /tmp/coderev-output.md 2>/tmp/coderev-stderr.txt
|
|
91
|
+
REVIEW_EXIT_CODE=$?
|
|
92
|
+
echo "Debug: review exit code = $REVIEW_EXIT_CODE"
|
|
93
|
+
|
|
94
|
+
# ── Post review as MR comment (if GITLAB_TOKEN is set) ──
|
|
95
|
+
- |
|
|
96
|
+
if [ -n "$GITLAB_TOKEN" ] && [ -n "$CI_MERGE_REQUEST_IID" ]; then
|
|
97
|
+
echo "💬 Posting review comment to MR !$CI_MERGE_REQUEST_IID ..."
|
|
98
|
+
|
|
99
|
+
# Read and escape the review output for JSON
|
|
100
|
+
REVIEW_BODY=$(cat /tmp/coderev-output.md | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))" 2>/dev/null || \
|
|
101
|
+
node -e "const fs=require('fs');console.log(JSON.stringify(fs.readFileSync('/tmp/coderev-output.md','utf8')))")
|
|
102
|
+
|
|
103
|
+
# Post via GitLab API
|
|
104
|
+
curl -s -X POST \
|
|
105
|
+
"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}/notes" \
|
|
106
|
+
--header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" \
|
|
107
|
+
--header "Content-Type: application/json" \
|
|
108
|
+
--data "{\"body\": $REVIEW_BODY}" \
|
|
109
|
+
> /tmp/coderev-post-response.json 2>/tmp/coderev-curl-stderr.txt
|
|
110
|
+
|
|
111
|
+
if [ $? -eq 0 ]; then
|
|
112
|
+
echo "✅ Review comment posted to MR !$CI_MERGE_REQUEST_IID"
|
|
113
|
+
else
|
|
114
|
+
echo "⚠️ Failed to post comment (check GITLAB_TOKEN scope: api)"
|
|
115
|
+
fi
|
|
116
|
+
else
|
|
117
|
+
echo "ℹ️ GITLAB_TOKEN not set — skipping MR comment. Review output:"
|
|
118
|
+
cat /tmp/coderev-output.md
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
# ── Exit with review status (CI mode) ──
|
|
122
|
+
- |
|
|
123
|
+
if [ "${CODEREV_BLOCK:-false}" = "true" ] && [ $REVIEW_EXIT_CODE -ne 0 ]; then
|
|
124
|
+
echo "🚫 Issues found! Blocking MR. Fix issues or lower CODEREV_CONFIDENCE."
|
|
125
|
+
exit 1
|
|
126
|
+
fi
|
|
127
|
+
echo "✅ coderev review complete."
|
|
128
|
+
|
|
129
|
+
artifacts:
|
|
130
|
+
when: always
|
|
131
|
+
paths:
|
|
132
|
+
- /tmp/coderev-output.md
|
|
133
|
+
- /tmp/coderev-stderr.txt
|
|
134
|
+
expire_in: 7 days
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# coderev — Multi-Agent AI Code Review for GitHub Actions
|
|
2
|
+
# Quick start:
|
|
3
|
+
# 1. Copy this file to .github/workflows/coderev.yml
|
|
4
|
+
# Or run: npx coderev-cli init --github-action
|
|
5
|
+
# 2. Set Secrets: DEEPSEEK_API_KEY in Settings → Secrets and variables → Actions
|
|
6
|
+
# 3. (Optional) Set GITHUB_TOKEN is auto-provided, no setup needed
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# - Review on every PR: default trigger
|
|
10
|
+
# - Block merging on issues: enable CODEREV_BLOCK or comment with coderev status
|
|
11
|
+
#
|
|
12
|
+
# Variables (set in workflow or as env):
|
|
13
|
+
# CODEREV_PROVIDER AI provider (default: deepseek)
|
|
14
|
+
# CODEREV_MODEL Model name (default: deepseek-chat)
|
|
15
|
+
# CODEREV_CONFIDENCE Minimum confidence 0-100 (default: 60)
|
|
16
|
+
# CODEREV_BLOCK Block PR on issues (default: false)
|
|
17
|
+
# CODEREV_BLAME Enable git blame context (default: false)
|
|
18
|
+
# CODEREV_MODE Review mode: comment | check (default: comment)
|
|
19
|
+
|
|
20
|
+
name: coderev AI Code Review
|
|
21
|
+
|
|
22
|
+
on:
|
|
23
|
+
pull_request:
|
|
24
|
+
types: [opened, synchronize, reopened]
|
|
25
|
+
workflow_dispatch:
|
|
26
|
+
inputs:
|
|
27
|
+
ref:
|
|
28
|
+
description: 'Git ref to review (branch/commit)'
|
|
29
|
+
required: false
|
|
30
|
+
|
|
31
|
+
permissions:
|
|
32
|
+
contents: read
|
|
33
|
+
pull-requests: write
|
|
34
|
+
checks: write
|
|
35
|
+
|
|
36
|
+
jobs:
|
|
37
|
+
coderev:
|
|
38
|
+
name: AI Code Review
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
timeout-minutes: 10
|
|
41
|
+
|
|
42
|
+
steps:
|
|
43
|
+
- name: Checkout
|
|
44
|
+
uses: actions/checkout@v4
|
|
45
|
+
with:
|
|
46
|
+
fetch-depth: 0
|
|
47
|
+
|
|
48
|
+
- name: Setup Node.js
|
|
49
|
+
uses: actions/setup-node@v4
|
|
50
|
+
with:
|
|
51
|
+
node-version: 20
|
|
52
|
+
|
|
53
|
+
- name: Install coderev
|
|
54
|
+
run: npm install -g coderev-cli
|
|
55
|
+
|
|
56
|
+
- name: Generate diff
|
|
57
|
+
id: diff
|
|
58
|
+
run: |
|
|
59
|
+
if [ -n "${{ github.event.pull_request.base.sha }}" ]; then
|
|
60
|
+
git diff ${{ github.event.pull_request.base.sha }}...${{ github.event.pull_request.head.sha }} > /tmp/coderev-pr.diff
|
|
61
|
+
else
|
|
62
|
+
git diff HEAD~1 > /tmp/coderev-pr.diff
|
|
63
|
+
fi
|
|
64
|
+
echo "Diff size: $(wc -c < /tmp/coderev-pr.diff) bytes"
|
|
65
|
+
|
|
66
|
+
- name: Run coderev review
|
|
67
|
+
id: review
|
|
68
|
+
env:
|
|
69
|
+
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
|
70
|
+
CODEREV_PROVIDER: ${{ env.CODEREV_PROVIDER || 'deepseek' }}
|
|
71
|
+
CODEREV_MODEL: ${{ env.CODEREV_MODEL || 'deepseek-chat' }}
|
|
72
|
+
run: |
|
|
73
|
+
BLAME_FLAG=""
|
|
74
|
+
if [ "${{ env.CODEREV_BLAME || 'false' }}" = "true" ]; then
|
|
75
|
+
BLAME_FLAG="--blame"
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
cat /tmp/coderev-pr.diff | coderev review \
|
|
79
|
+
--output markdown \
|
|
80
|
+
--ci $BLAME_FLAG \
|
|
81
|
+
--min-confidence ${{ env.CODEREV_CONFIDENCE || '60' }} \
|
|
82
|
+
> /tmp/coderev-report.md 2>/tmp/coderev-stderr.log
|
|
83
|
+
|
|
84
|
+
echo "Exit code: $?"
|
|
85
|
+
|
|
86
|
+
- name: Post review as PR comment
|
|
87
|
+
if: github.event_name == 'pull_request' && env.CODEREV_MODE != 'check'
|
|
88
|
+
uses: marocchino/sticky-pull-request-comment@v2
|
|
89
|
+
with:
|
|
90
|
+
header: coderev-review
|
|
91
|
+
path: /tmp/coderev-report.md
|
|
92
|
+
|
|
93
|
+
- name: Post review as GitHub Check
|
|
94
|
+
if: env.CODEREV_MODE == 'check'
|
|
95
|
+
uses: actions/github-script@v7
|
|
96
|
+
with:
|
|
97
|
+
script: |
|
|
98
|
+
const fs = require('fs');
|
|
99
|
+
const report = fs.readFileSync('/tmp/coderev-report.md', 'utf8');
|
|
100
|
+
|
|
101
|
+
// Parse score from report
|
|
102
|
+
const scoreMatch = report.match(/\*\*Score:\*\*\s*(\d+)\/100/);
|
|
103
|
+
const score = scoreMatch ? parseInt(scoreMatch[1]) : 0;
|
|
104
|
+
const conclusion = score >= 80 ? 'success' : score >= 50 ? 'neutral' : 'failure';
|
|
105
|
+
|
|
106
|
+
// Count issues
|
|
107
|
+
const issueMatches = report.match(/\*\*ERROR\*\*/g);
|
|
108
|
+
const warnMatches = report.match(/\*\*WARNING\*\*/g);
|
|
109
|
+
|
|
110
|
+
await github.rest.checks.create({
|
|
111
|
+
owner: context.repo.owner,
|
|
112
|
+
repo: context.repo.repo,
|
|
113
|
+
name: 'coderev AI Review',
|
|
114
|
+
head_sha: context.payload.pull_request?.head?.sha || context.sha,
|
|
115
|
+
status: 'completed',
|
|
116
|
+
conclusion: conclusion,
|
|
117
|
+
output: {
|
|
118
|
+
title: `Code Review: ${score}/100`,
|
|
119
|
+
summary: report.substring(0, 65535),
|
|
120
|
+
annotations: []
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
- name: Block on issues (optional)
|
|
125
|
+
if: env.CODEREV_BLOCK == 'true'
|
|
126
|
+
run: |
|
|
127
|
+
SCORE=$(grep -oP '\*\*Score:\*\*\s*\K\d+' /tmp/coderev-report.md || echo 0)
|
|
128
|
+
if [ "$SCORE" -lt 60 ]; then
|
|
129
|
+
echo "⛔ Score $SCORE/100 below threshold (60). Blocking PR."
|
|
130
|
+
cat /tmp/coderev-report.md
|
|
131
|
+
exit 1
|
|
132
|
+
fi
|
|
133
|
+
echo "✅ Score $SCORE/100 — passed."
|
|
134
|
+
|
|
135
|
+
- name: Upload review artifacts
|
|
136
|
+
if: always()
|
|
137
|
+
uses: actions/upload-artifact@v4
|
|
138
|
+
with:
|
|
139
|
+
name: coderev-report
|
|
140
|
+
path: |
|
|
141
|
+
/tmp/coderev-report.md
|
|
142
|
+
/tmp/coderev-stderr.log
|
|
143
|
+
retention-days: 7
|