@catchmexz/fedin-vibe-mcp-server 0.1.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.
Files changed (83) hide show
  1. package/LICENSE +202 -0
  2. package/dist/common/errors.js +69 -0
  3. package/dist/common/modularTemplates.js +483 -0
  4. package/dist/common/pipelineTemplates.js +19 -0
  5. package/dist/common/types.js +42 -0
  6. package/dist/common/utils.js +347 -0
  7. package/dist/common/version.js +1 -0
  8. package/dist/index.js +217 -0
  9. package/dist/operations/appstack/appOrchestrations.js +235 -0
  10. package/dist/operations/appstack/appTags.js +147 -0
  11. package/dist/operations/appstack/appTemplates.js +67 -0
  12. package/dist/operations/appstack/applications.js +154 -0
  13. package/dist/operations/appstack/changeOrders.js +293 -0
  14. package/dist/operations/appstack/changeRequests.js +263 -0
  15. package/dist/operations/appstack/deploymentResources.js +265 -0
  16. package/dist/operations/appstack/globalVars.js +200 -0
  17. package/dist/operations/appstack/releaseWorkflows.js +178 -0
  18. package/dist/operations/appstack/variableGroups.js +216 -0
  19. package/dist/operations/codeup/branches.js +144 -0
  20. package/dist/operations/codeup/changeRequestComments.js +89 -0
  21. package/dist/operations/codeup/changeRequests.js +203 -0
  22. package/dist/operations/codeup/compare.js +26 -0
  23. package/dist/operations/codeup/files.js +483 -0
  24. package/dist/operations/codeup/repositories.js +83 -0
  25. package/dist/operations/codeup/types.js +372 -0
  26. package/dist/operations/flow/hostGroup.js +48 -0
  27. package/dist/operations/flow/pipeline.js +530 -0
  28. package/dist/operations/flow/pipelineJob.js +113 -0
  29. package/dist/operations/flow/serviceConnection.js +23 -0
  30. package/dist/operations/flow/types.js +377 -0
  31. package/dist/operations/git/git-repository.js +334 -0
  32. package/dist/operations/git/index.js +210 -0
  33. package/dist/operations/organization/members.js +94 -0
  34. package/dist/operations/organization/organization.js +73 -0
  35. package/dist/operations/organization/types.js +111 -0
  36. package/dist/operations/packages/artifacts.js +64 -0
  37. package/dist/operations/packages/repositories.js +35 -0
  38. package/dist/operations/packages/types.js +56 -0
  39. package/dist/operations/projex/project.js +206 -0
  40. package/dist/operations/projex/sprint.js +90 -0
  41. package/dist/operations/projex/types.js +390 -0
  42. package/dist/operations/projex/workitem.js +452 -0
  43. package/dist/tool-handlers/appstack-change-orders.js +55 -0
  44. package/dist/tool-handlers/appstack-change-requests.js +49 -0
  45. package/dist/tool-handlers/appstack-deployment-resources.js +43 -0
  46. package/dist/tool-handlers/appstack-global-vars.js +43 -0
  47. package/dist/tool-handlers/appstack-orchestrations.js +49 -0
  48. package/dist/tool-handlers/appstack-tags.js +43 -0
  49. package/dist/tool-handlers/appstack-templates.js +19 -0
  50. package/dist/tool-handlers/appstack-variable-groups.js +55 -0
  51. package/dist/tool-handlers/appstack.js +37 -0
  52. package/dist/tool-handlers/code-management.js +174 -0
  53. package/dist/tool-handlers/git/branch-operations.js +1 -0
  54. package/dist/tool-handlers/git/clone-repository.js +36 -0
  55. package/dist/tool-handlers/git/create-branch.js +26 -0
  56. package/dist/tool-handlers/git/get-repository-status.js +33 -0
  57. package/dist/tool-handlers/git/pull-repository.js +27 -0
  58. package/dist/tool-handlers/git/push-repository.js +37 -0
  59. package/dist/tool-handlers/git/switch-branch.js +25 -0
  60. package/dist/tool-handlers/index.js +43 -0
  61. package/dist/tool-handlers/organization.js +90 -0
  62. package/dist/tool-handlers/packages.js +32 -0
  63. package/dist/tool-handlers/pipeline.js +272 -0
  64. package/dist/tool-handlers/project-management.js +152 -0
  65. package/dist/tool-handlers/service-connections.js +16 -0
  66. package/dist/tool-registry/appstack-change-orders.js +40 -0
  67. package/dist/tool-registry/appstack-change-requests.js +35 -0
  68. package/dist/tool-registry/appstack-deployment-resources.js +30 -0
  69. package/dist/tool-registry/appstack-global-vars.js +30 -0
  70. package/dist/tool-registry/appstack-orchestrations.js +35 -0
  71. package/dist/tool-registry/appstack-tags.js +30 -0
  72. package/dist/tool-registry/appstack-templates.js +10 -0
  73. package/dist/tool-registry/appstack-variable-groups.js +40 -0
  74. package/dist/tool-registry/appstack.js +25 -0
  75. package/dist/tool-registry/code-management.js +89 -0
  76. package/dist/tool-registry/git-repository.js +41 -0
  77. package/dist/tool-registry/index.js +6 -0
  78. package/dist/tool-registry/organization.js +65 -0
  79. package/dist/tool-registry/packages.js +21 -0
  80. package/dist/tool-registry/pipeline.js +157 -0
  81. package/dist/tool-registry/project-management.js +108 -0
  82. package/dist/tool-registry/service-connections.js +10 -0
  83. package/package.json +39 -0
