gitlab-ai-review 1.0.0 → 1.0.3
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 +160 -5
- package/index.js +109 -3
- package/lib/config.js +150 -0
- package/lib/gitlab-client.js +87 -0
- package/package.json +10 -4
- package/test-info.js +91 -0
package/README.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# GitLab AI Review SDK
|
|
2
2
|
|
|
3
|
-
GitLab AI Review SDK -
|
|
3
|
+
GitLab AI Review SDK - 支持 CI/CD 自动配置和手动配置
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- ✅ 封装 GitLab API 客户端
|
|
8
|
+
- ✅ CI/CD 环境自动检测配置
|
|
9
|
+
- ✅ 支持手动传递配置
|
|
10
|
+
- ✅ 获取项目和 MR 信息
|
|
11
|
+
- ✅ 添加 MR 评论
|
|
4
12
|
|
|
5
13
|
## 安装
|
|
6
14
|
|
|
@@ -8,16 +16,163 @@ GitLab AI Review SDK - 测试版本
|
|
|
8
16
|
npm install gitlab-ai-review
|
|
9
17
|
```
|
|
10
18
|
|
|
11
|
-
##
|
|
19
|
+
## 使用方式
|
|
20
|
+
|
|
21
|
+
### 方式 1:CI/CD 自动配置(推荐)
|
|
22
|
+
|
|
23
|
+
在 GitLab CI/CD 环境中,SDK 会自动检测环境变量:
|
|
12
24
|
|
|
13
25
|
```javascript
|
|
14
26
|
import GitLabAIReview from 'gitlab-ai-review';
|
|
15
27
|
|
|
28
|
+
// 自动从环境变量读取配置
|
|
16
29
|
const sdk = new GitLabAIReview();
|
|
17
|
-
|
|
30
|
+
|
|
31
|
+
// 获取 MR 信息
|
|
32
|
+
const mr = await sdk.getMergeRequest();
|
|
33
|
+
console.log('MR 标题:', mr.title);
|
|
34
|
+
|
|
35
|
+
// 添加评论
|
|
36
|
+
await sdk.addComment('✅ AI 代码审查完成!');
|
|
18
37
|
```
|
|
19
38
|
|
|
20
|
-
|
|
39
|
+
**自动检测的环境变量:**
|
|
40
|
+
- `CI_JOB_TOKEN` 或 `GITLAB_TOKEN` - GitLab Token
|
|
41
|
+
- `CI_SERVER_URL` 或 `GITLAB_URL` - GitLab 地址
|
|
42
|
+
- `CI_PROJECT_PATH` 或 `PROJECT_ID` - 项目 ID
|
|
43
|
+
- `CI_MERGE_REQUEST_IID` 或 `MERGE_REQUEST_IID` - MR 编号
|
|
44
|
+
|
|
45
|
+
### 方式 2:手动传递配置
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
import GitLabAIReview from 'gitlab-ai-review';
|
|
49
|
+
|
|
50
|
+
// 手动传递配置
|
|
51
|
+
const sdk = new GitLabAIReview({
|
|
52
|
+
token: 'your-gitlab-token',
|
|
53
|
+
url: 'https://gitlab.com',
|
|
54
|
+
projectId: 'group/project',
|
|
55
|
+
mergeRequestIid: 123,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// 获取项目信息
|
|
59
|
+
const project = await sdk.getProject();
|
|
60
|
+
console.log('项目名:', project.name);
|
|
61
|
+
|
|
62
|
+
// 获取 MR 信息
|
|
63
|
+
const mr = await sdk.getMergeRequest();
|
|
64
|
+
console.log('MR 标题:', mr.title);
|
|
65
|
+
|
|
66
|
+
// 添加评论
|
|
67
|
+
await sdk.addComment('✅ 代码审查通过!');
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## API 文档
|
|
71
|
+
|
|
72
|
+
### 构造函数
|
|
73
|
+
|
|
74
|
+
```javascript
|
|
75
|
+
new GitLabAIReview(options)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**参数:**
|
|
79
|
+
- `options.token` - GitLab Token(可选,CI/CD 中自动获取)
|
|
80
|
+
- `options.url` - GitLab 地址(可选,默认 `https://gitlab.com`)
|
|
81
|
+
- `options.projectId` - 项目 ID(可选,CI/CD 中自动获取)
|
|
82
|
+
- `options.mergeRequestIid` - MR 编号(可选,CI/CD 中自动获取)
|
|
83
|
+
|
|
84
|
+
### 方法
|
|
85
|
+
|
|
86
|
+
#### `validate()`
|
|
87
|
+
验证配置是否完整
|
|
88
|
+
|
|
89
|
+
```javascript
|
|
90
|
+
sdk.validate(); // 返回 true 或抛出错误
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### `getConfig()`
|
|
94
|
+
获取当前配置
|
|
95
|
+
|
|
96
|
+
```javascript
|
|
97
|
+
const config = sdk.getConfig();
|
|
98
|
+
console.log(config.gitlab.url);
|
|
99
|
+
console.log(config.project.projectId);
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
#### `getProject()`
|
|
103
|
+
获取项目信息
|
|
21
104
|
|
|
22
|
-
|
|
105
|
+
```javascript
|
|
106
|
+
const project = await sdk.getProject();
|
|
107
|
+
console.log(project.name);
|
|
108
|
+
console.log(project.description);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### `getMergeRequest()`
|
|
112
|
+
获取 MR 信息
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
const mr = await sdk.getMergeRequest();
|
|
116
|
+
console.log(mr.title);
|
|
117
|
+
console.log(mr.author.name);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### `getMergeRequestChanges()`
|
|
121
|
+
获取 MR 的代码变更
|
|
122
|
+
|
|
123
|
+
```javascript
|
|
124
|
+
const changes = await sdk.getMergeRequestChanges();
|
|
125
|
+
changes.forEach(change => {
|
|
126
|
+
console.log('文件:', change.new_path);
|
|
127
|
+
console.log('Diff:', change.diff);
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
#### `addComment(body)`
|
|
132
|
+
在 MR 上添加评论
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
await sdk.addComment('✅ 代码审查通过!');
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## 在 GitLab CI/CD 中使用
|
|
139
|
+
|
|
140
|
+
`.gitlab-ci.yml` 示例:
|
|
141
|
+
|
|
142
|
+
```yaml
|
|
143
|
+
stages:
|
|
144
|
+
- review
|
|
145
|
+
|
|
146
|
+
ai-review:
|
|
147
|
+
stage: review
|
|
148
|
+
image: node:18
|
|
149
|
+
only:
|
|
150
|
+
- merge_requests
|
|
151
|
+
script:
|
|
152
|
+
- npm install gitlab-ai-review
|
|
153
|
+
- node review.js
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
`review.js` 示例:
|
|
157
|
+
|
|
158
|
+
```javascript
|
|
159
|
+
import GitLabAIReview from 'gitlab-ai-review';
|
|
160
|
+
|
|
161
|
+
const sdk = new GitLabAIReview();
|
|
162
|
+
|
|
163
|
+
// 获取 MR 信息
|
|
164
|
+
const mr = await sdk.getMergeRequest();
|
|
165
|
+
console.log('正在审查 MR:', mr.title);
|
|
166
|
+
|
|
167
|
+
// 获取代码变更
|
|
168
|
+
const changes = await sdk.getMergeRequestChanges();
|
|
169
|
+
console.log(`共有 ${changes.length} 个文件变更`);
|
|
170
|
+
|
|
171
|
+
// 添加评论
|
|
172
|
+
await sdk.addComment('🤖 AI 代码审查已完成!');
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## 版本
|
|
23
176
|
|
|
177
|
+
- 1.0.1 - 添加 GitLab 客户端封装和自动配置
|
|
178
|
+
- 1.0.0 - 初始测试版本
|
package/index.js
CHANGED
|
@@ -1,12 +1,115 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* GitLab AI Review SDK
|
|
3
|
-
*
|
|
3
|
+
* 支持 CI/CD 自动配置和手动配置
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { getConfig, validateConfig } from './lib/config.js';
|
|
7
|
+
import { GitLabClient } from './lib/gitlab-client.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* GitLab AI Review SDK 主类
|
|
11
|
+
*/
|
|
6
12
|
export class GitLabAIReview {
|
|
7
|
-
constructor() {
|
|
13
|
+
constructor(options = {}) {
|
|
8
14
|
this.name = 'GitLab AI Review SDK';
|
|
9
15
|
this.version = '1.0.0';
|
|
16
|
+
|
|
17
|
+
// 如果传入了配置,使用手动配置;否则使用自动检测
|
|
18
|
+
if (options.token || options.gitlab) {
|
|
19
|
+
// 手动配置模式
|
|
20
|
+
this.config = {
|
|
21
|
+
gitlab: {
|
|
22
|
+
token: options.token || options.gitlab?.token,
|
|
23
|
+
url: options.url || options.gitlab?.url || 'https://gitlab.com',
|
|
24
|
+
},
|
|
25
|
+
project: {
|
|
26
|
+
projectId: options.projectId || options.project?.projectId,
|
|
27
|
+
mergeRequestIid: options.mergeRequestIid || options.project?.mergeRequestIid,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
} else {
|
|
31
|
+
// 自动检测模式(CI/CD)
|
|
32
|
+
this.config = getConfig();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// 创建 GitLab 客户端
|
|
36
|
+
this.gitlabClient = new GitLabClient({
|
|
37
|
+
token: this.config.gitlab.token,
|
|
38
|
+
host: this.config.gitlab.url,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 验证配置
|
|
44
|
+
*/
|
|
45
|
+
validate() {
|
|
46
|
+
return validateConfig(this.config);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 获取当前配置
|
|
51
|
+
*/
|
|
52
|
+
getConfig() {
|
|
53
|
+
return this.config;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 获取项目信息
|
|
58
|
+
*/
|
|
59
|
+
async getProject() {
|
|
60
|
+
if (!this.config.project.projectId) {
|
|
61
|
+
throw new Error('未配置项目 ID');
|
|
62
|
+
}
|
|
63
|
+
return this.gitlabClient.getProject(this.config.project.projectId);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* 获取 MR 信息
|
|
68
|
+
*/
|
|
69
|
+
async getMergeRequest() {
|
|
70
|
+
if (!this.config.project.projectId) {
|
|
71
|
+
throw new Error('未配置项目 ID');
|
|
72
|
+
}
|
|
73
|
+
if (!this.config.project.mergeRequestIid) {
|
|
74
|
+
throw new Error('未配置 MR IID');
|
|
75
|
+
}
|
|
76
|
+
return this.gitlabClient.getMergeRequest(
|
|
77
|
+
this.config.project.projectId,
|
|
78
|
+
this.config.project.mergeRequestIid
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 获取 MR 的代码变更
|
|
84
|
+
*/
|
|
85
|
+
async getMergeRequestChanges() {
|
|
86
|
+
if (!this.config.project.projectId) {
|
|
87
|
+
throw new Error('未配置项目 ID');
|
|
88
|
+
}
|
|
89
|
+
if (!this.config.project.mergeRequestIid) {
|
|
90
|
+
throw new Error('未配置 MR IID');
|
|
91
|
+
}
|
|
92
|
+
return this.gitlabClient.getMergeRequestChanges(
|
|
93
|
+
this.config.project.projectId,
|
|
94
|
+
this.config.project.mergeRequestIid
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 在 MR 上添加评论
|
|
100
|
+
*/
|
|
101
|
+
async addComment(body) {
|
|
102
|
+
if (!this.config.project.projectId) {
|
|
103
|
+
throw new Error('未配置项目 ID');
|
|
104
|
+
}
|
|
105
|
+
if (!this.config.project.mergeRequestIid) {
|
|
106
|
+
throw new Error('未配置 MR IID');
|
|
107
|
+
}
|
|
108
|
+
return this.gitlabClient.createMergeRequestNote(
|
|
109
|
+
this.config.project.projectId,
|
|
110
|
+
this.config.project.mergeRequestIid,
|
|
111
|
+
body
|
|
112
|
+
);
|
|
10
113
|
}
|
|
11
114
|
|
|
12
115
|
/**
|
|
@@ -17,6 +120,9 @@ export class GitLabAIReview {
|
|
|
17
120
|
}
|
|
18
121
|
}
|
|
19
122
|
|
|
123
|
+
// 导出工具函数
|
|
124
|
+
export { getConfig, validateConfig } from './lib/config.js';
|
|
125
|
+
export { GitLabClient } from './lib/gitlab-client.js';
|
|
126
|
+
|
|
20
127
|
// 默认导出
|
|
21
128
|
export default GitLabAIReview;
|
|
22
|
-
|
package/lib/config.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 配置模块 - 自动检测 CI/CD 环境变量
|
|
3
|
+
* 参考 review-bot/config.js 的实现
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import fs from 'fs';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 读取项目根目录下的 AI Review Guard 配置文件
|
|
11
|
+
*/
|
|
12
|
+
function readAIReviewGuardConfig() {
|
|
13
|
+
const configFiles = ['.aireviewguard', 'aireviewguard', '.aireviewguard.json', 'reviewguard.md', '.reviewguard.md'];
|
|
14
|
+
|
|
15
|
+
for (const filename of configFiles) {
|
|
16
|
+
try {
|
|
17
|
+
const configPath = path.join(process.cwd(), filename);
|
|
18
|
+
if (fs.existsSync(configPath)) {
|
|
19
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
20
|
+
|
|
21
|
+
// 如果是 Markdown 文件,返回原始内容
|
|
22
|
+
if (filename.endsWith('.md')) {
|
|
23
|
+
return {
|
|
24
|
+
type: 'markdown',
|
|
25
|
+
filename,
|
|
26
|
+
content,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 尝试解析 JSON,如果失败则返回纯文本
|
|
31
|
+
try {
|
|
32
|
+
return {
|
|
33
|
+
type: 'json',
|
|
34
|
+
filename,
|
|
35
|
+
...JSON.parse(content),
|
|
36
|
+
};
|
|
37
|
+
} catch {
|
|
38
|
+
return {
|
|
39
|
+
type: 'text',
|
|
40
|
+
filename,
|
|
41
|
+
content,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
} catch (error) {
|
|
46
|
+
// 忽略读取错误,继续尝试下一个文件
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 获取 GitLab 配置(支持自动检测 CI 环境)
|
|
55
|
+
*/
|
|
56
|
+
export function getGitLabConfig() {
|
|
57
|
+
// Token 优先级:GITLAB_TOKEN > CI_JOB_TOKEN
|
|
58
|
+
const token = process.env.GITLAB_TOKEN ||
|
|
59
|
+
process.env.CI_JOB_TOKEN ||
|
|
60
|
+
'';
|
|
61
|
+
|
|
62
|
+
// GitLab URL 优先级:GITLAB_URL > CI_SERVER_URL > 默认值
|
|
63
|
+
let url = process.env.GITLAB_URL;
|
|
64
|
+
if (!url && process.env.CI_SERVER_URL) {
|
|
65
|
+
url = process.env.CI_SERVER_URL;
|
|
66
|
+
} else if (!url && process.env.CI_API_V4_URL) {
|
|
67
|
+
// 从 API URL 推导(移除 /api/v4)
|
|
68
|
+
url = process.env.CI_API_V4_URL.replace(/\/api\/v4\/?$/, '');
|
|
69
|
+
} else if (!url) {
|
|
70
|
+
url = 'https://gitlab.com';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return { token, url };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* 获取 AI 配置(ARK API Key)
|
|
78
|
+
*/
|
|
79
|
+
export function getAIConfig() {
|
|
80
|
+
// 从环境变量读取 ARK_API_KEY
|
|
81
|
+
const arkApiKey = process.env.ARK_API_KEY || '';
|
|
82
|
+
|
|
83
|
+
// 从配置文件读取其他配置
|
|
84
|
+
const guardConfig = readAIReviewGuardConfig();
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
arkApiKey,
|
|
88
|
+
guardConfig,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* 获取项目配置(支持自动检测 CI 环境)
|
|
94
|
+
*/
|
|
95
|
+
export function getProjectConfig() {
|
|
96
|
+
// 项目 ID:PROJECT_ID > CI_PROJECT_ID > CI_PROJECT_PATH
|
|
97
|
+
let projectId = process.env.PROJECT_ID || process.env.CI_PROJECT_ID;
|
|
98
|
+
|
|
99
|
+
if (!projectId && process.env.CI_PROJECT_NAMESPACE && process.env.CI_PROJECT_NAME) {
|
|
100
|
+
projectId = `${process.env.CI_PROJECT_NAMESPACE}/${process.env.CI_PROJECT_NAME}`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (!projectId && process.env.CI_PROJECT_PATH) {
|
|
104
|
+
projectId = process.env.CI_PROJECT_PATH;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// MR IID:MERGE_REQUEST_IID > CI_MERGE_REQUEST_IID
|
|
108
|
+
const mergeRequestIid = process.env.MERGE_REQUEST_IID ||
|
|
109
|
+
process.env.CI_MERGE_REQUEST_IID ||
|
|
110
|
+
'';
|
|
111
|
+
|
|
112
|
+
return { projectId, mergeRequestIid };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* 获取完整配置
|
|
117
|
+
*/
|
|
118
|
+
export function getConfig() {
|
|
119
|
+
const gitlab = getGitLabConfig();
|
|
120
|
+
const project = getProjectConfig();
|
|
121
|
+
const ai = getAIConfig();
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
gitlab,
|
|
125
|
+
project,
|
|
126
|
+
ai,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* 验证配置
|
|
132
|
+
*/
|
|
133
|
+
export function validateConfig(config) {
|
|
134
|
+
const errors = [];
|
|
135
|
+
|
|
136
|
+
if (!config.gitlab.token) {
|
|
137
|
+
errors.push('缺少 GitLab Token');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (!config.project.projectId) {
|
|
141
|
+
errors.push('缺少项目 ID');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (errors.length > 0) {
|
|
145
|
+
throw new Error('配置验证失败: ' + errors.join(', '));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitLab API 客户端封装
|
|
3
|
+
* 简化版,仅包含基础功能
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export class GitLabClient {
|
|
7
|
+
constructor(options = {}) {
|
|
8
|
+
this.token = options.token;
|
|
9
|
+
this.host = options.host || 'https://gitlab.com';
|
|
10
|
+
this.apiUrl = `${this.host}/api/v4`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 发送 API 请求
|
|
15
|
+
*/
|
|
16
|
+
async request(endpoint, options = {}) {
|
|
17
|
+
const url = `${this.apiUrl}${endpoint}`;
|
|
18
|
+
const headers = {
|
|
19
|
+
'PRIVATE-TOKEN': this.token,
|
|
20
|
+
'Content-Type': 'application/json',
|
|
21
|
+
...options.headers,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const response = await fetch(url, {
|
|
25
|
+
...options,
|
|
26
|
+
headers,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
throw new Error(`GitLab API 请求失败: ${response.status} ${response.statusText}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return response.json();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 获取项目信息
|
|
38
|
+
*/
|
|
39
|
+
async getProject(projectId) {
|
|
40
|
+
return this.request(`/projects/${encodeURIComponent(projectId)}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 获取 Merge Request 信息
|
|
45
|
+
*/
|
|
46
|
+
async getMergeRequest(projectId, mergeRequestIid) {
|
|
47
|
+
return this.request(`/projects/${encodeURIComponent(projectId)}/merge_requests/${mergeRequestIid}`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 获取 MR 的代码变更
|
|
52
|
+
*/
|
|
53
|
+
async getMergeRequestChanges(projectId, mergeRequestIid) {
|
|
54
|
+
const mr = await this.request(`/projects/${encodeURIComponent(projectId)}/merge_requests/${mergeRequestIid}/changes`);
|
|
55
|
+
return mr.changes || [];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 在 MR 上创建评论
|
|
60
|
+
*/
|
|
61
|
+
async createMergeRequestNote(projectId, mergeRequestIid, body) {
|
|
62
|
+
return this.request(
|
|
63
|
+
`/projects/${encodeURIComponent(projectId)}/merge_requests/${mergeRequestIid}/notes`,
|
|
64
|
+
{
|
|
65
|
+
method: 'POST',
|
|
66
|
+
body: JSON.stringify({ body }),
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 在 MR 上创建讨论(行内评论)
|
|
73
|
+
*/
|
|
74
|
+
async createMergeRequestDiscussion(projectId, mergeRequestIid, body, position) {
|
|
75
|
+
return this.request(
|
|
76
|
+
`/projects/${encodeURIComponent(projectId)}/merge_requests/${mergeRequestIid}/discussions`,
|
|
77
|
+
{
|
|
78
|
+
method: 'POST',
|
|
79
|
+
body: JSON.stringify({
|
|
80
|
+
body,
|
|
81
|
+
position,
|
|
82
|
+
}),
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
package/package.json
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gitlab-ai-review",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "GitLab AI Review SDK -
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "GitLab AI Review SDK - 支持 CI/CD 自动配置和 ARK API",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "node test-info.js",
|
|
9
|
+
"test:info": "node test-info.js"
|
|
10
|
+
},
|
|
7
11
|
"files": [
|
|
8
12
|
"index.js",
|
|
13
|
+
"lib/",
|
|
14
|
+
"test-info.js",
|
|
9
15
|
"README.md"
|
|
10
16
|
],
|
|
11
17
|
"keywords": [
|
|
12
18
|
"gitlab",
|
|
13
19
|
"ai",
|
|
14
20
|
"review",
|
|
15
|
-
"sdk"
|
|
21
|
+
"sdk",
|
|
22
|
+
"ci-cd"
|
|
16
23
|
],
|
|
17
24
|
"author": "",
|
|
18
25
|
"license": "MIT",
|
|
@@ -20,4 +27,3 @@
|
|
|
20
27
|
"node": ">=18.0.0"
|
|
21
28
|
}
|
|
22
29
|
}
|
|
23
|
-
|
package/test-info.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 测试脚本:输出项目 URL 和最新 MR 编号
|
|
4
|
+
* 用于验证 gitlab-ai-review SDK 在 CI/CD 中的配置
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { GitLabAIReview } from './index.js';
|
|
8
|
+
|
|
9
|
+
async function testInfo() {
|
|
10
|
+
try {
|
|
11
|
+
console.log('🔍 正在测试 gitlab-ai-review SDK...\n');
|
|
12
|
+
|
|
13
|
+
// 创建 SDK 实例(自动从环境变量读取配置)
|
|
14
|
+
const sdk = new GitLabAIReview();
|
|
15
|
+
|
|
16
|
+
// 获取配置信息
|
|
17
|
+
const config = sdk.getConfig();
|
|
18
|
+
|
|
19
|
+
console.log('📋 配置信息:');
|
|
20
|
+
console.log('━'.repeat(50));
|
|
21
|
+
console.log(`GitLab URL: ${config.gitlab.url}`);
|
|
22
|
+
console.log(`项目 ID: ${config.project.projectId || '(未设置)'}`);
|
|
23
|
+
console.log(`MR IID: ${config.project.mergeRequestIid || '(未设置)'}`);
|
|
24
|
+
console.log(`Token: ${config.gitlab.token ? '✓ 已配置' : '✗ 未配置'}`);
|
|
25
|
+
console.log('━'.repeat(50));
|
|
26
|
+
console.log();
|
|
27
|
+
|
|
28
|
+
// 验证配置
|
|
29
|
+
try {
|
|
30
|
+
sdk.validate();
|
|
31
|
+
console.log('✅ 配置验证通过\n');
|
|
32
|
+
} catch (error) {
|
|
33
|
+
console.error('❌ 配置验证失败:', error.message);
|
|
34
|
+
console.log('\n💡 提示: 在 CI/CD 中,GitLab 会自动提供以下环境变量:');
|
|
35
|
+
console.log(' - CI_JOB_TOKEN (GitLab Token)');
|
|
36
|
+
console.log(' - CI_SERVER_URL (GitLab 地址)');
|
|
37
|
+
console.log(' - CI_PROJECT_PATH (项目路径)');
|
|
38
|
+
console.log(' - CI_MERGE_REQUEST_IID (MR 编号)\n');
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 获取项目信息
|
|
43
|
+
console.log('📦 正在获取项目信息...');
|
|
44
|
+
const project = await sdk.getProject();
|
|
45
|
+
console.log(`项目名称: ${project.name}`);
|
|
46
|
+
console.log(`项目描述: ${project.description || '(无)'}`);
|
|
47
|
+
console.log(`项目 URL: ${project.web_url}`);
|
|
48
|
+
console.log(`命名空间: ${project.namespace.full_path}`);
|
|
49
|
+
console.log(`默认分支: ${project.default_branch}`);
|
|
50
|
+
console.log();
|
|
51
|
+
|
|
52
|
+
// 获取 MR 信息
|
|
53
|
+
if (config.project.mergeRequestIid) {
|
|
54
|
+
console.log('🔀 正在获取 MR 信息...');
|
|
55
|
+
const mr = await sdk.getMergeRequest();
|
|
56
|
+
console.log(`MR 标题: ${mr.title}`);
|
|
57
|
+
console.log(`MR 编号: #${mr.iid}`);
|
|
58
|
+
console.log(`MR URL: ${mr.web_url}`);
|
|
59
|
+
console.log(`作者: ${mr.author.name} (@${mr.author.username})`);
|
|
60
|
+
console.log(`源分支: ${mr.source_branch}`);
|
|
61
|
+
console.log(`目标分支: ${mr.target_branch}`);
|
|
62
|
+
console.log(`状态: ${mr.state}`);
|
|
63
|
+
console.log(`创建时间: ${mr.created_at}`);
|
|
64
|
+
console.log();
|
|
65
|
+
|
|
66
|
+
// 获取代码变更
|
|
67
|
+
console.log('📝 正在获取代码变更...');
|
|
68
|
+
const changes = await sdk.getMergeRequestChanges();
|
|
69
|
+
console.log(`共有 ${changes.length} 个文件变更:`);
|
|
70
|
+
changes.forEach((change, index) => {
|
|
71
|
+
console.log(` ${index + 1}. ${change.new_path}`);
|
|
72
|
+
});
|
|
73
|
+
console.log();
|
|
74
|
+
} else {
|
|
75
|
+
console.log('⚠️ 未检测到 MR 环境(非 MR Pipeline)\n');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
console.log('━'.repeat(50));
|
|
79
|
+
console.log('✅ 测试完成!gitlab-ai-review SDK 工作正常!');
|
|
80
|
+
console.log('━'.repeat(50));
|
|
81
|
+
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error('\n❌ 测试失败:', error.message);
|
|
84
|
+
console.error('\n详细错误:', error);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 运行测试
|
|
90
|
+
testInfo();
|
|
91
|
+
|