xuanwu-cli 2.2.0 → 2.3.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.
Files changed (41) hide show
  1. package/.env.test.example +14 -0
  2. package/__tests__/E2E_TEST_REPORT.md +206 -0
  3. package/__tests__/README.md +322 -0
  4. package/__tests__/TEST_SUMMARY.md +215 -0
  5. package/__tests__/global-setup.ts +13 -0
  6. package/__tests__/global-teardown.ts +3 -0
  7. package/__tests__/helpers/test-utils.ts +70 -0
  8. package/__tests__/integration/app.integration.test.ts +363 -0
  9. package/__tests__/integration/auth.integration.test.ts +243 -0
  10. package/__tests__/integration/build.integration.test.ts +215 -0
  11. package/__tests__/integration/e2e.test.ts +267 -0
  12. package/__tests__/integration/service.integration.test.ts +267 -0
  13. package/__tests__/integration/webhook.integration.test.ts +246 -0
  14. package/__tests__/run-e2e.js +360 -0
  15. package/__tests__/setup.ts +9 -0
  16. package/bin/xuanwu +0 -0
  17. package/dist/api/client.d.ts +29 -4
  18. package/dist/api/client.js +113 -29
  19. package/dist/commands/app.js +44 -0
  20. package/dist/commands/auth/login.js +5 -4
  21. package/dist/commands/deploy.js +77 -49
  22. package/dist/commands/env.js +31 -48
  23. package/dist/commands/project.d.ts +5 -0
  24. package/dist/commands/project.js +134 -0
  25. package/dist/commands/svc.js +36 -0
  26. package/dist/config/types.d.ts +1 -0
  27. package/dist/index.js +2 -0
  28. package/jest.config.js +18 -0
  29. package/package.json +10 -2
  30. package/src/api/client.ts +142 -33
  31. package/src/commands/app.ts +53 -0
  32. package/src/commands/auth/login.ts +6 -4
  33. package/src/commands/deploy.ts +93 -48
  34. package/src/commands/env.ts +35 -52
  35. package/src/commands/project.ts +153 -0
  36. package/src/commands/svc.ts +40 -0
  37. package/src/config/types.ts +1 -0
  38. package/src/index.ts +2 -0
  39. package/test/cli-integration.sh +245 -0
  40. package/test/integration.js +3 -3
  41. package/test/integration.sh +252 -0
