devops-mcp-server-extension 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.
Files changed (102) hide show
  1. package/LICENSE +218 -0
  2. package/README.md +527 -0
  3. package/README.zh-cn.md +503 -0
  4. package/dist/common/errors.js +77 -0
  5. package/dist/common/modularTemplates.js +483 -0
  6. package/dist/common/pipelineTemplates.js +19 -0
  7. package/dist/common/toolsetManager.js +123 -0
  8. package/dist/common/toolsets.js +23 -0
  9. package/dist/common/types.js +60 -0
  10. package/dist/common/utils.js +381 -0
  11. package/dist/common/version.js +1 -0
  12. package/dist/index.js +225 -0
  13. package/dist/operations/appstack/appOrchestrations.js +260 -0
  14. package/dist/operations/appstack/appTags.js +168 -0
  15. package/dist/operations/appstack/appTemplates.js +72 -0
  16. package/dist/operations/appstack/applications.js +171 -0
  17. package/dist/operations/appstack/changeOrders.js +320 -0
  18. package/dist/operations/appstack/changeRequests.js +288 -0
  19. package/dist/operations/appstack/deploymentResources.js +286 -0
  20. package/dist/operations/appstack/globalVars.js +221 -0
  21. package/dist/operations/appstack/releaseWorkflows.js +695 -0
  22. package/dist/operations/appstack/variableGroups.js +245 -0
  23. package/dist/operations/codeup/branches.js +157 -0
  24. package/dist/operations/codeup/changeRequestComments.js +140 -0
  25. package/dist/operations/codeup/changeRequests.js +230 -0
  26. package/dist/operations/codeup/commits.js +121 -0
  27. package/dist/operations/codeup/compare.js +30 -0
  28. package/dist/operations/codeup/files.js +249 -0
  29. package/dist/operations/codeup/repositories.js +71 -0
  30. package/dist/operations/codeup/types.js +414 -0
  31. package/dist/operations/flow/hostGroup.js +52 -0
  32. package/dist/operations/flow/pipeline.js +609 -0
  33. package/dist/operations/flow/pipelineJob.js +126 -0
  34. package/dist/operations/flow/resourceMember.js +137 -0
  35. package/dist/operations/flow/serviceConnection.js +27 -0
  36. package/dist/operations/flow/tag.js +191 -0
  37. package/dist/operations/flow/types.js +523 -0
  38. package/dist/operations/flow/vmDeployOrder.js +171 -0
  39. package/dist/operations/organization/members.js +106 -0
  40. package/dist/operations/organization/organization.js +110 -0
  41. package/dist/operations/organization/types.js +111 -0
  42. package/dist/operations/packages/artifacts.js +71 -0
  43. package/dist/operations/packages/repositories.js +39 -0
  44. package/dist/operations/packages/types.js +56 -0
  45. package/dist/operations/projex/effort.js +122 -0
  46. package/dist/operations/projex/project.js +243 -0
  47. package/dist/operations/projex/sprint.js +103 -0
  48. package/dist/operations/projex/types.js +618 -0
  49. package/dist/operations/projex/workitem.js +826 -0
  50. package/dist/operations/testhub/testcases.js +240 -0
  51. package/dist/operations/testhub/testplans.js +128 -0
  52. package/dist/tool-handlers/appstack-app-release-workflows.js +103 -0
  53. package/dist/tool-handlers/appstack-change-orders.js +55 -0
  54. package/dist/tool-handlers/appstack-change-requests.js +49 -0
  55. package/dist/tool-handlers/appstack-deployment-resources.js +31 -0
  56. package/dist/tool-handlers/appstack-global-vars.js +37 -0
  57. package/dist/tool-handlers/appstack-orchestrations.js +49 -0
  58. package/dist/tool-handlers/appstack-release-workflows.js +37 -0
  59. package/dist/tool-handlers/appstack-tags.js +37 -0
  60. package/dist/tool-handlers/appstack-templates.js +19 -0
  61. package/dist/tool-handlers/appstack-variable-groups.js +55 -0
  62. package/dist/tool-handlers/appstack.js +37 -0
  63. package/dist/tool-handlers/base.js +25 -0
  64. package/dist/tool-handlers/code-management.js +150 -0
  65. package/dist/tool-handlers/commit.js +31 -0
  66. package/dist/tool-handlers/effort.js +103 -0
  67. package/dist/tool-handlers/index.js +119 -0
  68. package/dist/tool-handlers/organization.js +72 -0
  69. package/dist/tool-handlers/packages.js +32 -0
  70. package/dist/tool-handlers/pipeline.js +289 -0
  71. package/dist/tool-handlers/project-management.js +201 -0
  72. package/dist/tool-handlers/resourceMember.js +43 -0
  73. package/dist/tool-handlers/service-connections.js +16 -0
  74. package/dist/tool-handlers/tag.js +64 -0
  75. package/dist/tool-handlers/test-management.js +74 -0
  76. package/dist/tool-handlers/vmDeployOrder.js +50 -0
  77. package/dist/tool-registry/appstack-app-release-workflows.js +80 -0
  78. package/dist/tool-registry/appstack-change-orders.js +40 -0
  79. package/dist/tool-registry/appstack-change-requests.js +35 -0
  80. package/dist/tool-registry/appstack-deployment-resources.js +20 -0
  81. package/dist/tool-registry/appstack-global-vars.js +25 -0
  82. package/dist/tool-registry/appstack-orchestrations.js +35 -0
  83. package/dist/tool-registry/appstack-release-workflows.js +25 -0
  84. package/dist/tool-registry/appstack-tags.js +25 -0
  85. package/dist/tool-registry/appstack-templates.js +10 -0
  86. package/dist/tool-registry/appstack-variable-groups.js +40 -0
  87. package/dist/tool-registry/appstack.js +25 -0
  88. package/dist/tool-registry/base.js +19 -0
  89. package/dist/tool-registry/code-management.js +109 -0
  90. package/dist/tool-registry/commit.js +20 -0
  91. package/dist/tool-registry/effort.js +39 -0
  92. package/dist/tool-registry/index.js +7 -0
  93. package/dist/tool-registry/organization.js +65 -0
  94. package/dist/tool-registry/packages.js +21 -0
  95. package/dist/tool-registry/pipeline.js +190 -0
  96. package/dist/tool-registry/project-management.js +143 -0
  97. package/dist/tool-registry/resourceMember.js +29 -0
  98. package/dist/tool-registry/service-connections.js +10 -0
  99. package/dist/tool-registry/tag.js +44 -0
  100. package/dist/tool-registry/test-management.js +59 -0
  101. package/dist/tool-registry/vmDeployOrder.js +34 -0
  102. package/package.json +52 -0