@@ -0,0 +1,530 @@
1
+ import * as utils from "../../common/utils.js";
2
+ import { PipelineDetailSchema, PipelineListItemSchema, PipelineRunSchema, PipelineRunListItemSchema } from "./types.js";
3
+ import { generateModularPipeline } from "../../common/modularTemplates.js";
4
+ import { listServiceConnectionsFunc } from "./serviceConnection.js";
5
+ import { listHostGroupsFunc } from "./hostGroup.js";
6
+ /**
7
+ * 获取流水线详情
8
+ * @param organizationId 组织ID
9
+ * @param pipelineId 流水线ID
10
+ * @returns 流水线详情
11
+ */
12
+ export async function getPipelineFunc(organizationId, pipelineId) {
13
+ const url = `/oapi/v1/flow/organizations/${organizationId}/pipelines/${pipelineId}`;
14
+ const response = await utils.yunxiaoRequest(url, {
15
+ method: "GET",
16
+ });
17
+ return PipelineDetailSchema.parse(response);
18
+ }
19
+ /**
20
+ * 获取流水线列表
21
+ * @param organizationId 组织ID
22
+ * @param options 查询选项
23
+ * @returns 流水线列表
24
+ */
25
+ export async function listPipelinesFunc(organizationId, options) {
26
+ const baseUrl = `/oapi/v1/flow/organizations/${organizationId}/pipelines`;
27
+ // 构建查询参数
28
+ const queryParams = {};
29
+ // 处理时间戳参数
30
+ // 如果传入的是日期字符串或Date对象,自动转换为毫秒时间戳
31
+ if (options?.createStartTime !== undefined) {
32
+ queryParams.createStartTime = utils.convertToTimestamp(options.createStartTime);
33
+ }
34
+ if (options?.createEndTime !== undefined) {
35
+ queryParams.createEndTime = utils.convertToTimestamp(options.createEndTime);
36
+ }
37
+ if (options?.executeStartTime !== undefined) {
38
+ queryParams.executeStartTime = utils.convertToTimestamp(options.executeStartTime);
39
+ }
40
+ if (options?.executeEndTime !== undefined) {
41
+ queryParams.executeEndTime = utils.convertToTimestamp(options.executeEndTime);
42
+ }
43
+ if (options?.pipelineName !== undefined) {
44
+ queryParams.pipelineName = options.pipelineName;
45
+ }
46
+ if (options?.statusList !== undefined) {
47
+ queryParams.statusList = options.statusList;
48
+ }
49
+ if (options?.perPage !== undefined) {
50
+ queryParams.perPage = options.perPage;
51
+ }
52
+ if (options?.page !== undefined) {
53
+ queryParams.page = options.page;
54
+ }
55
+ const url = utils.buildUrl(baseUrl, queryParams);
56
+ const response = await utils.yunxiaoRequest(url, {
57
+ method: "GET",
58
+ });
59
+ const pagination = {
60
+ nextPage: null,
61
+ page: 1,
62
+ perPage: 10,
63
+ prevPage: null,
64
+ total: 0,
65
+ totalPages: 0
66
+ };
67
+ let items = [];
68
+ if (Array.isArray(response)) {
69
+ items = response.map(item => PipelineListItemSchema.parse(item));
70
+ }
71
+ return {
72
+ items,
73
+ pagination
74
+ };
75
+ }
76
+ /**
77
+ * 智能查询流水线列表,能够解析自然语言中的时间表达
78
+ * @param organizationId 组织ID
79
+ * @param timeReference 自然语言时间引用,如"今天"、"本周"、"上个月"
80
+ * @param options 其他查询选项
81
+ * @returns 流水线列表
82
+ */
83
+ export async function smartListPipelinesFunc(organizationId, timeReference, options) {
84
+ // 解析时间引用获取开始和结束时间戳
85
+ const { startTime, endTime } = utils.parseDateReference(timeReference);
86
+ // 合并选项
87
+ const fullOptions = {
88
+ ...options,
89
+ executeStartTime: startTime,
90
+ executeEndTime: endTime
91
+ };
92
+ return listPipelinesFunc(organizationId, fullOptions);
93
+ }
94
+ /**
95
+ * 运行流水线
96
+ * @param organizationId 组织ID
97
+ * @param pipelineId 流水线ID
98
+ * @param options 运行选项,可以是直接的JSON字符串或者自然语言描述的选项
99
+ * @returns 流水线运行ID
100
+ */
101
+ export async function createPipelineRunFunc(organizationId, pipelineId, options) {
102
+ const url = `/oapi/v1/flow/organizations/${organizationId}/pipelines/${pipelineId}/runs`;
103
+ // 如果用户已经提供了格式化的params,直接使用
104
+ if (options?.params) {
105
+ const body = {
106
+ params: options.params
107
+ };
108
+ const response = await utils.yunxiaoRequest(url, {
109
+ method: "POST",
110
+ body: body,
111
+ });
112
+ return Number(response);
113
+ }
114
+ // 否则,基于用户提供的自然语言参数构建params
115
+ const paramsObject = {};
116
+ // 处理分支模式相关参数
117
+ if (options?.branchMode && options?.branches && options.branches.length > 0) {
118
+ paramsObject.branchModeBranchs = options.branches;
119
+ }
120
+ // 处理Release分支相关参数
121
+ if (options?.createReleaseBranch !== undefined) {
122
+ paramsObject.needCreateBranch = options.createReleaseBranch;
123
+ }
124
+ if (options?.releaseBranch) {
125
+ paramsObject.releaseBranch = options.releaseBranch;
126
+ }
127
+ // 处理环境变量
128
+ if (options?.environmentVariables && Object.keys(options.environmentVariables).length > 0) {
129
+ paramsObject.envs = options.environmentVariables;
130
+ }
131
+ // 处理特定仓库配置
132
+ if (options?.repositories && options.repositories.length > 0) {
133
+ // 初始化runningBranchs和runningTags对象
134
+ const runningBranchs = {};
135
+ const runningTags = {};
136
+ // 填充分支和标签信息
137
+ options.repositories.forEach(repo => {
138
+ if (repo.branch) {
139
+ runningBranchs[repo.url] = repo.branch;
140
+ }
141
+ if (repo.tag) {
142
+ runningTags[repo.url] = repo.tag;
143
+ }
144
+ });
145
+ // 只有在有内容时才添加到params对象
146
+ if (Object.keys(runningBranchs).length > 0) {
147
+ paramsObject.runningBranchs = runningBranchs;
148
+ }
149
+ if (Object.keys(runningTags).length > 0) {
150
+ paramsObject.runningTags = runningTags;
151
+ }
152
+ }
153
+ // 如果有自然语言描述,尝试解析它
154
+ if (options?.description) {
155
+ // 此处可以添加更复杂的自然语言处理逻辑
156
+ // 当前实现是简单的关键词匹配
157
+ const description = options.description.toLowerCase();
158
+ // 检测分支模式
159
+ if ((description.includes('branch mode') || description.includes('分支模式')) &&
160
+ !paramsObject.branchModeBranchs &&
161
+ options?.branches?.length) {
162
+ paramsObject.branchModeBranchs = options.branches;
163
+ }
164
+ // 检测是否需要创建release分支
165
+ if ((description.includes('create release') || description.includes('创建release')) &&
166
+ paramsObject.needCreateBranch === undefined) {
167
+ paramsObject.needCreateBranch = true;
168
+ }
169
+ // 如果提到特定release分支但没有指定
170
+ if ((description.includes('release branch') || description.includes('release分支')) &&
171
+ !paramsObject.releaseBranch &&
172
+ options?.branches?.length) {
173
+ // 假设第一个分支就是release分支
174
+ paramsObject.releaseBranch = options.branches[0];
175
+ }
176
+ }
177
+ const body = {};
178
+ if (Object.keys(paramsObject).length > 0) {
179
+ body.params = JSON.stringify(paramsObject);
180
+ }
181
+ const response = await utils.yunxiaoRequest(url, {
182
+ method: "POST",
183
+ body: body,
184
+ });
185
+ return Number(response);
186
+ }
187
+ /**
188
+ * 获取最近一次流水线运行信息
189
+ * @param organizationId 组织ID
190
+ * @param pipelineId 流水线ID
191
+ * @returns 最近一次流水线运行信息
192
+ */
193
+ export async function getLatestPipelineRunFunc(organizationId, pipelineId) {
194
+ const url = `/oapi/v1/flow/organizations/${organizationId}/pipelines/${pipelineId}/runs/latestPipelineRun`;
195
+ const response = await utils.yunxiaoRequest(url, {
196
+ method: "GET",
197
+ });
198
+ return PipelineRunSchema.parse(response);
199
+ }
200
+ /**
201
+ * 获取特定流水线运行实例
202
+ * @param organizationId 组织ID
203
+ * @param pipelineId 流水线ID
204
+ * @param pipelineRunId 流水线运行ID
205
+ * @returns 流水线运行实例信息
206
+ */
207
+ export async function getPipelineRunFunc(organizationId, pipelineId, pipelineRunId) {
208
+ const url = `/oapi/v1/flow/organizations/${organizationId}/pipelines/${pipelineId}/runs/${pipelineRunId}`;
209
+ const response = await utils.yunxiaoRequest(url, {
210
+ method: "GET",
211
+ });
212
+ return PipelineRunSchema.parse(response);
213
+ }
214
+ /**
215
+ * 获取流水线运行实例列表
216
+ * @param organizationId 组织ID
217
+ * @param pipelineId 流水线ID
218
+ * @param options 查询选项
219
+ * @returns 流水线运行实例列表和分页信息
220
+ */
221
+ export async function listPipelineRunsFunc(organizationId, pipelineId, options) {
222
+ const baseUrl = `/oapi/v1/flow/organizations/${organizationId}/pipelines/${pipelineId}/runs`;
223
+ // 构建查询参数
224
+ const queryParams = {};
225
+ if (options?.perPage !== undefined) {
226
+ queryParams.perPage = options.perPage;
227
+ }
228
+ if (options?.page !== undefined) {
229
+ queryParams.page = options.page;
230
+ }
231
+ if (options?.startTime !== undefined) {
232
+ queryParams.startTime = utils.convertToTimestamp(options.startTime);
233
+ }
234
+ if (options?.endTime !== undefined) {
235
+ queryParams.endTme = utils.convertToTimestamp(options.endTime);
236
+ }
237
+ if (options?.status !== undefined) {
238
+ queryParams.status = options.status;
239
+ }
240
+ if (options?.triggerMode !== undefined) {
241
+ queryParams.triggerMode = options.triggerMode;
242
+ }
243
+ const url = utils.buildUrl(baseUrl, queryParams);
244
+ const response = await utils.yunxiaoRequest(url, {
245
+ method: "GET",
246
+ });
247
+ const pagination = {
248
+ nextPage: null,
249
+ page: options?.page ?? 1,
250
+ perPage: options?.perPage ?? 10,
251
+ prevPage: null,
252
+ total: 0,
253
+ totalPages: 0
254
+ };
255
+ let items = [];
256
+ if (Array.isArray(response)) {
257
+ items = response.map(item => PipelineRunListItemSchema.parse(item));
258
+ }
259
+ return {
260
+ items,
261
+ pagination
262
+ };
263
+ }
264
+ /**
265
+ * 创建流水线
266
+ * @param organizationId 组织ID
267
+ * @param name 流水线名称
268
+ * @param content 流水线YAML描述
269
+ * @returns 流水线ID
270
+ */
271
+ export async function createPipelineFunc(organizationId, name, content) {
272
+ const url = `/oapi/v1/flow/organizations/${organizationId}/pipelines`;
273
+ const body = {
274
+ name: name,
275
+ content: content
276
+ };
277
+ const response = await utils.yunxiaoRequest(url, {
278
+ method: "POST",
279
+ body: body,
280
+ });
281
+ return Number(response);
282
+ }
283
+ /**
284
+ * 基于结构化参数生成流水线YAML(不创建流水线)
285
+ * @param options 结构化的流水线配置选项
286
+ * @returns 生成的YAML字符串
287
+ */
288
+ export async function generatePipelineYamlFunc(options) {
289
+ // 自动从repoUrl解析serviceName(如果用户没有明确指定)
290
+ let derivedServiceName = options.serviceName;
291
+ if (!derivedServiceName && options.repoUrl) {
292
+ // 从Git URL中提取项目名称
293
+ // 支持格式: git@codeup.aliyun.com:org/repo.git 或 https://codeup.aliyun.com/org/repo.git
294
+ const repoUrlMatch = options.repoUrl.match(/[\/:]([^\/]+)\.git$/);
295
+ if (repoUrlMatch) {
296
+ derivedServiceName = repoUrlMatch[1];
297
+ }
298
+ }
299
+ // 准备变量,确保版本号有双引号
300
+ const variables = {
301
+ // 基础配置
302
+ ...(options.repoUrl && { repoUrl: options.repoUrl }),
303
+ ...(options.branch && { branch: options.branch }),
304
+ ...(derivedServiceName && { serviceName: derivedServiceName }),
305
+ ...(options.serviceConnectionId && { serviceConnectionId: options.serviceConnectionId }),
306
+ ...(options.packagesServiceConnection && { packagesServiceConnection: options.packagesServiceConnection }),
307
+ ...(options.machineGroupId && { machineGroupId: options.machineGroupId }),
308
+ ...(options.namespace && { namespace: options.namespace }),
309
+ ...(options.dockerImage && { dockerImage: options.dockerImage }),
310
+ // 版本相关(确保双引号)
311
+ ...(options.jdkVersion && { jdkVersion: `"${options.jdkVersion}"` }),
312
+ ...(options.mavenVersion && { mavenVersion: `"${options.mavenVersion}"` }),
313
+ ...(options.nodeVersion && { nodeVersion: `"${options.nodeVersion}"` }),
314
+ ...(options.pythonVersion && { pythonVersion: `"${options.pythonVersion}"` }),
315
+ ...(options.goVersion && { goVersion: `"${options.goVersion}"` }),
316
+ ...(options.kubectlVersion && { kubectlVersion: `"${options.kubectlVersion}"` }),
317
+ // 构建物上传相关
318
+ ...(options.uploadType && { uploadType: options.uploadType }),
319
+ ...(options.artifactName && { artifactName: options.artifactName }),
320
+ ...(options.artifactVersion && { artifactVersion: options.artifactVersion }),
321
+ ...(options.packagesRepoId && { packagesRepoId: options.packagesRepoId }),
322
+ ...(options.includePathInArtifact !== undefined && { includePathInArtifact: options.includePathInArtifact }),
323
+ // 部署相关
324
+ ...(options.executeUser && { executeUser: options.executeUser }),
325
+ ...(options.artifactDownloadPath && { artifactDownloadPath: options.artifactDownloadPath }),
326
+ ...(options.kubernetesClusterId && { kubernetesClusterId: options.kubernetesClusterId }),
327
+ ...(options.yamlPath && { yamlPath: options.yamlPath }),
328
+ // 命令
329
+ ...(options.buildCommand && { buildCommand: options.buildCommand }),
330
+ ...(options.testCommand && { testCommand: options.testCommand }),
331
+ ...(options.deployCommand && { deployCommand: options.deployCommand }),
332
+ };
333
+ // 转换为模块化流水线选项
334
+ const deployTargets = options.deployTarget ? [options.deployTarget] : [];
335
+ // 使用模块化架构生成YAML
336
+ return generateModularPipeline({
337
+ keywords: [options.buildLanguage, options.buildTool],
338
+ buildLanguages: [options.buildLanguage],
339
+ buildTools: [options.buildTool],
340
+ deployTargets: deployTargets,
341
+ uploadType: options.uploadType || 'packages',
342
+ variables: variables
343
+ });
344
+ }
345
+ /**
346
+ * 基于结构化参数创建流水线
347
+ * @param organizationId 组织ID
348
+ * @param options 结构化的流水线配置选项
349
+ * @returns 创建结果,包含流水线ID和生成的YAML
350
+ */
351
+ export async function createPipelineWithOptionsFunc(organizationId, options) {
352
+ // 获取默认服务连接ID(如果用户没有明确指定)
353
+ let defaultServiceConnectionId = null;
354
+ const hasServiceConnectionId = options.serviceConnectionId;
355
+ if (!hasServiceConnectionId) {
356
+ defaultServiceConnectionId = await getDefaultServiceConnectionId(organizationId);
357
+ }
358
+ // 获取默认Packages服务连接ID(如果用户没有明确指定且需要packages上传)
359
+ let defaultPackagesServiceConnectionId = null;
360
+ const hasPackagesServiceConnectionId = options.packagesServiceConnection;
361
+ const needsPackagesUpload = !options.uploadType || options.uploadType === 'packages';
362
+ if (!hasPackagesServiceConnectionId && needsPackagesUpload) {
363
+ defaultPackagesServiceConnectionId = await getDefaultPackagesServiceConnectionId(organizationId);
364
+ }
365
+ // 获取默认主机组ID(如果用户没有明确指定且需要VM部署)
366
+ let defaultMachineGroupId = null;
367
+ const hasMachineGroupId = options.machineGroupId;
368
+ const needsVMDeploy = options.deployTarget === 'vm';
369
+ if (!hasMachineGroupId && needsVMDeploy) {
370
+ defaultMachineGroupId = await getDefaultHostGroupId(organizationId);
371
+ }
372
+ // 自动从repoUrl解析serviceName(如果用户没有明确指定)
373
+ let derivedServiceName = options.serviceName;
374
+ if (!derivedServiceName && options.repoUrl) {
375
+ // 从Git URL中提取项目名称
376
+ // 支持格式: git@codeup.aliyun.com:org/repo.git 或 https://codeup.aliyun.com/org/repo.git
377
+ const repoUrlMatch = options.repoUrl.match(/[\/:]([^\/]+)\.git$/);
378
+ if (repoUrlMatch) {
379
+ derivedServiceName = repoUrlMatch[1];
380
+ }
381
+ }
382
+ // 准备模块化流水线生成的变量
383
+ const finalVariables = {
384
+ // 基础配置(直接使用用户提供的值)
385
+ ...(options.repoUrl && { repoUrl: options.repoUrl }),
386
+ ...(options.branch && { branch: options.branch }),
387
+ ...(derivedServiceName && { serviceName: derivedServiceName }),
388
+ // 使用获取到的默认服务连接ID
389
+ ...(defaultServiceConnectionId && !hasServiceConnectionId && { serviceConnectionId: defaultServiceConnectionId }),
390
+ // 使用获取到的默认Packages服务连接ID
391
+ ...(defaultPackagesServiceConnectionId && !hasPackagesServiceConnectionId && { packagesServiceConnection: defaultPackagesServiceConnectionId }),
392
+ // 使用获取到的默认主机组ID
393
+ ...(defaultMachineGroupId && !hasMachineGroupId && { machineGroupId: defaultMachineGroupId }),
394
+ // 用户明确指定的值优先级最高
395
+ ...(options.serviceConnectionId && { serviceConnectionId: options.serviceConnectionId }),
396
+ ...(options.packagesServiceConnection && { packagesServiceConnection: options.packagesServiceConnection }),
397
+ ...(options.machineGroupId && { machineGroupId: options.machineGroupId }),
398
+ ...(options.namespace && { namespace: options.namespace }),
399
+ ...(options.dockerImage && { dockerImage: options.dockerImage }),
400
+ // 版本相关(确保双引号)
401
+ ...(options.jdkVersion && { jdkVersion: `"${options.jdkVersion}"` }),
402
+ ...(options.mavenVersion && { mavenVersion: `"${options.mavenVersion}"` }),
403
+ ...(options.nodeVersion && { nodeVersion: `"${options.nodeVersion}"` }),
404
+ ...(options.pythonVersion && { pythonVersion: `"${options.pythonVersion}"` }),
405
+ ...(options.goVersion && { goVersion: `"${options.goVersion}"` }),
406
+ ...(options.kubectlVersion && { kubectlVersion: `"${options.kubectlVersion}"` }),
407
+ // 构建物上传相关
408
+ ...(options.uploadType && { uploadType: options.uploadType }),
409
+ ...(options.artifactName && { artifactName: options.artifactName }),
410
+ ...(options.artifactVersion && { artifactVersion: options.artifactVersion }),
411
+ ...(options.packagesRepoId && { packagesRepoId: options.packagesRepoId }),
412
+ ...(options.includePathInArtifact !== undefined && { includePathInArtifact: options.includePathInArtifact }),
413
+ // 部署相关
414
+ ...(options.executeUser && { executeUser: options.executeUser }),
415
+ ...(options.artifactDownloadPath && { artifactDownloadPath: options.artifactDownloadPath }),
416
+ ...(options.kubernetesClusterId && { kubernetesClusterId: options.kubernetesClusterId }),
417
+ ...(options.yamlPath && { yamlPath: options.yamlPath }),
418
+ // 命令
419
+ ...(options.buildCommand && { buildCommand: options.buildCommand }),
420
+ ...(options.testCommand && { testCommand: options.testCommand }),
421
+ ...(options.deployCommand && { deployCommand: options.deployCommand }),
422
+ };
423
+ // 转换为模块化流水线选项
424
+ const deployTargets = options.deployTarget ? [options.deployTarget] : [];
425
+ // 使用模块化架构生成YAML
426
+ const generatedYaml = generateModularPipeline({
427
+ keywords: [options.buildLanguage, options.buildTool],
428
+ buildLanguages: [options.buildLanguage],
429
+ buildTools: [options.buildTool],
430
+ deployTargets: deployTargets,
431
+ uploadType: options.uploadType || 'packages',
432
+ variables: finalVariables
433
+ });
434
+ // 创建流水线
435
+ try {
436
+ const pipelineId = await createPipelineFunc(organizationId, options.name, generatedYaml);
437
+ return {
438
+ pipelineId,
439
+ generatedYaml
440
+ };
441
+ }
442
+ catch (error) {
443
+ // 如果是YAML校验失败或其他流水线创建错误,将详细信息透出给用户
444
+ console.error('Create pipeline failed:', error);
445
+ // 构造包含生成YAML的错误信息,方便用户排查
446
+ const errorMessage = error instanceof Error ? error.message : String(error);
447
+ const enhancedError = new Error(`Create pipeline failed: ${errorMessage}\n\n` +
448
+ `YAML content:\n${generatedYaml}\n\n` +
449
+ `Suggestions:\n` +
450
+ `1. Check whether the YAML format is correct.\n` +
451
+ `2. Verify whether the serviceConnectionID、machineGroupID、kubernetesClusterID and other parameters are existed and valid.`);
452
+ // 保持原始错误的堆栈信息
453
+ if (error instanceof Error && error.stack) {
454
+ enhancedError.stack = error.stack;
455
+ }
456
+ throw enhancedError;
457
+ }
458
+ }
459
+ /**
460
+ * 获取默认的服务连接ID(用于代码源配置)
461
+ * @param organizationId 组织ID
462
+ * @returns 服务连接ID
463
+ */
464
+ async function getDefaultServiceConnectionId(organizationId) {
465
+ try {
466
+ // 获取Codeup类型的服务连接(代码源最常用)
467
+ const serviceConnections = await listServiceConnectionsFunc(organizationId, 'codeup');
468
+ if (serviceConnections && serviceConnections.length > 0) {
469
+ return serviceConnections[0].uuid || null;
470
+ }
471
+ return null;
472
+ }
473
+ catch (error) {
474
+ console.error('获取Codeup服务连接失败:', error);
475
+ return null;
476
+ }
477
+ }
478
+ /**
479
+ * 获取默认的Packages服务连接ID(用于制品上传配置)
480
+ * @param organizationId 组织ID
481
+ * @returns Packages服务连接ID
482
+ */
483
+ async function getDefaultPackagesServiceConnectionId(organizationId) {
484
+ try {
485
+ // 获取packages类型的服务连接
486
+ const serviceConnections = await listServiceConnectionsFunc(organizationId, 'packages');
487
+ if (serviceConnections && serviceConnections.length > 0) {
488
+ return serviceConnections[0].uuid || null;
489
+ }
490
+ return null;
491
+ }
492
+ catch (error) {
493
+ console.error('获取Packages服务连接失败:', error);
494
+ return null;
495
+ }
496
+ }
497
+ /**
498
+ * 获取默认的主机组UUID(用于VM部署配置)
499
+ * @param organizationId 组织ID
500
+ * @returns null(暂不自动获取)
501
+ */
502
+ async function getDefaultHostGroupId(organizationId) {
503
+ try {
504
+ const hostGroups = await listHostGroupsFunc(organizationId);
505
+ if (hostGroups && hostGroups.length > 0) {
506
+ return hostGroups[0].uuid || null;
507
+ }
508
+ return null;
509
+ }
510
+ catch (error) {
511
+ console.error('获取主机组失败:', error);
512
+ return null;
513
+ }
514
+ }
515
+ /**
516
+ * 更新流水线内容(YAML)
517
+ * @param organizationId
518
+ * @param pipelineId
519
+ * @param name
520
+ * @param content
521
+ */
522
+ export async function updatePipelineFunc(organizationId, pipelineId, name, content) {
523
+ const url = `/oapi/v1/flow/organizations/${organizationId}/pipelines/${pipelineId}`;
524
+ const body = { name, content };
525
+ const response = await utils.yunxiaoRequest(url, {
526
+ method: "PUT",
527
+ body
528
+ });
529
+ return Boolean(response);
530
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * 流水线任务相关操作
3
+ * 提供按照分类获取流水线执行的任务接口
4
+ */
5
+ import * as utils from "../../common/utils.js";
6
+ import { PipelineJobItemSchema, PipelineJobHistoryItemSchema, PipelineJobRunLogSchema } from "./types.js";
7
+ /**
8
+ * 按任务分类获取流水线执行的任务
9
+ * @param organizationId Organization ID(组织ID)
10
+ * @param pipelineId Pipeline ID(流水线ID)
11
+ * @param category Task category, currently only supports DEPLOY(任务分类,当前仅支持DEPLOY)
12
+ * @returns 任务列表
13
+ */
14
+ export async function listPipelineJobsByCategoryFunc(organizationId, pipelineId, category) {
15
+ const url = `/oapi/v1/flow/organizations/${organizationId}/pipelines/${pipelineId}/listTasksByCategory/${category}`;
16
+ const response = await utils.yunxiaoRequest(url, {
17
+ method: "GET",
18
+ });
19
+ if (!Array.isArray(response)) {
20
+ return [];
21
+ }
22
+ return response.map(job => PipelineJobItemSchema.parse(job));
23
+ }
24
+ /**
25
+ * 获取流水线任务的执行历史
26
+ * @param organizationId Organization ID(组织ID)
27
+ * @param pipelineId Pipeline ID(流水线ID)
28
+ * @param category Task category, currently only supports DEPLOY(任务分类,当前仅支持DEPLOY)
29
+ * @param identifier Task identifier(任务标识)
30
+ * @param page Page number, default 1
31
+ * @param perPage Number of items per page, default 10, max 30
32
+ * @returns Job history list and pagination information
33
+ */
34
+ export async function listPipelineJobHistorysFunc(organizationId, pipelineId, category, identifier, page = 1, perPage = 10) {
35
+ const baseUrl = `/oapi/v1/flow/organizations/${organizationId}/pipelines/getComponentsWithoutButtons`;
36
+ const queryParams = {
37
+ pipelineId,
38
+ category,
39
+ identifier,
40
+ page,
41
+ perPage
42
+ };
43
+ const url = utils.buildUrl(baseUrl, queryParams);
44
+ const response = await utils.yunxiaoRequest(url, {
45
+ method: "GET",
46
+ });
47
+ const pagination = {
48
+ nextPage: null,
49
+ page: page,
50
+ perPage: perPage,
51
+ prevPage: null,
52
+ total: 0,
53
+ totalPages: 0
54
+ };
55
+ if (response && 'headers' in response) {
56
+ const headers = response.headers;
57
+ if (headers['x-next-page']) {
58
+ pagination.nextPage = parseInt(headers['x-next-page']);
59
+ }
60
+ if (headers['x-page']) {
61
+ pagination.page = parseInt(headers['x-page']);
62
+ }
63
+ if (headers['x-per-page']) {
64
+ pagination.perPage = parseInt(headers['x-per-page']);
65
+ }
66
+ if (headers['x-prev-page']) {
67
+ pagination.prevPage = parseInt(headers['x-prev-page']);
68
+ }
69
+ if (headers['x-total']) {
70
+ pagination.total = parseInt(headers['x-total']);
71
+ }
72
+ if (headers['x-total-pages']) {
73
+ pagination.totalPages = parseInt(headers['x-total-pages']);
74
+ }
75
+ }
76
+ const items = Array.isArray(response)
77
+ ? response.map(item => PipelineJobHistoryItemSchema.parse(item))
78
+ : [];
79
+ return {
80
+ items,
81
+ pagination
82
+ };
83
+ }
84
+ /**
85
+ * 手动运行流水线任务
86
+ * @param organizationId Organization ID(组织ID)
87
+ * @param pipelineId Pipeline ID(流水线ID)
88
+ * @param pipelineRunId Pipeline run instance ID(流水线运行ID)
89
+ * @param jobId Job ID for the pipeline run task(流水线运行任务ID)
90
+ * @returns Whether the operation was successful
91
+ */
92
+ export async function executePipelineJobRunFunc(organizationId, pipelineId, pipelineRunId, jobId) {
93
+ const url = `/oapi/v1/flow/organizations/${organizationId}/pipelines/${pipelineId}/pipelineRuns/${pipelineRunId}/jobs/${jobId}/start`;
94
+ const response = await utils.yunxiaoRequest(url, {
95
+ method: "POST",
96
+ });
97
+ return Boolean(response);
98
+ }
99
+ /**
100
+ * 查询任务运行日志
101
+ * @param organizationId Organization ID(组织ID)
102
+ * @param pipelineId Pipeline ID(流水线ID)
103
+ * @param pipelineRunId Pipeline run instance ID(流水线运行ID)
104
+ * @param jobId Job ID of the pipeline run task(流水线运行任务ID)
105
+ * @returns Log content and metadata
106
+ */
107
+ export async function getPipelineJobRunLogFunc(organizationId, pipelineId, pipelineRunId, jobId) {
108
+ const url = `/oapi/v1/flow/organizations/${organizationId}/pipelines/${pipelineId}/runs/${pipelineRunId}/job/${jobId}/log`;
109
+ const response = await utils.yunxiaoRequest(url, {
110
+ method: "GET",
111
+ });
112
+ return PipelineJobRunLogSchema.parse(response);
113
+ }
@@ -0,0 +1,23 @@
1
+ import * as utils from "../../common/utils.js";
2
+ import { ServiceConnectionSchema } from "./types.js";
3
+ /**
4
+ * 获取服务连接列表
5
+ * @param organizationId 组织ID
6
+ * @param serviceConnectionType 服务连接类型
7
+ * @returns 服务连接列表
8
+ */
9
+ export async function listServiceConnectionsFunc(organizationId, serviceConnectionType) {
10
+ const baseUrl = `/oapi/v1/flow/organizations/${organizationId}/serviceConnections`;
11
+ // 构建查询参数
12
+ const queryParams = {
13
+ sericeConnectionType: serviceConnectionType // 注意:API文档中拼写为 sericeConnectionType
14
+ };
15
+ const url = utils.buildUrl(baseUrl, queryParams);
16
+ const response = await utils.yunxiaoRequest(url, {
17
+ method: "GET",
18
+ });
19
+ if (!Array.isArray(response)) {
20
+ return [];
21
+ }
22
+ return response.map(item => ServiceConnectionSchema.parse(item));
23
+ }