@@ -0,0 +1,246 @@
1
+ /**
2
+ * Webhook 集成测试
3
+ * 测试 Git 和 Jenkins Webhook
4
+ */
5
+
6
+ import { generateRandomCode } from '../helpers/test-utils'
7
+
8
+ const API_URL = process.env.TEST_API_URL || 'https://i.xuanwu.dev.aimstek.cn'
9
+ const TEST_EMAIL = process.env.TEST_USER_EMAIL || ''
10
+ const TEST_PASSWORD = process.env.TEST_USER_PASSWORD || ''
11
+
12
+ describe('Webhook Integration Tests', () => {
13
+ let testToken: string
14
+ let testAppCode: string
15
+
16
+ beforeAll(async () => {
17
+ if (!TEST_EMAIL || !TEST_PASSWORD) {
18
+ console.warn('Skipping tests: TEST_USER_EMAIL and TEST_USER_PASSWORD not set')
19
+ return
20
+ }
21
+
22
+ const response = await fetch(`${API_URL}/api/cli/auth/login`, {
23
+ method: 'POST',
24
+ headers: { 'Content-Type': 'application/json' },
25
+ body: JSON.stringify({
26
+ email: TEST_EMAIL,
27
+ password: TEST_PASSWORD,
28
+ deviceName: 'Test CLI',
29
+ expiresIn: '30d'
30
+ })
31
+ })
32
+
33
+ if (!response.ok) {
34
+ throw new Error('Failed to login')
35
+ }
36
+
37
+ const data = await response.json() as { token: string }
38
+ testToken = data.token
39
+ })
40
+
41
+ describe('Git Webhook', () => {
42
+ test.skipIf(!TEST_EMAIL || !TEST_PASSWORD)('should handle git push webhook', async () => {
43
+ testAppCode = generateRandomCode('webhook-test')
44
+
45
+ const createResponse = await fetch(`${API_URL}/api/applications`, {
46
+ method: 'POST',
47
+ headers: {
48
+ 'Authorization': `Bearer ${testToken}`,
49
+ 'Content-Type': 'application/json'
50
+ },
51
+ body: JSON.stringify({
52
+ name: 'Webhook测试应用',
53
+ code: testAppCode,
54
+ gitRepo: 'https://github.com/example/test.git'
55
+ })
56
+ })
57
+
58
+ if (!createResponse.ok) {
59
+ console.warn('Failed to create application for webhook test')
60
+ return
61
+ }
62
+
63
+ const pushPayload = {
64
+ ref: 'refs/heads/main',
65
+ before: 'abc123',
66
+ after: 'def456',
67
+ repository: {
68
+ clone_url: 'https://github.com/example/test.git'
69
+ },
70
+ commits: [
71
+ {
72
+ id: 'def456',
73
+ message: 'Test commit',
74
+ author: {
75
+ name: 'Test User',
76
+ email: 'test@example.com'
77
+ }
78
+ }
79
+ ]
80
+ }
81
+
82
+ const response = await fetch(`${API_URL}/api/webhooks/git/${testAppCode}`, {
83
+ method: 'POST',
84
+ headers: {
85
+ 'Content-Type': 'application/json'
86
+ },
87
+ body: JSON.stringify(pushPayload)
88
+ })
89
+
90
+ expect(response.ok).toBeTruthy()
91
+
92
+ const cleanupResponse = await fetch(`${API_URL}/api/cli/apps/${testAppCode}`, {
93
+ method: 'DELETE',
94
+ headers: {
95
+ 'Authorization': `Bearer ${testToken}`
96
+ }
97
+ })
98
+ })
99
+
100
+ test.skipIf(!TEST_EMAIL || !TEST_PASSWORD)('should fail for non-existent application', async () => {
101
+ const response = await fetch(`${API_URL}/api/webhooks/git/non-existent-app`, {
102
+ method: 'POST',
103
+ headers: {
104
+ 'Content-Type': 'application/json'
105
+ },
106
+ body: JSON.stringify({
107
+ ref: 'refs/heads/main',
108
+ commits: []
109
+ })
110
+ })
111
+
112
+ expect(response.ok).toBeFalsy()
113
+ })
114
+
115
+ test.skipIf(!TEST_EMAIL || !TEST_PASSWORD)('should validate webhook signature', async () => {
116
+ testAppCode = generateRandomCode('webhook-test')
117
+
118
+ await fetch(`${API_URL}/api/applications`, {
119
+ method: 'POST',
120
+ headers: {
121
+ 'Authorization': `Bearer ${testToken}`,
122
+ 'Content-Type': 'application/json'
123
+ },
124
+ body: JSON.stringify({
125
+ name: 'Webhook测试应用',
126
+ code: testAppCode,
127
+ gitRepo: 'https://github.com/example/test.git'
128
+ })
129
+ })
130
+
131
+ const payload = JSON.stringify({
132
+ ref: 'refs/heads/main',
133
+ commits: []
134
+ })
135
+
136
+ const crypto = require('crypto')
137
+ const secret = 'webhook-secret'
138
+ const signature = 'sha256=' + crypto.createHmac('sha256', secret).update(payload).digest('hex')
139
+
140
+ const response = await fetch(`${API_URL}/api/webhooks/git/${testAppCode}`, {
141
+ method: 'POST',
142
+ headers: {
143
+ 'Content-Type': 'application/json',
144
+ 'X-Hub-Signature-256': signature
145
+ },
146
+ body: payload
147
+ })
148
+
149
+ await fetch(`${API_URL}/api/cli/apps/${testAppCode}`, {
150
+ method: 'DELETE',
151
+ headers: {
152
+ 'Authorization': `Bearer ${testToken}`
153
+ }
154
+ })
155
+ })
156
+ })
157
+
158
+ describe('Jenkins Webhook', () => {
159
+ test.skipIf(!TEST_EMAIL || !TEST_PASSWORD)('should handle jenkins build complete webhook', async () => {
160
+ testAppCode = generateRandomCode('webhook-test')
161
+
162
+ const createResponse = await fetch(`${API_URL}/api/applications`, {
163
+ method: 'POST',
164
+ headers: {
165
+ 'Authorization': `Bearer ${testToken}`,
166
+ 'Content-Type': 'application/json'
167
+ },
168
+ body: JSON.stringify({
169
+ name: 'Webhook测试应用',
170
+ code: testAppCode,
171
+ gitRepo: 'https://github.com/example/test.git'
172
+ })
173
+ })
174
+
175
+ if (!createResponse.ok) {
176
+ console.warn('Failed to create application for webhook test')
177
+ return
178
+ }
179
+
180
+ const jenkinsPayload = {
181
+ buildNumber: 1,
182
+ status: 'SUCCESS',
183
+ imageTag: 'registry.example.com/app:v1.0.0',
184
+ duration: 120
185
+ }
186
+
187
+ const response = await fetch(`${API_URL}/api/webhooks/jenkins/${testAppCode}`, {
188
+ method: 'POST',
189
+ headers: {
190
+ 'Content-Type': 'application/json'
191
+ },
192
+ body: JSON.stringify(jenkinsPayload)
193
+ })
194
+
195
+ expect(response.ok).toBeTruthy()
196
+
197
+ await fetch(`${API_URL}/api/cli/apps/${testAppCode}`, {
198
+ method: 'DELETE',
199
+ headers: {
200
+ 'Authorization': `Bearer ${testToken}`
201
+ }
202
+ })
203
+ })
204
+
205
+ test.skipIf(!TEST_EMAIL || !TEST_PASSWORD)('should handle jenkins build failed webhook', async () => {
206
+ testAppCode = generateRandomCode('webhook-test')
207
+
208
+ await fetch(`${API_URL}/api/applications`, {
209
+ method: 'POST',
210
+ headers: {
211
+ 'Authorization': `Bearer ${testToken}`,
212
+ 'Content-Type': 'application/json'
213
+ },
214
+ body: JSON.stringify({
215
+ name: 'Webhook测试应用',
216
+ code: testAppCode,
217
+ gitRepo: 'https://github.com/example/test.git'
218
+ })
219
+ })
220
+
221
+ const jenkinsPayload = {
222
+ buildNumber: 1,
223
+ status: 'FAILED',
224
+ error: 'Build failed',
225
+ duration: 60
226
+ }
227
+
228
+ const response = await fetch(`${API_URL}/api/webhooks/jenkins/${testAppCode}`, {
229
+ method: 'POST',
230
+ headers: {
231
+ 'Content-Type': 'application/json'
232
+ },
233
+ body: JSON.stringify(jenkinsPayload)
234
+ })
235
+
236
+ expect(response.ok).toBeTruthy()
237
+
238
+ await fetch(`${API_URL}/api/cli/apps/${testAppCode}`, {
239
+ method: 'DELETE',
240
+ headers: {
241
+ 'Authorization': `Bearer ${testToken}`
242
+ }
243
+ })
244
+ })
245
+ })
246
+ })
@@ -0,0 +1,360 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * E2E 测试独立运行器
4
+ * 不依赖 Jest,直接运行端到端测试
5
+ */
6
+
7
+ const { spawn } = require('child_process')
8
+ const path = require('path')
9
+
10
+ const API_URL = process.env.TEST_API_URL || 'https://i.xuanwu.dev.aimstek.cn'
11
+ const TEST_EMAIL = process.env.TEST_USER_EMAIL || ''
12
+ const TEST_PASSWORD = process.env.TEST_USER_PASSWORD || ''
13
+
14
+ class CLIExecutor {
15
+ constructor() {
16
+ this.cliPath = path.join(__dirname, '..', 'bin', 'xuanwu')
17
+ }
18
+
19
+ async execute(args, options = {}) {
20
+ return new Promise((resolve, reject) => {
21
+ const timeout = options.timeout || 30000
22
+ const env = { ...process.env, ...options.env }
23
+
24
+ const proc = spawn('node', [this.cliPath, ...args], {
25
+ env,
26
+ timeout
27
+ })
28
+
29
+ let stdout = ''
30
+ let stderr = ''
31
+
32
+ proc.stdout.on('data', (data) => {
33
+ stdout += data.toString()
34
+ })
35
+
36
+ proc.stderr.on('data', (data) => {
37
+ stderr += data.toString()
38
+ })
39
+
40
+ proc.on('close', (code) => {
41
+ resolve({
42
+ stdout,
43
+ stderr,
44
+ exitCode: code || 0
45
+ })
46
+ })
47
+
48
+ proc.on('error', (error) => {
49
+ reject(error)
50
+ })
51
+ })
52
+ }
53
+ }
54
+
55
+ function sleep(ms) {
56
+ return new Promise(resolve => setTimeout(resolve, ms))
57
+ }
58
+
59
+ function generateRandomCode(prefix = 'test') {
60
+ return `${prefix}-${Date.now()}-${Math.random().toString(36).substring(7)}`
61
+ }
62
+
63
+ async function runTests() {
64
+ const cli = new CLIExecutor()
65
+ let passed = 0
66
+ let failed = 0
67
+ let skipped = 0
68
+
69
+ console.log('========================================')
70
+ console.log('玄武工厂 CLI E2E 测试')
71
+ console.log('========================================\n')
72
+
73
+ console.log(`API URL: ${API_URL}`)
74
+ console.log(`Test Email: ${TEST_EMAIL || '(未设置)'}\n`)
75
+
76
+ // 测试 1: 帮助命令
77
+ console.log('测试 1: 显示帮助信息')
78
+ try {
79
+ const result = await cli.execute(['--help'])
80
+ if (result.exitCode === 0 && result.stdout.includes('玄武工厂')) {
81
+ console.log('✅ 通过 - 帮助命令正常工作')
82
+ passed++
83
+ } else {
84
+ console.log('❌ 失败 - 帮助命令输出不正确')
85
+ failed++
86
+ }
87
+ } catch (error) {
88
+ console.log('❌ 失败 - 帮助命令执行出错:', error.message)
89
+ failed++
90
+ }
91
+
92
+ // 测试 2: 版本命令
93
+ console.log('\n测试 2: 显示版本信息')
94
+ try {
95
+ const result = await cli.execute(['--version'])
96
+ if (result.exitCode === 0) {
97
+ console.log('✅ 通过 - 版本命令正常工作')
98
+ console.log(` 输出: ${result.stdout.trim()}`)
99
+ passed++
100
+ } else {
101
+ console.log('❌ 失败 - 版本命令返回非零退出码')
102
+ failed++
103
+ }
104
+ } catch (error) {
105
+ console.log('❌ 失败 - 版本命令执行出错:', error.message)
106
+ failed++
107
+ }
108
+
109
+ // 测试 3: 无效命令
110
+ console.log('\n测试 3: 无效命令处理')
111
+ try {
112
+ const result = await cli.execute(['invalid-command'])
113
+ if (result.exitCode !== 0) {
114
+ console.log('✅ 通过 - 无效命令正确返回错误')
115
+ passed++
116
+ } else {
117
+ console.log('❌ 失败 - 无效命令应该返回错误')
118
+ failed++
119
+ }
120
+ } catch (error) {
121
+ console.log('❌ 失败 - 无效命令执行出错:', error.message)
122
+ failed++
123
+ }
124
+
125
+ // 测试 4: 登录(如果提供了凭据)
126
+ if (TEST_EMAIL && TEST_PASSWORD) {
127
+ console.log('\n测试 4: 邮箱密码登录')
128
+ try {
129
+ const result = await cli.execute([
130
+ 'login',
131
+ '--email', TEST_EMAIL,
132
+ '--password', TEST_PASSWORD,
133
+ '--api-url', API_URL,
134
+ '--expires-in', '30d'
135
+ ], { timeout: 60000 })
136
+
137
+ if (result.exitCode === 0 && result.stdout.includes('登录成功')) {
138
+ console.log('✅ 通过 - 登录成功')
139
+ console.log(` 用户: ${TEST_EMAIL}`)
140
+ passed++
141
+ } else {
142
+ console.log('❌ 失败 - 登录失败')
143
+ console.log(` 错误: ${result.stderr || result.stdout}`)
144
+ failed++
145
+ }
146
+ } catch (error) {
147
+ console.log('❌ 失败 - 登录执行出错:', error.message)
148
+ failed++
149
+ }
150
+
151
+ // 测试 5: 查看当前用户
152
+ console.log('\n测试 5: 查看当前用户信息 (whoami)')
153
+ try {
154
+ const result = await cli.execute(['whoami'])
155
+ if (result.exitCode === 0 && result.stdout.includes(TEST_EMAIL)) {
156
+ console.log('✅ 通过 - whoami 命令正常')
157
+ passed++
158
+ } else {
159
+ console.log('❌ 失败 - whoami 命令返回错误')
160
+ failed++
161
+ }
162
+ } catch (error) {
163
+ console.log('❌ 失败 - whoami 执行出错:', error.message)
164
+ failed++
165
+ }
166
+
167
+ // 测试 6: 列出应用
168
+ console.log('\n测试 6: 列出应用')
169
+ try {
170
+ const result = await cli.execute(['app', 'ls'])
171
+ if (result.exitCode === 0) {
172
+ console.log('✅ 通过 - 应用列表命令正常')
173
+ passed++
174
+ } else {
175
+ console.log('❌ 失败 - 应用列表命令返回错误')
176
+ failed++
177
+ }
178
+ } catch (error) {
179
+ console.log('❌ 失败 - 应用列表执行出错:', error.message)
180
+ failed++
181
+ }
182
+
183
+ // 测试 7: 创建应用
184
+ console.log('\n测试 7: 创建应用')
185
+ const testAppCode = generateRandomCode('e2e-test')
186
+ try {
187
+ const result = await cli.execute([
188
+ 'app', 'create',
189
+ '--name', 'E2E测试应用',
190
+ '--code', testAppCode,
191
+ '--git', 'https://github.com/example/test.git'
192
+ ], { timeout: 60000 })
193
+
194
+ if (result.exitCode === 0 && result.stdout.includes('created')) {
195
+ console.log('✅ 通过 - 应用创建成功')
196
+ console.log(` Code: ${testAppCode}`)
197
+ passed++
198
+
199
+ // 测试 8: 获取应用详情
200
+ console.log('\n测试 8: 获取应用详情')
201
+ await sleep(1000)
202
+ const getResult = await cli.execute(['app', 'get', testAppCode])
203
+ if (getResult.exitCode === 0 && getResult.stdout.includes(testAppCode)) {
204
+ console.log('✅ 通过 - 应用详情查询成功')
205
+ passed++
206
+ } else {
207
+ console.log('❌ 失败 - 应用详情查询失败')
208
+ failed++
209
+ }
210
+
211
+ // 测试 9: 更新应用
212
+ console.log('\n测试 9: 更新应用')
213
+ const updateResult = await cli.execute([
214
+ 'app', 'update', testAppCode,
215
+ '--name', '更新后的应用名'
216
+ ])
217
+ if (updateResult.exitCode === 0 && updateResult.stdout.includes('updated')) {
218
+ console.log('✅ 通过 - 应用更新成功')
219
+ passed++
220
+ } else {
221
+ console.log('❌ 失败 - 应用更新失败')
222
+ failed++
223
+ }
224
+
225
+ // 测试 10: 触发构建
226
+ console.log('\n测试 10: 触发构建')
227
+ const buildResult = await cli.execute(['app', 'build', testAppCode], { timeout: 60000 })
228
+ if (buildResult.exitCode === 0 && buildResult.stdout.includes('started')) {
229
+ console.log('✅ 通过 - 构建触发成功')
230
+ passed++
231
+ } else {
232
+ console.log('❌ 失败 - 构建触发失败')
233
+ console.log(` 错误: ${buildResult.stderr || buildResult.stdout}`)
234
+ failed++
235
+ }
236
+
237
+ // 测试 11: 删除应用
238
+ console.log('\n测试 11: 删除应用')
239
+ const deleteResult = await cli.execute(['app', 'delete', testAppCode])
240
+ if (deleteResult.exitCode === 0 && deleteResult.stdout.includes('deleted')) {
241
+ console.log('✅ 通过 - 应用删除成功')
242
+ passed++
243
+ } else {
244
+ console.log('❌ 失败 - 应用删除失败')
245
+ failed++
246
+ }
247
+ } else {
248
+ console.log('❌ 失败 - 应用创建失败')
249
+ console.log(` 错误: ${result.stderr || result.stdout}`)
250
+ failed++
251
+ }
252
+ } catch (error) {
253
+ console.log('❌ 失败 - 应用创建执行出错:', error.message)
254
+ failed++
255
+ }
256
+
257
+ // 测试 12: 列出服务
258
+ console.log('\n测试 12: 列出服务')
259
+ try {
260
+ const result = await cli.execute(['svc', 'ls'])
261
+ if (result.exitCode === 0) {
262
+ console.log('✅ 通过 - 服务列表命令正常')
263
+ passed++
264
+ } else {
265
+ console.log('❌ 失败 - 服务列表命令返回错误')
266
+ failed++
267
+ }
268
+ } catch (error) {
269
+ console.log('❌ 失败 - 服务列表执行出错:', error.message)
270
+ failed++
271
+ }
272
+
273
+ // 测试 13: 列出构建
274
+ console.log('\n测试 13: 列出构建')
275
+ try {
276
+ const result = await cli.execute(['build', 'ls'])
277
+ if (result.exitCode === 0) {
278
+ console.log('✅ 通过 - 构建列表命令正常')
279
+ passed++
280
+ } else {
281
+ console.log('❌ 失败 - 构建列表命令返回错误')
282
+ failed++
283
+ }
284
+ } catch (error) {
285
+ console.log('❌ 失败 - 构建列表执行出错:', error.message)
286
+ failed++
287
+ }
288
+
289
+ // 测试 14: 列出Tokens
290
+ console.log('\n测试 14: 列出Tokens')
291
+ try {
292
+ const result = await cli.execute(['tokens'])
293
+ if (result.exitCode === 0) {
294
+ console.log('✅ 通过 - Tokens列表命令正常')
295
+ passed++
296
+ } else {
297
+ console.log('❌ 失败 - Tokens列表命令返回错误')
298
+ failed++
299
+ }
300
+ } catch (error) {
301
+ console.log('❌ 失败 - Tokens列表执行出错:', error.message)
302
+ failed++
303
+ }
304
+
305
+ // 测试 15: 登出
306
+ console.log('\n测试 15: 登出')
307
+ try {
308
+ const result = await cli.execute(['logout'])
309
+ if (result.exitCode === 0) {
310
+ console.log('✅ 通过 - 登出成功')
311
+ passed++
312
+ } else {
313
+ console.log('❌ 失败 - 登出失败')
314
+ failed++
315
+ }
316
+ } catch (error) {
317
+ console.log('❌ 失败 - 登出执行出错:', error.message)
318
+ failed++
319
+ }
320
+ } else {
321
+ console.log('\n测试 4-15: 跳过(需要 TEST_USER_EMAIL 和 TEST_USER_PASSWORD)')
322
+ skipped += 12
323
+ }
324
+
325
+ // 测试不存在的应用
326
+ console.log('\n测试 16: 查询不存在的应用')
327
+ try {
328
+ const result = await cli.execute(['app', 'get', 'non-existent-app'])
329
+ if (result.exitCode !== 0) {
330
+ console.log('✅ 通过 - 正确返回错误')
331
+ passed++
332
+ } else {
333
+ console.log('❌ 失败 - 应该返回错误')
334
+ failed++
335
+ }
336
+ } catch (error) {
337
+ console.log('✅ 通过 - 正确抛出错误')
338
+ passed++
339
+ }
340
+
341
+ // 输出测试结果
342
+ console.log('\n========================================')
343
+ console.log('测试结果汇总')
344
+ console.log('========================================')
345
+ console.log(`✅ 通过: ${passed}`)
346
+ console.log(`❌ 失败: ${failed}`)
347
+ console.log(`⏭️ 跳过: ${skipped}`)
348
+ console.log(`📊 总计: ${passed + failed + skipped}`)
349
+ console.log(`\n通过率: ${((passed / (passed + failed)) * 100).toFixed(1)}%`)
350
+ console.log('========================================\n')
351
+
352
+ // 退出码
353
+ process.exit(failed > 0 ? 1 : 0)
354
+ }
355
+
356
+ // 运行测试
357
+ runTests().catch(error => {
358
+ console.error('测试运行失败:', error)
359
+ process.exit(1)
360
+ })
@@ -0,0 +1,9 @@
1
+ import '@jest/globals'
2
+
3
+ beforeAll(() => {
4
+ process.env.XW_API_URL = process.env.TEST_API_URL || 'https://i.xuanwu.dev.aimstek.cn'
5
+ })
6
+
7
+ afterEach(() => {
8
+ jest.clearAllMocks()
9
+ })
package/bin/xuanwu CHANGED
File without changes
@@ -4,16 +4,14 @@
4
4
  import { Connection, CLIResult, ServiceInfo, NamespaceInfo, DeployOptions, Application, Build, CreateApplicationDto, UpdateApplicationDto, TriggerBuildOptions } from '../config/types';
