job51-gitlab-cr-node-skill-prompt-optimize 1.0.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.md +58 -0
- package/analyze_filepath.js +66 -0
- package/analyze_issue.js +68 -0
- package/debug_test.js +89 -0
- package/env_check.js +32 -0
- package/example.js +29 -0
- package/index.js +532 -0
- package/log.txt +519 -0
- package/mr-review-template.md +65 -0
- package/package.json +23 -0
- package/simulate_ci.js +57 -0
- package/simulate_no_claude.js +61 -0
- package/temp-diff-block-1772527822359-0.diff +10 -0
- package/temp-diff-block-1772527823803-2.diff +9 -0
- package/temp-diff-block-1772527949844-0.diff +10 -0
- package/temp-diff-block-1772527949860-2.diff +9 -0
- package/temp-diff-block-1772528045156-0.diff +10 -0
- package/temp-diff-block-1772528045169-1.diff +8 -0
- package/temp-diff-block-1772528045180-2.diff +9 -0
- package/temp-diff-block-1772528185915-0.diff +10 -0
- package/temp-diff-block-1772528185952-2.diff +9 -0
- package/test_claude_file_access.js +125 -0
- package/test_filepath.js +98 -0
- package/test_no_nested_session.js +117 -0
- package/test_path_recognition.js +119 -0
- package/utils.js +67 -0
package/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# GitLab Code Review AI Tool
|
|
2
|
+
|
|
3
|
+
一个使用 AI 自动审查 GitLab 合并请求的工具,基于 Claude AI 进行代码分析。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
通过 npm 全局安装:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g gitlab-cr-node
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 使用方法
|
|
14
|
+
|
|
15
|
+
### 1. 环境变量配置
|
|
16
|
+
|
|
17
|
+
在使用前需要设置以下环境变量:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
export CI_API_V4_URL="https://your-gitlab-instance.com/api/v4"
|
|
21
|
+
export GITLAB_ACCESS_TOKEN="your_gitlab_access_token"
|
|
22
|
+
export CI_PROJECT_ID="your_project_id"
|
|
23
|
+
export CI_MERGE_REQUEST_IID="your_merge_request_iid"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
或者在 Windows PowerShell 中:
|
|
27
|
+
|
|
28
|
+
```powershell
|
|
29
|
+
$env:CI_API_V4_URL="https://your-gitlab-instance.com/api/v4"
|
|
30
|
+
$env:GITLAB_ACCESS_TOKEN="your_gitlab_access_token"
|
|
31
|
+
$env:CI_PROJECT_ID="your_project_id"
|
|
32
|
+
$env:CI_MERGE_REQUEST_IID="your_merge_request_iid"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 2. 运行代码审查
|
|
36
|
+
|
|
37
|
+
设置好环境变量后,运行:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
gitlab-cr
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 功能特性
|
|
44
|
+
|
|
45
|
+
- 自动获取 GitLab 合并请求的代码变更
|
|
46
|
+
- 使用 Claude AI 进行代码审查
|
|
47
|
+
- 生成结构化的审查报告
|
|
48
|
+
- 将审查结果发布到 GitLab MR
|
|
49
|
+
|
|
50
|
+
## 依赖要求
|
|
51
|
+
|
|
52
|
+
- Node.js 10+
|
|
53
|
+
- Claude CLI 工具
|
|
54
|
+
- GitLab 访问令牌
|
|
55
|
+
|
|
56
|
+
## 许可证
|
|
57
|
+
|
|
58
|
+
MIT
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// 详细分析Claude命令的文件路径问题
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
console.log('=== 分析Claude命令文件路径问题 ===\n');
|
|
6
|
+
|
|
7
|
+
// 1. 查看当前工作目录
|
|
8
|
+
console.log(`当前工作目录: ${process.cwd()}`);
|
|
9
|
+
|
|
10
|
+
// 2. 分析临时文件路径创建逻辑
|
|
11
|
+
const timestamp = Date.now();
|
|
12
|
+
const blockIndex = 0;
|
|
13
|
+
const relativeTmpPath = `./temp-diff-block-${timestamp}-${blockIndex}.diff`;
|
|
14
|
+
const absoluteTmpPath = path.resolve(relativeTmpPath);
|
|
15
|
+
|
|
16
|
+
console.log(`相对路径: ${relativeTmpPath}`);
|
|
17
|
+
console.log(`绝对路径: ${absoluteTmpPath}`);
|
|
18
|
+
|
|
19
|
+
// 3. 检查index.js中的实际实现逻辑
|
|
20
|
+
console.log('\n=== index.js中实际的文件路径逻辑 ===');
|
|
21
|
+
|
|
22
|
+
console.log('在index.js的第120行:');
|
|
23
|
+
console.log(' const tmpFileName = `./temp-diff-block-${Date.now()}-${blockIndex}.diff`;');
|
|
24
|
+
|
|
25
|
+
console.log('在index.js的第124行:');
|
|
26
|
+
console.log(' fs.writeFileSync(tmpFileName, diffObject.diff);');
|
|
27
|
+
|
|
28
|
+
console.log('在index.js的第127行:');
|
|
29
|
+
console.log(' const review_result = await this.reviewDiffWithClaudeUsingFile(tmpFileName);');
|
|
30
|
+
|
|
31
|
+
console.log('在index.js的第198行:');
|
|
32
|
+
console.log(' const prompt = \'/simple-code-review\' + \' \' + filePath;');
|
|
33
|
+
|
|
34
|
+
console.log('这形成了如下操作:');
|
|
35
|
+
console.log(` 1. 创建文件: ${relativeTmpPath}`);
|
|
36
|
+
console.log(` 2. 调用: claude -p "/simple-code-review ${relativeTmpPath}"`);
|
|
37
|
+
|
|
38
|
+
console.log('\n=== 关键问题 ===');
|
|
39
|
+
console.log('1. 临时文件是在当前工作目录创建的');
|
|
40
|
+
console.log('2. 使用相对路径传递给Claude命令');
|
|
41
|
+
console.log('3. Claude命令是否能在其执行环境中找到这个相对路径的文件?');
|
|
42
|
+
|
|
43
|
+
// 检查Claude在调用时的工作目录是否与临时文件创建目录一致
|
|
44
|
+
console.log('\n=== 可能的解决方案 ===');
|
|
45
|
+
console.log('1. 使用绝对路径而不是相对路径传递给Claude命令');
|
|
46
|
+
console.log('2. 确保Claude命令在相同的工作目录中执行');
|
|
47
|
+
console.log('3. 或者修改Claude技能以接受文件内容而不是文件路径');
|
|
48
|
+
|
|
49
|
+
console.log('\n在第525行的runClaudeCommand函数中:');
|
|
50
|
+
console.log(' cwd: __dirname, // 设置工作目录为当前脚本所在目录');
|
|
51
|
+
console.log('这应该确保Claude命令在正确的目录中执行,但可能在CI环境中仍有问题');
|
|
52
|
+
|
|
53
|
+
// 模拟index.js中确切的代码流程
|
|
54
|
+
console.log('\n=== 模拟精确的执行流程 ===');
|
|
55
|
+
console.log('1. 创建临时文件 (使用相对路径):');
|
|
56
|
+
console.log(' fs.writeFileSync("./temp-diff-block-xxx.diff", diff_content)');
|
|
57
|
+
|
|
58
|
+
console.log('2. 生成prompt:');
|
|
59
|
+
console.log(' prompt = "/simple-code-review ./temp-diff-block-xxx.diff"');
|
|
60
|
+
|
|
61
|
+
console.log('3. 调用Claude命令:');
|
|
62
|
+
console.log(' claude -p "/simple-code-review ./temp-diff-block-xxx.diff"');
|
|
63
|
+
|
|
64
|
+
console.log('4. Claude的/simple-code-review技能可能需要读取该文件');
|
|
65
|
+
|
|
66
|
+
console.log('\n问题: 如果Claude在其自己的工作目录中运行,可能找不到这个相对路径的文件。');
|
package/analyze_issue.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// 专门测试在GitLab CI中可能遇到的问题
|
|
2
|
+
const { spawn, exec } = require('child_process');
|
|
3
|
+
|
|
4
|
+
console.log('=== 分析GitLab CI中可能遇到的问题 ===');
|
|
5
|
+
|
|
6
|
+
// 首先,测试在移除CLAUDECODE变量后直接执行claude命令
|
|
7
|
+
console.log('1. 检查系统中是否安装了claude命令(移除CLAUDECODE环境变量后)...');
|
|
8
|
+
|
|
9
|
+
const envWithoutClaudeCode = { ...process.env };
|
|
10
|
+
delete envWithoutClaudeCode.CLAUDECODE;
|
|
11
|
+
delete envWithoutClaudeCode.CLAUDE_CODE_ENTRYPOINT;
|
|
12
|
+
|
|
13
|
+
// 使用exec同步检查命令是否存在
|
|
14
|
+
exec('which claude', { env: envWithoutClaudeCode }, (error, stdout, stderr) => {
|
|
15
|
+
if (error) {
|
|
16
|
+
console.log(' -> Claude命令未找到或不可执行 (exit code: ' + error.code + ')');
|
|
17
|
+
console.log(' -> 这很可能是GitLab CI环境中的问题根源');
|
|
18
|
+
|
|
19
|
+
// 测试在GitLab CI中常见的情况:缺少claude CLI
|
|
20
|
+
console.log('\n2. 这就是GitLab CI环境中的典型问题:');
|
|
21
|
+
console.log(' - 没有安装Claude CLI');
|
|
22
|
+
console.log(' - Claude CLI无法访问或执行');
|
|
23
|
+
console.log(' - 权限不足');
|
|
24
|
+
console.log(' - PATH环境变量不同');
|
|
25
|
+
|
|
26
|
+
console.log('\n3. 因此,runClaudeCommand函数在GitLab CI中会:');
|
|
27
|
+
console.log(' - spawn执行claude命令失败');
|
|
28
|
+
console.log(' - 触发error事件');
|
|
29
|
+
console.log(' - 如果错误处理不当,可能返回空字符串');
|
|
30
|
+
console.log(' - 导致claudeResult为空');
|
|
31
|
+
|
|
32
|
+
console.log('\n4. 解决方案可能包括:');
|
|
33
|
+
console.log(' - 在GitLab CI中安装Claude CLI');
|
|
34
|
+
console.log(' - 修改脚本使用其他方式调用Claude(如API调用)');
|
|
35
|
+
console.log(' - 添加适当的错误处理和回退机制');
|
|
36
|
+
} else {
|
|
37
|
+
console.log(' -> Claude命令存在: ' + stdout.trim());
|
|
38
|
+
|
|
39
|
+
// 如果claude命令存在,测试执行它
|
|
40
|
+
console.log('\n5. Claude命令存在,尝试执行简单的Claude命令...');
|
|
41
|
+
const claudeTest = spawn('claude', ['-p', 'hello'], {
|
|
42
|
+
env: envWithoutClaudeCode,
|
|
43
|
+
shell: true
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
let testOutput = '';
|
|
47
|
+
let testError = '';
|
|
48
|
+
|
|
49
|
+
claudeTest.stdout.on('data', (data) => {
|
|
50
|
+
testOutput += data.toString();
|
|
51
|
+
console.log(' -> Claude输出: ' + data.toString().substring(0, 100) + '...');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
claudeTest.stderr.on('data', (data) => {
|
|
55
|
+
testError += data.toString();
|
|
56
|
+
console.log(' -> Claude错误: ' + data.toString());
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
claudeTest.on('close', (code) => {
|
|
60
|
+
console.log(' -> Claude命令结束,退出码: ' + code);
|
|
61
|
+
if (code === 0) {
|
|
62
|
+
console.log(' -> Claude命令执行成功');
|
|
63
|
+
} else {
|
|
64
|
+
console.log(' -> Claude命令执行失败,这可能是另一个问题原因');
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
});
|
package/debug_test.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
const { spawn } = require('child_process');
|
|
2
|
+
|
|
3
|
+
// 测试在不同环境下 claude 命令的行为
|
|
4
|
+
function testClaudeCommand() {
|
|
5
|
+
console.log('开始测试Claude命令...');
|
|
6
|
+
|
|
7
|
+
// 测试1: 直接执行 claude 命令
|
|
8
|
+
console.log('\n--- 测试1: 检查claude命令 ---');
|
|
9
|
+
const checkCmd = spawn('which', ['claude'], {
|
|
10
|
+
shell: true,
|
|
11
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
let checkStdout = '';
|
|
15
|
+
let checkStderr = '';
|
|
16
|
+
|
|
17
|
+
checkCmd.stdout.on('data', (data) => {
|
|
18
|
+
checkStdout += data.toString();
|
|
19
|
+
console.log('which claude stdout:', data.toString());
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
checkCmd.stderr.on('data', (data) => {
|
|
23
|
+
checkStderr += data.toString();
|
|
24
|
+
console.log('which claude stderr:', data.toString());
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
checkCmd.on('close', (code) => {
|
|
28
|
+
console.log('which claude exit code:', code);
|
|
29
|
+
console.log('which claude result:', checkStdout.trim() || 'Command not found');
|
|
30
|
+
|
|
31
|
+
// 测试2: 执行 claude --version
|
|
32
|
+
console.log('\n--- 测试2: 执行claude --version ---');
|
|
33
|
+
const versionCmd = spawn('claude', ['--version'], {
|
|
34
|
+
shell: true,
|
|
35
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
let versionStdout = '';
|
|
39
|
+
let versionStderr = '';
|
|
40
|
+
|
|
41
|
+
versionCmd.stdout.on('data', (data) => {
|
|
42
|
+
versionStdout += data.toString();
|
|
43
|
+
console.log('claude --version stdout:', data.toString());
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
versionCmd.stderr.on('data', (data) => {
|
|
47
|
+
versionStderr += data.toString();
|
|
48
|
+
console.log('claude --version stderr:', data.toString());
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
versionCmd.on('close', (code) => {
|
|
52
|
+
console.log('claude --version exit code:', code);
|
|
53
|
+
|
|
54
|
+
// 测试3: 执行 claude 命令带简单提示
|
|
55
|
+
console.log('\n--- 测试3: 执行claude命令带简单提示 ---');
|
|
56
|
+
const claudeCmd = spawn('claude', ['-p', 'hello world'], {
|
|
57
|
+
shell: true,
|
|
58
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
let claudeStdout = '';
|
|
62
|
+
let claudeStderr = '';
|
|
63
|
+
|
|
64
|
+
claudeCmd.stdout.on('data', (data) => {
|
|
65
|
+
claudeStdout += data.toString();
|
|
66
|
+
console.log('claude [-p hello world] stdout chunk:', data.toString().substring(0, 100) + '...');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
claudeCmd.stderr.on('data', (data) => {
|
|
70
|
+
claudeStderr += data.toString();
|
|
71
|
+
console.log('claude [-p hello world] stderr:', data.toString());
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
claudeCmd.on('close', (code) => {
|
|
75
|
+
console.log('claude command exit code:', code);
|
|
76
|
+
console.log('claude command final stdout:', claudeStdout ? claudeStdout.substring(0, 200) + '...' : '(empty)');
|
|
77
|
+
console.log('claude command final stderr:', claudeStderr || '(empty)');
|
|
78
|
+
|
|
79
|
+
console.log('\n--- 环境信息 ---');
|
|
80
|
+
console.log('NODE_ENV:', process.env.NODE_ENV);
|
|
81
|
+
console.log('SHELL:', process.env.SHELL);
|
|
82
|
+
console.log('PROCESSOR_ARCHITECTURE:', process.env.PROCESSOR_ARCHITECTURE);
|
|
83
|
+
console.log('OSTYPE:', process.env.OSTYPE || 'Not set');
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
testClaudeCommand();
|
package/env_check.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// 检查当前运行环境
|
|
2
|
+
console.log('=== 环境检测 ===');
|
|
3
|
+
console.log('CLAUDECODE 环境变量:', process.env.CLAUDECODE);
|
|
4
|
+
console.log('是否在 Claude Code 环境中:', !!process.env.CLAUDECODE);
|
|
5
|
+
|
|
6
|
+
// 检查其他可能的环境变量
|
|
7
|
+
console.log('TERM:', process.env.TERM);
|
|
8
|
+
console.log('COLORTERM:', process.env.COLORTERM);
|
|
9
|
+
console.log('TERM_PROGRAM:', process.env.TERM_PROGRAM);
|
|
10
|
+
|
|
11
|
+
// 检查是否有其他指示运行环境的变量
|
|
12
|
+
console.log('CI:', process.env.CI);
|
|
13
|
+
console.log('GITLAB_CI:', process.env.GITLAB_CI);
|
|
14
|
+
|
|
15
|
+
// 尝试执行一些基本的系统命令
|
|
16
|
+
const { spawn } = require('child_process');
|
|
17
|
+
|
|
18
|
+
console.log('\n=== 尝试运行简单命令 ===');
|
|
19
|
+
|
|
20
|
+
// 测试环境变量
|
|
21
|
+
const envTest = spawn('env');
|
|
22
|
+
|
|
23
|
+
let envOutput = '';
|
|
24
|
+
envTest.stdout.on('data', (data) => {
|
|
25
|
+
envOutput += data.toString();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
envTest.on('close', () => {
|
|
29
|
+
console.log('所有环境变量:');
|
|
30
|
+
const claudeVars = envOutput.split('\n').filter(line => line.includes('CLAUDE') || line.includes('CODE'));
|
|
31
|
+
console.log('包含CLAUDE/CODE的环境变量:', claudeVars);
|
|
32
|
+
});
|
package/example.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// 示例文件,展示如何使用 GitLabCodeReviewer 类
|
|
2
|
+
const GitLabCodeReviewer = require('./index.js');
|
|
3
|
+
|
|
4
|
+
// 从环境变量获取配置
|
|
5
|
+
const gitlabUrl = process.env.CI_API_V4_URL;
|
|
6
|
+
const gitlabToken = process.env.GITLAB_ACCESS_TOKEN;
|
|
7
|
+
const projectId = process.env.CI_PROJECT_ID;
|
|
8
|
+
const mergeRequestIid = process.env.CI_MERGE_REQUEST_IID;
|
|
9
|
+
|
|
10
|
+
if (!gitlabToken || !projectId || !mergeRequestIid) {
|
|
11
|
+
console.error('缺少必要的环境变量配置');
|
|
12
|
+
console.error('请设置: CI_API_V4_URL, GITLAB_ACCESS_TOKEN, CI_PROJECT_ID, CI_MERGE_REQUEST_IID');
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const reviewer = new GitLabCodeReviewer(gitlabToken, gitlabUrl);
|
|
17
|
+
|
|
18
|
+
async function runExample() {
|
|
19
|
+
try {
|
|
20
|
+
console.log('开始审查合并请求...');
|
|
21
|
+
const results = await reviewer.reviewMergeRequest(projectId, mergeRequestIid);
|
|
22
|
+
console.log('审查完成,结果已发布到 GitLab MR');
|
|
23
|
+
} catch (error) {
|
|
24
|
+
console.error('审查过程出错:', error);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
runExample();
|