@@ -0,0 +1,245 @@
1
+ import { z } from 'zod';
2
+ import { yunxiaoRequest, isRegionEdition } from '../../common/utils.js';
3
+ import { resolveOrganizationId } from '../organization/organization.js';
4
+ // Define the Variable schema based on the definition in appstack.swagger.json
5
+ const VariableSchema = z.object({
6
+ description: z.string().optional().describe("变量描述"),
7
+ key: z.string().optional().describe("变量键"),
8
+ value: z.string().optional().describe("变量值"),
9
+ }).describe("变量模型");
10
+ // Define the RepoMeta schema based on the definition in appstack.swagger.json
11
+ const RepoMetaSchema = z.object({
12
+ name: z.string().describe("仓库名称"),
13
+ type: z.string().describe("仓库类型"),
14
+ }).describe("仓库信息");
15
+ // Define the Revision schema based on the definition in 变量组.swagger.json
16
+ const RevisionSchema = z.object({
17
+ author: z.string().describe("提交人"),
18
+ commitTime: z.number().describe("提交时间 (毫秒时间戳)"),
19
+ message: z.string().describe("版本提交信息"),
20
+ refs: z.array(z.string()).describe("关联信息"),
21
+ repoMeta: RepoMetaSchema.describe("仓库元信息"),
22
+ sha: z.string().describe("版本sha值"),
23
+ }).describe("版本信息");
24
+ // Define the RevisionVariableGroup schema based on the definition in 变量组.swagger.json
25
+ const RevisionVariableGroupSchema = z.object({
26
+ displayName: z.string().optional().describe("变量组展示名称"),
27
+ name: z.string().optional().describe("变量组名称"),
28
+ revision: RevisionSchema.optional().describe("版本信息"),
29
+ type: z.enum(["GLOBAL", "TEMPLATE", "APP"]).optional().describe("类型"),
30
+ vars: z.array(VariableSchema).optional().describe("变量列表"),
31
+ }).describe("变量组版本记录");
32
+ // Schema for the GetEnvVariableGroups API
33
+ export const GetEnvVariableGroupsRequestSchema = z.object({
34
+ organizationId: z.string().describe("组织ID"),
35
+ appName: z.string().describe("应用名"),
36
+ envName: z.string().describe("环境名"),
37
+ });
38
+ export const GetEnvVariableGroupsResponseSchema = z.array(RevisionVariableGroupSchema);
39
+ // Schema for the CreateVariableGroup API
40
+ export const CreateVariableGroupRequestSchema = z.object({
41
+ organizationId: z.string().describe("组织ID"),
42
+ appName: z.string().describe("应用名"),
43
+ branchName: z.string().optional().describe("版本分支,默认 master"),
44
+ displayName: z.string().optional().describe("变量组展示名"),
45
+ fromRevisionSha: z.string().describe("变量组版本号"),
46
+ message: z.string().optional().describe("变量组描述信息"),
47
+ name: z.string().optional().describe("变量组唯一名"),
48
+ vars: z.array(VariableSchema).optional().describe("变量列表"),
49
+ });
50
+ export const CreateVariableGroupResponseSchema = RevisionVariableGroupSchema;
51
+ // Schema for the DeleteVariableGroup API
52
+ export const DeleteVariableGroupRequestSchema = z.object({
53
+ organizationId: z.string().describe("组织ID"),
54
+ appName: z.string().describe("应用名"),
55
+ variableGroupName: z.string().describe("变量组名"),
56
+ });
57
+ export const DeleteVariableGroupResponseSchema = z.boolean().describe("调用是否成功");
58
+ // Schema for the GetVariableGroup API
59
+ export const GetVariableGroupRequestSchema = z.object({
60
+ organizationId: z.string().describe("组织ID"),
61
+ appName: z.string().describe("应用名"),
62
+ variableGroupName: z.string().describe("变量组名"),
63
+ });
64
+ export const GetVariableGroupResponseSchema = RevisionVariableGroupSchema;
65
+ // Schema for the UpdateVariableGroup API
66
+ export const UpdateVariableGroupRequestSchema = z.object({
67
+ organizationId: z.string().describe("组织ID"),
68
+ appName: z.string().describe("应用名"),
69
+ variableGroupName: z.string().describe("变量组名"),
70
+ branchName: z.string().optional().describe("版本分支,默认 master"),
71
+ displayName: z.string().optional().describe("变量组展示名"),
72
+ fromRevisionSha: z.string().describe("变量组版本号"),
73
+ message: z.string().optional().describe("变量组描述信息"),
74
+ name: z.string().optional().describe("变量组唯一名"),
75
+ vars: z.array(VariableSchema).optional().describe("变量列表"),
76
+ });
77
+ export const UpdateVariableGroupResponseSchema = RevisionVariableGroupSchema;
78
+ // Schema for the GetAppVariableGroups API
79
+ export const GetAppVariableGroupsRequestSchema = z.object({
80
+ organizationId: z.string().describe("组织ID"),
81
+ appName: z.string().describe("应用名"),
82
+ });
83
+ export const GetAppVariableGroupsResponseSchema = z.array(RevisionVariableGroupSchema);
84
+ // Schema for the GetAppVariableGroupsRevision API
85
+ export const GetAppVariableGroupsRevisionRequestSchema = z.object({
86
+ organizationId: z.string().describe("组织ID"),
87
+ appName: z.string().describe("应用名"),
88
+ });
89
+ export const GetAppVariableGroupsRevisionResponseSchema = RevisionSchema;
90
+ /**
91
+ * Get variable groups for an environment
92
+ *
93
+ * @param params - The request parameters
94
+ * @returns The list of variable groups for the environment
95
+ */
96
+ export async function getEnvVariableGroups(params) {
97
+ const { organizationId, appName, envName } = params;
98
+ const finalOrgId = await resolveOrganizationId(organizationId);
99
+ try {
100
+ const url = isRegionEdition()
101
+ ? `/oapi/v1/appstack/apps/${appName}/envs/${envName}/variableGroups`
102
+ : `/oapi/v1/appstack/organizations/${finalOrgId}/apps/${appName}/envs/${envName}/variableGroups`;
103
+ const response = await yunxiaoRequest(url, {
104
+ method: 'GET',
105
+ });
106
+ return GetEnvVariableGroupsResponseSchema.parse(response);
107
+ }
108
+ catch (error) {
109
+ throw error;
110
+ }
111
+ }
112
+ /**
113
+ * Create a variable group
114
+ *
115
+ * @param params - The request parameters
116
+ * @returns The created variable group
117
+ */
118
+ export async function createVariableGroup(params) {
119
+ const { organizationId, appName, ...body } = params;
120
+ const finalOrgId = await resolveOrganizationId(organizationId);
121
+ try {
122
+ const url = isRegionEdition()
123
+ ? `/oapi/v1/appstack/apps/${appName}/variableGroup`
124
+ : `/oapi/v1/appstack/organizations/${finalOrgId}/apps/${appName}/variableGroup`;
125
+ const response = await yunxiaoRequest(url, {
126
+ method: 'POST',
127
+ body: body,
128
+ });
129
+ return CreateVariableGroupResponseSchema.parse(response);
130
+ }
131
+ catch (error) {
132
+ throw error;
133
+ }
134
+ }
135
+ /**
136
+ * Delete a variable group
137
+ *
138
+ * @param params - The request parameters
139
+ * @returns Whether the deletion was successful
140
+ */
141
+ export async function deleteVariableGroup(params) {
142
+ const { organizationId, appName, variableGroupName } = params;
143
+ const finalOrgId = await resolveOrganizationId(organizationId);
144
+ try {
145
+ const url = isRegionEdition()
146
+ ? `/oapi/v1/appstack/apps/${appName}/variableGroup/${variableGroupName}`
147
+ : `/oapi/v1/appstack/organizations/${finalOrgId}/apps/${appName}/variableGroup/${variableGroupName}`;
148
+ const response = await yunxiaoRequest(url, {
149
+ method: 'DELETE',
150
+ });
151
+ return DeleteVariableGroupResponseSchema.parse(response);
152
+ }
153
+ catch (error) {
154
+ throw error;
155
+ }
156
+ }
157
+ /**
158
+ * Get a variable group
159
+ *
160
+ * @param params - The request parameters
161
+ * @returns The variable group
162
+ */
163
+ export async function getVariableGroup(params) {
164
+ const { organizationId, appName, variableGroupName } = params;
165
+ const finalOrgId = await resolveOrganizationId(organizationId);
166
+ try {
167
+ const url = isRegionEdition()
168
+ ? `/oapi/v1/appstack/apps/${appName}/variableGroup/${variableGroupName}`
169
+ : `/oapi/v1/appstack/organizations/${finalOrgId}/apps/${appName}/variableGroup/${variableGroupName}`;
170
+ const response = await yunxiaoRequest(url, {
171
+ method: 'GET',
172
+ });
173
+ return GetVariableGroupResponseSchema.parse(response);
174
+ }
175
+ catch (error) {
176
+ throw error;
177
+ }
178
+ }
179
+ /**
180
+ * Update a variable group
181
+ *
182
+ * @param params - The request parameters
183
+ * @returns The updated variable group
184
+ */
185
+ export async function updateVariableGroup(params) {
186
+ const { organizationId, appName, variableGroupName, ...body } = params;
187
+ const finalOrgId = await resolveOrganizationId(organizationId);
188
+ try {
189
+ const url = isRegionEdition()
190
+ ? `/oapi/v1/appstack/apps/${appName}/variableGroup/${variableGroupName}`
191
+ : `/oapi/v1/appstack/organizations/${finalOrgId}/apps/${appName}/variableGroup/${variableGroupName}`;
192
+ const response = await yunxiaoRequest(url, {
193
+ method: 'PUT',
194
+ body: body,
195
+ });
196
+ return UpdateVariableGroupResponseSchema.parse(response);
197
+ }
198
+ catch (error) {
199
+ throw error;
200
+ }
201
+ }
202
+ /**
203
+ * Get variable groups for an application
204
+ *
205
+ * @param params - The request parameters
206
+ * @returns The list of variable groups for the application
207
+ */
208
+ export async function getAppVariableGroups(params) {
209
+ const { organizationId, appName } = params;
210
+ const finalOrgId = await resolveOrganizationId(organizationId);
211
+ try {
212
+ const url = isRegionEdition()
213
+ ? `/oapi/v1/appstack/apps/${appName}/variableGroups`
214
+ : `/oapi/v1/appstack/organizations/${finalOrgId}/apps/${appName}/variableGroups`;
215
+ const response = await yunxiaoRequest(url, {
216
+ method: 'GET',
217
+ });
218
+ return GetAppVariableGroupsResponseSchema.parse(response);
219
+ }
220
+ catch (error) {
221
+ throw error;
222
+ }
223
+ }
224
+ /**
225
+ * Get the revision of variable groups for an application
226
+ *
227
+ * @param params - The request parameters
228
+ * @returns The revision of variable groups for the application
229
+ */
230
+ export async function getAppVariableGroupsRevision(params) {
231
+ const { organizationId, appName } = params;
232
+ const finalOrgId = await resolveOrganizationId(organizationId);
233
+ try {
234
+ const url = isRegionEdition()
235
+ ? `/oapi/v1/appstack/apps/${appName}/variableGroups:revision`
236
+ : `/oapi/v1/appstack/organizations/${finalOrgId}/apps/${appName}/variableGroups:revision`;
237
+ const response = await yunxiaoRequest(url, {
238
+ method: 'GET',
239
+ });
240
+ return GetAppVariableGroupsRevisionResponseSchema.parse(response);
241
+ }
242
+ catch (error) {
243
+ throw error;
244
+ }
245
+ }
@@ -0,0 +1,157 @@
1
+ import { buildUrl, yunxiaoRequest, isRegionEdition } from "../../common/utils.js";
2
+ import { resolveOrganizationId } from "../organization/organization.js";
3
+ import { CodeupBranchSchema } from "./types.js";
4
+ /**
5
+ * 创建分支
6
+ * @param organizationId
7
+ * @param repositoryId
8
+ * @param branch
9
+ * @param ref
10
+ */
11
+ export async function createBranchFunc(organizationId, repositoryId, branch, ref = "master") {
12
+ const finalOrgId = await resolveOrganizationId(organizationId);
13
+ // Automatically handle unencoded slashes in repositoryId
14
+ if (repositoryId.includes("/")) {
15
+ // Found unencoded slash, automatically URL encode it
16
+ const parts = repositoryId.split("/", 2);
17
+ if (parts.length === 2) {
18
+ const encodedRepoName = encodeURIComponent(parts[1]);
19
+ // Remove + signs from encoding (spaces are encoded as +, but we need %20)
20
+ const formattedEncodedName = encodedRepoName.replace(/\+/g, "%20");
21
+ repositoryId = `${parts[0]}%2F${formattedEncodedName}`;
22
+ }
23
+ }
24
+ const baseUrl = isRegionEdition()
25
+ ? `/oapi/v1/codeup/repositories/${repositoryId}/branches`
26
+ : `/oapi/v1/codeup/organizations/${finalOrgId}/repositories/${repositoryId}/branches`;
27
+ // Build query parameters
28
+ const queryParams = {
29
+ branch: branch,
30
+ ref: ref
31
+ };
32
+ const url = buildUrl(baseUrl, queryParams);
33
+ console.error("createBranchFunc url:" + url);
34
+ const response = await yunxiaoRequest(url, {
35
+ method: "POST",
36
+ });
37
+ return CodeupBranchSchema.parse(response);
38
+ }
39
+ /**
40
+ * 获取分支详情
41
+ * @param organizationId
42
+ * @param repositoryId
43
+ * @param branchName
44
+ */
45
+ export async function getBranchFunc(organizationId, repositoryId, branchName) {
46
+ const finalOrgId = await resolveOrganizationId(organizationId);
47
+ // Automatically handle unencoded slashes in repositoryId
48
+ if (repositoryId.includes("/")) {
49
+ // Found unencoded slash, automatically URL encode it
50
+ const parts = repositoryId.split("/", 2);
51
+ if (parts.length === 2) {
52
+ const encodedRepoName = encodeURIComponent(parts[1]);
53
+ // Remove + signs from encoding (spaces are encoded as +, but we need %20)
54
+ const formattedEncodedName = encodedRepoName.replace(/\+/g, "%20");
55
+ repositoryId = `${parts[0]}%2F${formattedEncodedName}`;
56
+ }
57
+ }
58
+ // Automatically handle unencoded slashes in branchName
59
+ if (branchName.includes("/")) {
60
+ branchName = encodeURIComponent(branchName);
61
+ }
62
+ const url = isRegionEdition()
63
+ ? `/oapi/v1/codeup/repositories/${repositoryId}/branches/${branchName}`
64
+ : `/oapi/v1/codeup/organizations/${finalOrgId}/repositories/${repositoryId}/branches/${branchName}`;
65
+ const response = await yunxiaoRequest(url, {
66
+ method: "GET",
67
+ });
68
+ return CodeupBranchSchema.parse(response);
69
+ }
70
+ /**
71
+ * 删除分支
72
+ * @param organizationId
73
+ * @param repositoryId
74
+ * @param branchName
75
+ */
76
+ export async function deleteBranchFunc(organizationId, repositoryId, branchName) {
77
+ const finalOrgId = await resolveOrganizationId(organizationId);
78
+ // Automatically handle unencoded slashes in repositoryId
79
+ if (repositoryId.includes("/")) {
80
+ // Found unencoded slash, automatically URL encode it
81
+ const parts = repositoryId.split("/", 2);
82
+ if (parts.length === 2) {
83
+ const encodedRepoName = encodeURIComponent(parts[1]);
84
+ // Remove + signs from encoding (spaces are encoded as +, but we need %20)
85
+ const formattedEncodedName = encodedRepoName.replace(/\+/g, "%20");
86
+ repositoryId = `${parts[0]}%2F${formattedEncodedName}`;
87
+ }
88
+ }
89
+ // Automatically handle unencoded slashes in branchName
90
+ if (branchName.includes("/")) {
91
+ branchName = encodeURIComponent(branchName);
92
+ }
93
+ const url = isRegionEdition()
94
+ ? `/oapi/v1/codeup/repositories/${repositoryId}/branches/${branchName}`
95
+ : `/oapi/v1/codeup/organizations/${finalOrgId}/repositories/${repositoryId}/branches/${branchName}`;
96
+ const response = await yunxiaoRequest(url, {
97
+ method: "DELETE",
98
+ });
99
+ return {
100
+ branchName: branchName
101
+ };
102
+ }
103
+ /**
104
+ * 查询分支列表
105
+ * @param organizationId
106
+ * @param repositoryId
107
+ * @param page
108
+ * @param perPage
109
+ * @param sort
110
+ * @param search
111
+ */
112
+ export async function listBranchesFunc(organizationId, repositoryId, page, perPage, sort, // Possible values: name_asc, name_desc, updated_asc, updated_desc
113
+ search) {
114
+ const finalOrgId = await resolveOrganizationId(organizationId);
115
+ console.error("listBranchesFunc page:" + page + " perPage:" + perPage + " sort:" + sort + " search:" + search);
116
+ // Automatically handle unencoded slashes in repositoryId
117
+ if (repositoryId.includes("/")) {
118
+ // Found unencoded slash, automatically URL encode it
119
+ const parts = repositoryId.split("/", 2);
120
+ if (parts.length === 2) {
121
+ const encodedRepoName = encodeURIComponent(parts[1]);
122
+ // Remove + signs from encoding (spaces are encoded as +, but we need %20)
123
+ const formattedEncodedName = encodedRepoName.replace(/\+/g, "%20");
124
+ repositoryId = `${parts[0]}%2F${formattedEncodedName}`;
125
+ }
126
+ }
127
+ const baseUrl = isRegionEdition()
128
+ ? `/oapi/v1/codeup/repositories/${repositoryId}/branches`
129
+ : `/oapi/v1/codeup/organizations/${finalOrgId}/repositories/${repositoryId}/branches`;
130
+ // Build query parameters - use lowercase parameter names as expected by the API
131
+ const queryParams = {};
132
+ if (page !== undefined && page !== null) {
133
+ queryParams.page = page;
134
+ }
135
+ if (perPage !== undefined && perPage !== null) {
136
+ queryParams.perPage = perPage;
137
+ }
138
+ if (sort !== undefined && sort !== null) {
139
+ queryParams.sort = sort;
140
+ }
141
+ if (search !== undefined && search !== null) {
142
+ queryParams.search = search;
143
+ }
144
+ const url = buildUrl(baseUrl, queryParams);
145
+ const response = await yunxiaoRequest(url, {
146
+ method: "GET",
147
+ });
148
+ if (!Array.isArray(response)) {
149
+ return [];
150
+ }
151
+ // Map each branch object and handle null values
152
+ return response.map(branchData => {
153
+ // Filter out null values that would cause parsing errors
154
+ // This is a defensive approach until we update all schemas properly
155
+ return CodeupBranchSchema.parse(branchData);
156
+ });
157
+ }
@@ -0,0 +1,140 @@
1
+ import { yunxiaoRequest, handleRepositoryIdEncoding, isRegionEdition } from "../../common/utils.js";
2
+ import { resolveOrganizationId } from "../organization/organization.js";
3
+ import { ChangeRequestCommentSchema } from "./types.js";
4
+ /**
5
+ * 创建合并请求评论
6
+ * 支持两种评论类型:
7
+ * 1. GLOBAL_COMMENT - 全局评论:对整个合并请求的评论
8
+ * 2. INLINE_COMMENT - 行内评论:针对特定代码行的评论
9
+ *
10
+ * 创建行内评论时,必须提供以下参数:
11
+ * - file_path: 文件路径,例如 '/src/main/java/com/example/MyClass.java'
12
+ * - line_number: 行号,例如 42
13
+ * - from_patchset_biz_id: 比较的起始版本ID(通常是目标分支版本)
14
+ * - to_patchset_biz_id: 比较的目标版本ID(通常是源分支版本)
15
+ *
16
+ * @param organizationId 组织ID,示例:'60d54f3daccf2bbd6659f3ad'
17
+ * @param repositoryId 代码库ID或路径,示例:'2835387' 或 '60de7a6852743a5162b5f957%2FDemoRepo'
18
+ * @param localId 合并请求局部ID,示例:'1'
19
+ * @param comment_type 评论类型:'GLOBAL_COMMENT' 或 'INLINE_COMMENT'
20
+ * @param content 评论内容,长度1-65535,示例:'This is a comment content.'
21
+ * @param draft 是否草稿评论,默认 false
22
+ * @param resolved 是否标记已解决,默认 false
23
+ * @param patchset_biz_id 关联版本ID,示例:'bf117304dfe44d5d9b1132f348edf92e'
24
+ * @param file_path 文件路径(仅行内评论),示例:'/src/main/java/com/example/MyClass.java'
25
+ * @param line_number 行号(仅行内评论),示例:42
26
+ * @param from_patchset_biz_id 起始版本ID(行内评论必传),示例:'bf117304dfe44d5d9b1132f348edf92e'
27
+ * @param to_patchset_biz_id 目标版本ID(行内评论必传),示例:'537367017a9841738ac4269fbf6aacbe'
28
+ * @param parent_comment_biz_id 父评论ID(用于回复),示例:'1d8171cf0cc2453197fae0e0a27d5ece'
29
+ */
30
+ export async function createChangeRequestCommentFunc(organizationId, repositoryId, localId, comment_type, // Possible values: GLOBAL_COMMENT, INLINE_COMMENT
31
+ content, draft, resolved, patchset_biz_id, file_path, line_number, from_patchset_biz_id, to_patchset_biz_id, parent_comment_biz_id) {
32
+ const finalOrgId = await resolveOrganizationId(organizationId);
33
+ const encodedRepoId = handleRepositoryIdEncoding(repositoryId);
34
+ const url = isRegionEdition()
35
+ ? `/oapi/v1/codeup/repositories/${encodedRepoId}/changeRequests/${localId}/comments`
36
+ : `/oapi/v1/codeup/organizations/${finalOrgId}/repositories/${encodedRepoId}/changeRequests/${localId}/comments`;
37
+ // 准备payload
38
+ const payload = {
39
+ comment_type: comment_type,
40
+ content: content,
41
+ draft: draft,
42
+ resolved: resolved,
43
+ patchset_biz_id: patchset_biz_id,
44
+ };
45
+ // 根据评论类型添加必要参数
46
+ if (comment_type === "INLINE_COMMENT") {
47
+ // 检查INLINE_COMMENT必需的参数
48
+ if (!file_path || line_number === undefined || !from_patchset_biz_id || !to_patchset_biz_id) {
49
+ throw new Error("For INLINE_COMMENT, file_path, line_number, from_patchset_biz_id, and to_patchset_biz_id are required");
50
+ }
51
+ payload.file_path = file_path;
52
+ payload.line_number = line_number;
53
+ payload.from_patchset_biz_id = from_patchset_biz_id;
54
+ payload.to_patchset_biz_id = to_patchset_biz_id;
55
+ }
56
+ // 添加可选参数
57
+ if (parent_comment_biz_id) {
58
+ payload.parent_comment_biz_id = parent_comment_biz_id;
59
+ }
60
+ const response = await yunxiaoRequest(url, {
61
+ method: "POST",
62
+ body: payload,
63
+ });
64
+ return ChangeRequestCommentSchema.parse(response);
65
+ }
66
+ /**
67
+ * 获取合并请求评论列表
68
+ * 支持按评论类型、状态、解决状态和文件路径进行过滤
69
+ *
70
+ * @param organizationId 组织ID,示例:'60d54f3daccf2bbd6659f3ad'
71
+ * @param repositoryId 代码库ID或路径,示例:'2835387' 或 '60de7a6852743a5162b5f957%2FDemoRepo'
72
+ * @param localId 合并请求局部ID,示例:'1'
73
+ * @param patchSetBizIds 版本ID列表(可选),示例:['bf117304dfe44d5d9b1132f348edf92e']
74
+ * @param commentType 评论类型:'GLOBAL_COMMENT' 或 'INLINE_COMMENT',默认 'GLOBAL_COMMENT'
75
+ * @param state 评论状态:'OPENED' 或 'DRAFT',默认 'OPENED'
76
+ * @param resolved 是否已解决,默认 false
77
+ * @param filePath 文件路径过滤(仅行内评论),示例:'/src/main/java/com/example/MyClass.java'
78
+ */
79
+ export async function listChangeRequestCommentsFunc(organizationId, repositoryId, localId, patchSetBizIds, commentType = "GLOBAL_COMMENT", // Possible values: GLOBAL_COMMENT, INLINE_COMMENT
80
+ state = "OPENED", // Possible values: OPENED, DRAFT
81
+ resolved = false, filePath) {
82
+ const finalOrgId = await resolveOrganizationId(organizationId);
83
+ const encodedRepoId = handleRepositoryIdEncoding(repositoryId);
84
+ const url = isRegionEdition()
85
+ ? `/oapi/v1/codeup/repositories/${encodedRepoId}/changeRequests/${localId}/comments/list`
86
+ : `/oapi/v1/codeup/organizations/${finalOrgId}/repositories/${encodedRepoId}/changeRequests/${localId}/comments/list`;
87
+ // 准备payload
88
+ const payload = {
89
+ patchSetBizIds: patchSetBizIds || [],
90
+ commentType: commentType,
91
+ state: state,
92
+ resolved: resolved,
93
+ };
94
+ // 添加可选参数
95
+ if (filePath) {
96
+ payload.filePath = filePath;
97
+ }
98
+ const response = await yunxiaoRequest(url, {
99
+ method: "POST",
100
+ body: payload,
101
+ });
102
+ // 确保响应是数组
103
+ if (!Array.isArray(response)) {
104
+ return [];
105
+ }
106
+ // 解析每个评论对象
107
+ return response.map(comment => ChangeRequestCommentSchema.parse(comment));
108
+ }
109
+ /**
110
+ * 更新合并请求评论
111
+ * 可以更新评论的内容和解决状态
112
+ *
113
+ * @param organizationId 组织ID,示例:'60d54f3daccf2bbd6659f3ad'
114
+ * @param repositoryId 代码库ID或路径,示例:'2835387' 或 '60de7a6852743a5162b5f957%2FDemoRepo'
115
+ * @param localId 合并请求局部ID,示例:'1'
116
+ * @param commentBizId 评论 bizId,示例:'bf117304dfe44d5d9b1132f348edf92e'
117
+ * @param content 更新后的评论内容(可选),示例:'your new comment'
118
+ * @param resolved 是否已解决(可选),示例:false
119
+ */
120
+ export async function updateChangeRequestCommentFunc(organizationId, repositoryId, localId, commentBizId, content, resolved) {
121
+ const finalOrgId = await resolveOrganizationId(organizationId);
122
+ const encodedRepoId = handleRepositoryIdEncoding(repositoryId);
123
+ const url = isRegionEdition()
124
+ ? `/oapi/v1/codeup/repositories/${encodedRepoId}/changeRequests/${localId}/comments/${commentBizId}`
125
+ : `/oapi/v1/codeup/organizations/${finalOrgId}/repositories/${encodedRepoId}/changeRequests/${localId}/comments/${commentBizId}`;
126
+ // 准备payload
127
+ const payload = {};
128
+ if (content !== undefined) {
129
+ payload.content = content;
130
+ }
131
+ if (resolved !== undefined) {
132
+ payload.resolved = resolved;
133
+ }
134
+ const response = await yunxiaoRequest(url, {
135
+ method: "PUT",
136
+ body: payload,
137
+ });
138
+ // 根据 swagger 文档,响应格式为 { result: boolean }
139
+ return response;
140
+ }