5
5
  export declare class APIClient {
6
6
  private client;
7
+ private connection;
8
+ private sessionManager;
7
9
  constructor(connection: Connection);
8
10
  private request;
9
11
  listNamespaces(): Promise<CLIResult<NamespaceInfo[]>>;
10
12
  createNamespace(name: string): Promise<CLIResult<any>>;
11
13
  deleteNamespace(id: string): Promise<CLIResult<void>>;
12
14
  getNamespaceInfo(identifier: string): Promise<CLIResult<any>>;
13
- getProjects(): Promise<CLIResult<any[]>>;
14
- createProject(name: string, description?: string): Promise<CLIResult<any>>;
15
- deleteProject(projectId: string): Promise<CLIResult<void>>;
16
- createNamespaceWithProject(name: string, projectId: string, environment?: string): Promise<CLIResult<any>>;
17
15
  listServices(namespace: string): Promise<CLIResult<ServiceInfo[]>>;
18
16
  getServiceStatus(namespace: string, name: string): Promise<CLIResult<any>>;
19
17
  deleteService(namespace: string, name: string): Promise<CLIResult<void>>;
@@ -35,6 +33,27 @@ export declare class APIClient {
35
33
  deleteApplication(code: string): Promise<CLIResult<void>>;
36
34
  triggerApplicationBuild(code: string, options?: TriggerBuildOptions): Promise<CLIResult<Build>>;
37
35
  listApplicationBuilds(code: string): Promise<CLIResult<Build[]>>;
36
+ listProjects(options?: {
37
+ name?: string;
38
+ code?: string;
39
+ }): Promise<CLIResult<any[]>>;
40
+ getProject(code: string): Promise<CLIResult<any>>;
41
+ createProject(name: string, code: string, description?: string): Promise<CLIResult<any>>;
42
+ deleteProject(code: string): Promise<CLIResult<void>>;
43
+ listEnvironments(options?: {
44
+ project?: string;
45
+ name?: string;
46
+ }): Promise<CLIResult<any[]>>;
47
+ getEnvironment(namespace: string): Promise<CLIResult<any>>;
48
+ createEnvironment(name: string, namespace: string, projectCode?: string): Promise<CLIResult<any>>;
49
+ deleteEnvironment(namespace: string): Promise<CLIResult<void>>;
50
+ deployService(namespace: string, name: string, image: string, options?: {
51
+ projectCode?: string;
52
+ replicas?: number;
53
+ port?: number;
54
+ env?: Record<string, string>;
55
+ }): Promise<CLIResult<any>>;
56
+ listServiceDeployments(namespace: string, name: string): Promise<CLIResult<any>>;
38
57
  listK8sServices(namespace?: string): Promise<CLIResult<any>>;
39
58
  getK8sService(namespace: string, name: string): Promise<CLIResult<any>>;
40
59
  getK8sServiceStatus(namespace: string, name: string): Promise<CLIResult<any>>;
@@ -43,6 +62,11 @@ export declare class APIClient {
43
62
  scaleK8sService(namespace: string, name: string, replicas: number): Promise<CLIResult<any>>;
44
63
  execK8sService(namespace: string, name: string, command: string, podName?: string): Promise<CLIResult<any>>;
45
64
  listK8sServicePods(namespace: string, name: string): Promise<CLIResult<any>>;
65
+ updateK8sService(namespace: string, name: string, options: {
66
+ image?: string;
67
+ replicas?: number;
68
+ port?: number;
69
+ }): Promise<CLIResult<any>>;
46
70
  deleteK8sService(namespace: string, name: string): Promise<CLIResult<void>>;
47
71
  listBuilds(options?: {
48
72
  appCode?: string;
@@ -50,5 +74,6 @@ export declare class APIClient {
50
74
  }): Promise<CLIResult<Build[]>>;
51
75
  getBuild(id: string): Promise<CLIResult<Build>>;
52
76
  cancelBuild(id: string): Promise<CLIResult<void>>;
77
+ getBuildLogs(id: string, follow?: boolean): Promise<CLIResult<any>>;
53
78
  }
54
79
  export declare function createClient(connection: Connection): APIClient;