long-git-cli 1.0.15 → 1.0.18

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.
@@ -0,0 +1,489 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Long CLI - 自动化部署配置</title>
7
+ <link rel="stylesheet" href="/css/main.css" />
8
+ <link rel="stylesheet" href="/css/components.css" />
9
+ </head>
10
+ <body>
11
+ <!-- 页面容器 -->
12
+ <div class="container">
13
+ <!-- 头部 -->
14
+ <header class="header">
15
+ <h1>Long CLI - 自动化部署配置</h1>
16
+ </header>
17
+
18
+ <!-- 主内容区 -->
19
+ <div class="main-content">
20
+ <!-- 侧边栏 -->
21
+ <aside class="sidebar">
22
+ <nav class="nav">
23
+ <a href="#" class="nav-item active" data-page="config">
24
+ <span class="nav-icon"></span>
25
+ <span class="nav-text">基础配置</span>
26
+ </a>
27
+ <a href="#" class="nav-item" data-page="projects">
28
+ <span class="nav-icon"></span>
29
+ <span class="nav-text">项目管理</span>
30
+ </a>
31
+ <a href="#" class="nav-item" data-page="pipeline">
32
+ <span class="nav-icon"></span>
33
+ <span class="nav-text">Pipeline 监听</span>
34
+ </a>
35
+ <a href="#" class="nav-item" data-page="deploy">
36
+ <span class="nav-icon"></span>
37
+ <span class="nav-text">Jenkins 部署</span>
38
+ </a>
39
+ <a href="#" class="nav-item" data-page="full-deploy">
40
+ <span class="nav-icon">⚡</span>
41
+ <span class="nav-text">一键部署</span>
42
+ </a>
43
+ <a href="#" class="nav-item" data-page="history">
44
+ <span class="nav-icon"></span>
45
+ <span class="nav-text">部署历史</span>
46
+ </a>
47
+ </nav>
48
+ </aside>
49
+
50
+ <!-- 内容区域 -->
51
+ <main class="content">
52
+ <!-- 基础配置页面 -->
53
+ <div id="page-config" class="page active">
54
+ <h2>基础配置</h2>
55
+
56
+ <!-- Bitbucket 配置 -->
57
+ <div class="card">
58
+ <div class="card-header">
59
+ <h3 class="card-title">Bitbucket 配置</h3>
60
+ </div>
61
+ <div class="card-body">
62
+ <form id="bitbucket-form">
63
+ <div class="form-group">
64
+ <label class="form-label">Username</label>
65
+ <input
66
+ type="text"
67
+ class="form-input"
68
+ id="bitbucket-username"
69
+ placeholder="your-email@example.com"
70
+ required
71
+ />
72
+ <small style="color: var(--text-secondary); font-size: 0.75rem;">
73
+ 你的 Bitbucket 账号邮箱或用户名
74
+ </small>
75
+ </div>
76
+ <div class="form-group">
77
+ <label class="form-label">API Token / App Password</label>
78
+ <input
79
+ type="password"
80
+ class="form-input"
81
+ id="bitbucket-password"
82
+ placeholder="输入 Bitbucket API Token"
83
+ required
84
+ />
85
+ <small style="color: var(--text-secondary); font-size: 0.75rem;">
86
+ <strong>App Password 已停用</strong>,请使用 <strong>API Token with scopes</strong><br/>
87
+ 在 Bitbucket 个人设置 → API tokens 中创建(需要 repository:read 和 pipeline:read 权限)
88
+ <a href="https://bitbucket.org/account/settings/api-tokens/" target="_blank" style="color: var(--primary-color);">
89
+ (点击前往)
90
+ </a>
91
+ </small>
92
+ </div>
93
+ <div class="form-group">
94
+ <button type="button" class="btn btn-secondary" id="test-bitbucket-btn">
95
+ 测试连接
96
+ </button>
97
+ <button type="button" class="btn btn-primary" id="save-bitbucket-btn" style="margin-left: 0.5rem;">
98
+ 保存 Bitbucket 配置
99
+ </button>
100
+ <span id="bitbucket-status" class="connection-status"></span>
101
+ </div>
102
+ </form>
103
+ </div>
104
+ </div>
105
+
106
+ <!-- Jenkins 配置 -->
107
+ <div class="card">
108
+ <div class="card-header">
109
+ <h3 class="card-title">Jenkins 配置</h3>
110
+ </div>
111
+ <div class="card-body">
112
+ <form id="jenkins-form">
113
+ <div class="form-group">
114
+ <label class="form-label">Jenkins URL</label>
115
+ <input
116
+ type="url"
117
+ class="form-input"
118
+ id="jenkins-url"
119
+ placeholder="https://jenkins.example.com"
120
+ required
121
+ />
122
+ <small style="color: var(--text-secondary); font-size: 0.75rem;">
123
+ Jenkins 服务器地址
124
+ </small>
125
+ </div>
126
+ <div class="form-group">
127
+ <label class="form-label">Username</label>
128
+ <input
129
+ type="text"
130
+ class="form-input"
131
+ id="jenkins-username"
132
+ placeholder="jenkins-user"
133
+ required
134
+ />
135
+ <small style="color: var(--text-secondary); font-size: 0.75rem;">
136
+ 你的 Jenkins 登录用户名
137
+ </small>
138
+ </div>
139
+ <div class="form-group">
140
+ <label class="form-label">API Token</label>
141
+ <input
142
+ type="password"
143
+ class="form-input"
144
+ id="jenkins-token"
145
+ placeholder="输入 Jenkins API Token"
146
+ required
147
+ />
148
+ <small style="color: var(--text-secondary); font-size: 0.75rem;">
149
+ 在 Jenkins 用户设置 → Configure → API Token 中生成
150
+ </small>
151
+ </div>
152
+ <div class="form-group">
153
+ <button type="button" class="btn btn-secondary" id="test-jenkins-btn">
154
+ 测试连接
155
+ </button>
156
+ <button type="button" class="btn btn-primary" id="save-jenkins-btn" style="margin-left: 0.5rem;">
157
+ 保存 Jenkins 配置
158
+ </button>
159
+ <span id="jenkins-status" class="connection-status"></span>
160
+ </div>
161
+ </form>
162
+ </div>
163
+ </div>
164
+ </div>
165
+
166
+ <!-- 项目管理页面 -->
167
+ <div id="page-projects" class="page">
168
+ <div class="flex justify-between items-center mb-lg">
169
+ <h2 style="margin: 0;">项目管理</h2>
170
+ <button type="button" class="btn btn-primary" id="add-project-btn">
171
+ + 添加项目
172
+ </button>
173
+ </div>
174
+
175
+ <!-- 项目列表 -->
176
+ <div id="projects-list">
177
+ <!-- 项目卡片将动态添加 -->
178
+ </div>
179
+
180
+ <!-- 空状态 -->
181
+ <div id="projects-empty" class="empty-state hidden">
182
+ <div class="empty-state-icon"></div>
183
+ <div class="empty-state-title">还没有项目</div>
184
+ <div class="empty-state-description">
185
+ 点击"添加项目"按钮创建第一个项目配置
186
+ </div>
187
+ </div>
188
+ </div>
189
+
190
+ <!-- Pipeline 监听测试页面 -->
191
+ <div id="page-pipeline" class="page">
192
+ <h2>Pipeline 监听测试</h2>
193
+
194
+ <div class="card">
195
+ <div class="card-header">
196
+ <h3 class="card-title">Bitbucket Pipeline 测试</h3>
197
+ </div>
198
+ <div class="card-body">
199
+ <form id="pipeline-form">
200
+ <div class="form-group">
201
+ <label class="form-label">项目路径</label>
202
+ <button type="button" class="btn btn-primary" id="pipeline-select-folder-btn" style="width: 100%;">
203
+ 选择项目文件夹
204
+ </button>
205
+ <input type="hidden" id="pipeline-project-path" />
206
+ <input type="hidden" id="pipeline-workspace" />
207
+ <input type="hidden" id="pipeline-repo-slug" />
208
+
209
+ <div id="pipeline-path-info" style="display: none; margin-top: 0.75rem;">
210
+ <div style="padding: 0.75rem; background-color: var(--bg-secondary); border-radius: var(--radius-md); border: 1px solid var(--border-color);">
211
+ <div style="color: var(--text-primary); font-size: 0.875rem; margin-bottom: 0.5rem;">
212
+ <strong>路径:</strong> <span id="pipeline-display-path" style="color: var(--text-secondary);"></span>
213
+ </div>
214
+ <div id="pipeline-git-info" style="display: none; padding-top: 0.5rem; border-top: 1px solid var(--border-color);">
215
+ <div style="color: var(--text-primary); font-size: 0.875rem;">
216
+ <strong>Bitbucket:</strong>
217
+ <span id="pipeline-display-workspace" style="color: var(--text-secondary);"></span>
218
+ <span style="color: var(--text-secondary);"> / </span>
219
+ <span id="pipeline-display-repo-slug" style="color: var(--text-secondary);"></span>
220
+ </div>
221
+ </div>
222
+ </div>
223
+ </div>
224
+ </div>
225
+
226
+ <div class="form-group">
227
+ <label class="form-label">Tag 格式</label>
228
+ <input
229
+ type="text"
230
+ class="form-input"
231
+ id="pipeline-tag-format"
232
+ placeholder="test-v00.00.0000"
233
+ required
234
+ />
235
+ <small style="color: var(--text-secondary); font-size: 0.75rem;">
236
+ 输入 tag 格式,系统会自动获取该格式的最新 tag 并叠加(如 test-v00.00.0001 → test-v00.00.0002)
237
+ </small>
238
+ </div>
239
+
240
+ <div class="form-group">
241
+ <label class="form-label">查询固定 Tag(可选)</label>
242
+ <input
243
+ type="text"
244
+ class="form-input"
245
+ id="pipeline-fixed-tag"
246
+ placeholder="test-v00.00.0262"
247
+ />
248
+ <small style="color: var(--text-secondary); font-size: 0.75rem;">
249
+ 输入已存在的 tag 名称,用于查询构建状态(不会创建新 tag)
250
+ </small>
251
+ </div>
252
+
253
+ <div class="form-group">
254
+ <button type="button" class="btn btn-secondary" id="save-pipeline-config-btn">
255
+ 保存配置
256
+ </button>
257
+ <button type="button" class="btn btn-primary" id="pipeline-test-btn" style="margin-left: 0.5rem;">
258
+ 创建 Tag 并监听
259
+ </button>
260
+ <button type="button" class="btn btn-primary" id="pipeline-query-btn" style="margin-left: 0.5rem;">
261
+ 查询固定 Tag
262
+ </button>
263
+ </div>
264
+ </form>
265
+
266
+ <!-- Pipeline 状态显示 -->
267
+ <div id="pipeline-status" style="display: none; margin-top: 1.5rem;">
268
+ <!-- 状态将动态显示 -->
269
+ </div>
270
+ </div>
271
+ </div>
272
+
273
+ <!-- 使用说明 -->
274
+ <div class="card mt-lg">
275
+ <div class="card-header">
276
+ <h3 class="card-title">使用说明</h3>
277
+ </div>
278
+ <div class="card-body">
279
+ <ol style="color: var(--text-secondary); line-height: 1.8;">
280
+ <li>确保已在"基础配置"中配置了 Bitbucket API Token</li>
281
+ <li>点击"选择项目文件夹",系统会自动解析 Git 仓库信息</li>
282
+ <li>输入 tag 格式(如 test-v00.00.0000)</li>
283
+ <li>点击"保存配置"保存当前配置,下次打开会自动填充</li>
284
+ <li>点击"创建 Tag 并监听 Pipeline"按钮</li>
285
+ <li>系统将自动获取该格式的最新 tag,叠加后创建新 tag 并推送</li>
286
+ <li>然后监听 Bitbucket Pipeline 执行状态,直到完成或超时(30 分钟)</li>
287
+ </ol>
288
+ </div>
289
+ </div>
290
+ </div>
291
+
292
+ <!-- Jenkins 部署测试页面 -->
293
+ <div id="page-deploy" class="page">
294
+ <h2>Jenkins 部署测试</h2>
295
+
296
+ <div class="card">
297
+ <div class="card-header">
298
+ <h3 class="card-title">Jenkins 部署配置</h3>
299
+ </div>
300
+ <div class="card-body">
301
+ <form id="deploy-form">
302
+ <div class="form-group">
303
+ <label class="form-label">Jenkins URL</label>
304
+ <input
305
+ type="url"
306
+ class="form-input"
307
+ id="deploy-jenkins-url"
308
+ placeholder="https://jenkins.example.com"
309
+ required
310
+ />
311
+ <small style="color: var(--text-secondary); font-size: 0.75rem;">
312
+ Jenkins 服务器地址
313
+ </small>
314
+ </div>
315
+
316
+ <div class="form-group">
317
+ <label class="form-label">Jenkins Username</label>
318
+ <input
319
+ type="text"
320
+ class="form-input"
321
+ id="deploy-jenkins-username"
322
+ placeholder="jenkins-user"
323
+ required
324
+ />
325
+ <small style="color: var(--text-secondary); font-size: 0.75rem;">
326
+ Jenkins 登录用户名
327
+ </small>
328
+ </div>
329
+
330
+ <div class="form-group">
331
+ <label class="form-label">Jenkins API Token</label>
332
+ <input
333
+ type="password"
334
+ class="form-input"
335
+ id="deploy-jenkins-token"
336
+ placeholder="输入 Jenkins API Token"
337
+ required
338
+ />
339
+ <small style="color: var(--text-secondary); font-size: 0.75rem;">
340
+ 在 Jenkins 用户设置 → Configure → API Token 中生成
341
+ </small>
342
+ </div>
343
+
344
+ <div class="form-group">
345
+ <label class="form-label">Job 路径</label>
346
+ <input
347
+ type="text"
348
+ class="form-input"
349
+ id="deploy-job-name"
350
+ placeholder="app-test-hy-service/frontend-msg-admin4"
351
+ required
352
+ />
353
+ <small style="color: var(--text-secondary); font-size: 0.75rem;">
354
+ Jenkins Job 的完整路径(包含文件夹)
355
+ </small>
356
+ </div>
357
+
358
+ <div class="form-group">
359
+ <button type="button" class="btn btn-secondary" id="save-deploy-config-btn">
360
+ 保存配置
361
+ </button>
362
+ <button type="button" class="btn btn-primary" id="deploy-btn" style="margin-left: 0.5rem;">
363
+ 测试部署
364
+ </button>
365
+ </div>
366
+ </form>
367
+
368
+ <!-- 部署状态显示 -->
369
+ <div id="deploy-status" style="display: none; margin-top: 1.5rem;">
370
+ <!-- 状态将动态显示 -->
371
+ </div>
372
+ </div>
373
+ </div>
374
+
375
+ <!-- 使用说明 -->
376
+ <div class="card mt-lg">
377
+ <div class="card-header">
378
+ <h3 class="card-title">使用说明</h3>
379
+ </div>
380
+ <div class="card-body">
381
+ <ol style="color: var(--text-secondary); line-height: 1.8;">
382
+ <li>填写 Jenkins 服务器地址、用户名和 API Token</li>
383
+ <li>输入 Jenkins Job 完整路径(如:app-test-hy-service/frontend-msg-admin4)</li>
384
+ <li>点击"保存配置"保存当前配置,下次打开会自动填充</li>
385
+ <li>点击"测试部署"按钮触发 Jenkins 构建</li>
386
+ <li>系统将自动传递 action=approve 参数,并使用最新的构建</li>
387
+ <li>构建完成后会显示结果(成功或失败)</li>
388
+ </ol>
389
+ </div>
390
+ </div>
391
+ </div>
392
+
393
+ <!-- 完整部署流程页面 -->
394
+ <div id="page-full-deploy" class="page">
395
+ <h2>一键部署</h2>
396
+
397
+ <div class="card">
398
+ <div class="card-header">
399
+ <h3 class="card-title">完整部署流程</h3>
400
+ </div>
401
+ <div class="card-body">
402
+ <p style="color: var(--text-secondary); margin-bottom: 1.5rem;">
403
+ 此功能将执行完整的部署流程:创建 Tag → 推送 Tag → 监听 Pipeline → 触发 Jenkins 部署
404
+ </p>
405
+
406
+ <form id="full-deploy-form">
407
+ <div class="form-group">
408
+ <label class="form-label">选择项目</label>
409
+ <select class="form-input" id="full-deploy-project" required>
410
+ <option value="">请选择项目</option>
411
+ </select>
412
+ </div>
413
+
414
+ <div class="form-group">
415
+ <label class="form-label">选择环境</label>
416
+ <select class="form-input" id="full-deploy-environment" required>
417
+ <option value="">请先选择项目</option>
418
+ </select>
419
+ </div>
420
+
421
+ <div class="form-group">
422
+ <button type="button" class="btn btn-primary" id="full-deploy-btn">
423
+ 开始部署
424
+ </button>
425
+ </div>
426
+ </form>
427
+
428
+ <!-- 部署状态显示 -->
429
+ <div id="full-deploy-status" style="display: none; margin-top: 1.5rem;">
430
+ <!-- 状态将动态显示 -->
431
+ </div>
432
+ </div>
433
+ </div>
434
+
435
+ <!-- 使用说明 -->
436
+ <div class="card mt-lg">
437
+ <div class="card-header">
438
+ <h3 class="card-title">使用说明</h3>
439
+ </div>
440
+ <div class="card-body">
441
+ <ol style="color: var(--text-secondary); line-height: 1.8;">
442
+ <li>确保已在"基础配置"中配置了 Bitbucket 和 Jenkins 凭证</li>
443
+ <li>确保已在"项目管理"中添加了项目和环境配置</li>
444
+ <li>选择要部署的项目和环境</li>
445
+ <li>选择是否创建新 tag(如果不创建,需要输入现有 tag 名称)</li>
446
+ <li>点击"开始部署"按钮</li>
447
+ <li>系统将自动执行完整的部署流程,并显示实时进度</li>
448
+ </ol>
449
+ </div>
450
+ </div>
451
+ </div>
452
+
453
+ <!-- 部署历史页面 -->
454
+ <div id="page-history" class="page">
455
+ <h2>部署历史</h2>
456
+
457
+ <!-- 空状态 -->
458
+ <div class="empty-state">
459
+ <div class="empty-state-icon"></div>
460
+ <div class="empty-state-title">部署历史功能</div>
461
+ <div class="empty-state-description">
462
+ 此功能将在后续版本中实现,用于查看历史部署记录
463
+ </div>
464
+ </div>
465
+ </div>
466
+ </main>
467
+ </div>
468
+ </div>
469
+
470
+ <!-- Toast 容器 -->
471
+ <div id="toast-container"></div>
472
+
473
+ <!-- Loading 遮罩 -->
474
+ <div id="loading-overlay" class="loading-overlay hidden">
475
+ <div class="loading-spinner"></div>
476
+ <p class="loading-text">加载中...</p>
477
+ </div>
478
+
479
+ <!-- 脚本 -->
480
+ <script src="/js/api.js"></script>
481
+ <script src="/js/components.js"></script>
482
+ <script src="/js/config-page.js"></script>
483
+ <script src="/js/projects-page.js"></script>
484
+ <script src="/js/pipeline-page.js"></script>
485
+ <script src="/js/deploy-page.js"></script>
486
+ <script src="/js/full-deploy-page.js"></script>
487
+ <script src="/js/app.js"></script>
488
+ </body>
489
+ </html>
@@ -0,0 +1,116 @@
1
+ /**
2
+ * API 调用封装
3
+ * 使用 fetch API 进行 HTTP 请求
4
+ */
5
+
6
+ const API = {
7
+ /**
8
+ * 基础 URL
9
+ */
10
+ baseURL: "/api",
11
+
12
+ /**
13
+ * 发送 GET 请求
14
+ */
15
+ async get(endpoint) {
16
+ try {
17
+ const response = await fetch(`${this.baseURL}${endpoint}`, {
18
+ method: "GET",
19
+ headers: {
20
+ "Content-Type": "application/json",
21
+ },
22
+ });
23
+
24
+ if (!response.ok) {
25
+ const error = await response.json();
26
+ throw new Error(error.error || "请求失败");
27
+ }
28
+
29
+ return await response.json();
30
+ } catch (error) {
31
+ console.error("GET 请求失败:", error);
32
+ throw error;
33
+ }
34
+ },
35
+
36
+ /**
37
+ * 发送 POST 请求
38
+ */
39
+ async post(endpoint, data) {
40
+ try {
41
+ const response = await fetch(`${this.baseURL}${endpoint}`, {
42
+ method: "POST",
43
+ headers: {
44
+ "Content-Type": "application/json",
45
+ },
46
+ body: JSON.stringify(data),
47
+ });
48
+
49
+ if (!response.ok) {
50
+ const error = await response.json();
51
+ throw new Error(error.error || "请求失败");
52
+ }
53
+
54
+ return await response.json();
55
+ } catch (error) {
56
+ console.error("POST 请求失败:", error);
57
+ throw error;
58
+ }
59
+ },
60
+
61
+ /**
62
+ * 发送 PUT 请求
63
+ */
64
+ async put(endpoint, data) {
65
+ try {
66
+ const response = await fetch(`${this.baseURL}${endpoint}`, {
67
+ method: "PUT",
68
+ headers: {
69
+ "Content-Type": "application/json",
70
+ },
71
+ body: JSON.stringify(data),
72
+ });
73
+
74
+ if (!response.ok) {
75
+ const error = await response.json();
76
+ throw new Error(error.error || "请求失败");
77
+ }
78
+
79
+ return await response.json();
80
+ } catch (error) {
81
+ console.error("PUT 请求失败:", error);
82
+ throw error;
83
+ }
84
+ },
85
+
86
+ /**
87
+ * 发送 DELETE 请求
88
+ */
89
+ async delete(endpoint) {
90
+ try {
91
+ const response = await fetch(`${this.baseURL}${endpoint}`, {
92
+ method: "DELETE",
93
+ headers: {
94
+ "Content-Type": "application/json",
95
+ },
96
+ });
97
+
98
+ if (!response.ok) {
99
+ const error = await response.json();
100
+ throw new Error(error.error || "请求失败");
101
+ }
102
+
103
+ return await response.json();
104
+ } catch (error) {
105
+ console.error("DELETE 请求失败:", error);
106
+ throw error;
107
+ }
108
+ },
109
+
110
+ /**
111
+ * 健康检查
112
+ */
113
+ async health() {
114
+ return this.get("/health");
115
+ },
116
+ };