zt-devops-cli 0.1.4__tar.gz → 0.1.6__tar.gz

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,110 @@
1
+ Metadata-Version: 2.4
2
+ Name: zt-devops-cli
3
+ Version: 0.1.6
4
+ Summary: DevOps 平台迭代管理 CLI
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: playwright>=1.40.0
8
+ Requires-Dist: requests>=2.31.0
9
+ Requires-Dist: click>=8.1.0
10
+ Requires-Dist: pyyaml>=6.0
11
+
12
+ # DevOps CLI
13
+
14
+ 蓝鲸 DevOps 平台迭代管理命令行工具。
15
+
16
+ ## 打包
17
+ ```bash
18
+ python -m pip install --upgrade build twine
19
+ python -m build
20
+ twine upload dist/*
21
+ ```
22
+
23
+ ## 安装
24
+ * 源码安装
25
+ ```bash
26
+ pip install -e .
27
+ ```
28
+
29
+ * pip安装
30
+ ```bash
31
+ pipx install zt-devops-cli
32
+ ```
33
+
34
+ ## 使用
35
+
36
+ ### 登陆
37
+
38
+ 首次运行时会自动打开浏览器,请登录蓝鲸 DevOps。登录成功后 cookie 会缓存到本地。
39
+ ```bash
40
+ zt-devops-cli login
41
+ ```
42
+
43
+ ### 空间管理
44
+
45
+ ```bash
46
+ zt-devops-cli project list
47
+ ```
48
+
49
+ ### ZTeam 项目列表
50
+ ```bash
51
+ zt-devops-cli zteam-project list --project f39507
52
+ ```
53
+
54
+ ### 迭代管理
55
+
56
+ #### 迭代列表
57
+ ```bash
58
+ zt-devops-cli sprint list --project k64352
59
+ ```
60
+
61
+ #### 创建迭代
62
+
63
+ ```bash
64
+ zt-devops-cli sprint create --project k64352 \
65
+ --title "迭代名称" \
66
+ --start-date 2026-04-04 \
67
+ --end-date 2026-05-30 \
68
+ --purpose "迭代目标"
69
+ ```
70
+
71
+ #### 启用迭代
72
+ ```bash
73
+ zt-devops-cli sprint start --project k64352 --sprint-id <id>
74
+ ```
75
+
76
+ #### 删除迭代
77
+ ```bash
78
+ zt-devops-cli sprint delete --project k64352 --sprint-id <id>
79
+ ```
80
+
81
+ #### 完成迭代
82
+ ```bash
83
+ zt-devops-cli sprint done --project k64352 --sprint-id <id>
84
+ ```
85
+
86
+ ### 任务管理
87
+
88
+ #### 查询任务列表(TASK)
89
+ ```bash
90
+ zt-devops-cli task list --project f39507 \
91
+ --start-date 2026-04-01 \
92
+ --end-date 2026-04-30 \
93
+ --creator zt07905
94
+ ```
95
+
96
+ #### 新增任务(TASK)
97
+ ```bash
98
+ zt-devops-cli task create --project <project-id> \ # 通过 project list 获取
99
+ --title "<任务标题>" \
100
+ --owner <工号> \
101
+ --estimate-start <预计开始时间: yyyy-MM-dd> \
102
+ --estimate-end <预计完成时间: yyyy-MM-dd> \
103
+ --origin-hours 8.00 \ # 预估工时
104
+ --remain-hours 8.00 \ # 实际工时
105
+ --zteam-project-id <zteam-project-id> # 通过 zteam-project list 获取
106
+ ```
107
+
108
+ ## 配置
109
+ - cookie 缓存:`~/.zt-devops-cli/cookies.json`
110
+ - 配置文件:`~/.zt-devops-cli/config.yaml`
@@ -0,0 +1,99 @@
1
+ # DevOps CLI
2
+
3
+ 蓝鲸 DevOps 平台迭代管理命令行工具。
4
+
5
+ ## 打包
6
+ ```bash
7
+ python -m pip install --upgrade build twine
8
+ python -m build
9
+ twine upload dist/*
10
+ ```
11
+
12
+ ## 安装
13
+ * 源码安装
14
+ ```bash
15
+ pip install -e .
16
+ ```
17
+
18
+ * pip安装
19
+ ```bash
20
+ pipx install zt-devops-cli
21
+ ```
22
+
23
+ ## 使用
24
+
25
+ ### 登陆
26
+
27
+ 首次运行时会自动打开浏览器,请登录蓝鲸 DevOps。登录成功后 cookie 会缓存到本地。
28
+ ```bash
29
+ zt-devops-cli login
30
+ ```
31
+
32
+ ### 空间管理
33
+
34
+ ```bash
35
+ zt-devops-cli project list
36
+ ```
37
+
38
+ ### ZTeam 项目列表
39
+ ```bash
40
+ zt-devops-cli zteam-project list --project f39507
41
+ ```
42
+
43
+ ### 迭代管理
44
+
45
+ #### 迭代列表
46
+ ```bash
47
+ zt-devops-cli sprint list --project k64352
48
+ ```
49
+
50
+ #### 创建迭代
51
+
52
+ ```bash
53
+ zt-devops-cli sprint create --project k64352 \
54
+ --title "迭代名称" \
55
+ --start-date 2026-04-04 \
56
+ --end-date 2026-05-30 \
57
+ --purpose "迭代目标"
58
+ ```
59
+
60
+ #### 启用迭代
61
+ ```bash
62
+ zt-devops-cli sprint start --project k64352 --sprint-id <id>
63
+ ```
64
+
65
+ #### 删除迭代
66
+ ```bash
67
+ zt-devops-cli sprint delete --project k64352 --sprint-id <id>
68
+ ```
69
+
70
+ #### 完成迭代
71
+ ```bash
72
+ zt-devops-cli sprint done --project k64352 --sprint-id <id>
73
+ ```
74
+
75
+ ### 任务管理
76
+
77
+ #### 查询任务列表(TASK)
78
+ ```bash
79
+ zt-devops-cli task list --project f39507 \
80
+ --start-date 2026-04-01 \
81
+ --end-date 2026-04-30 \
82
+ --creator zt07905
83
+ ```
84
+
85
+ #### 新增任务(TASK)
86
+ ```bash
87
+ zt-devops-cli task create --project <project-id> \ # 通过 project list 获取
88
+ --title "<任务标题>" \
89
+ --owner <工号> \
90
+ --estimate-start <预计开始时间: yyyy-MM-dd> \
91
+ --estimate-end <预计完成时间: yyyy-MM-dd> \
92
+ --origin-hours 8.00 \ # 预估工时
93
+ --remain-hours 8.00 \ # 实际工时
94
+ --zteam-project-id <zteam-project-id> # 通过 zteam-project list 获取
95
+ ```
96
+
97
+ ## 配置
98
+ - cookie 缓存:`~/.zt-devops-cli/cookies.json`
99
+ - 配置文件:`~/.zt-devops-cli/config.yaml`
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "zt-devops-cli"
7
- version = "0.1.4"
7
+ version = "0.1.6"
8
8
  description = "DevOps 平台迭代管理 CLI"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -0,0 +1,165 @@
1
+ """API 请求封装"""
2
+ import json as json_mod
3
+ import requests
4
+ from typing import Optional
5
+
6
+ from .auth import get_auth_cookies, get_auth_headers
7
+ from .config import config
8
+
9
+
10
+ class DevOpsAPI:
11
+ """DevOps API 客户端"""
12
+
13
+ def __init__(self, project_id: str):
14
+ self.project_id = project_id
15
+ self.base_url = config.BASE_URL
16
+
17
+ def _request(self, method: str, path: str, **kwargs) -> dict:
18
+ """发送 API 请求"""
19
+ cookies = get_auth_cookies()
20
+ headers = get_auth_headers(cookies, self.project_id)
21
+
22
+ url = f"{self.base_url}/{path}"
23
+
24
+ # 处理 data 参数
25
+ if "data" in kwargs:
26
+ kwargs["json"] = kwargs.pop("data")
27
+
28
+ # #############################################
29
+ # # 打印 curl 命令
30
+ # curl_parts = [f"curl -X {method}"]
31
+ # for k, v in headers.items():
32
+ # curl_parts.append(f"-H '{k}: {v}'")
33
+ # if "json" in kwargs:
34
+ # curl_parts.append(f"-d '{json_mod.dumps(kwargs['json'], ensure_ascii=False)}'")
35
+ # curl_parts.append(f"'{url}'")
36
+ # print(" ".join(curl_parts))
37
+ # #############################################
38
+
39
+ response = requests.request(
40
+ method=method,
41
+ url=url,
42
+ headers=headers,
43
+ cookies=cookies,
44
+ **kwargs
45
+ )
46
+
47
+ if response.status_code >= 400:
48
+ raise Exception(f"API 错误: {response.status_code} {response.text}")
49
+
50
+ return response.json()
51
+
52
+ # ========== 迭代操作 ==========
53
+
54
+ def create_sprint(
55
+ self,
56
+ title: str,
57
+ start_date: str,
58
+ end_date: str,
59
+ purpose: str = "",
60
+ test_start_date: Optional[str] = None,
61
+ test_end_date: Optional[str] = None,
62
+ development_pic: str = "",
63
+ test_pic: str = "",
64
+ acceptance_pic: str = "",
65
+ ) -> dict:
66
+ """创建迭代"""
67
+ data = {
68
+ "title": title,
69
+ "startDate": start_date,
70
+ "endDate": end_date,
71
+ "purpose": purpose,
72
+ "daterange": [f"{start_date}T16:00:00.000Z", f"{end_date}T16:00:00.000Z"],
73
+ "reviewTime": "",
74
+ "testStartDate": test_start_date or start_date,
75
+ "testEndDate": test_end_date or end_date,
76
+ "developmentPic": development_pic,
77
+ "testPic": test_pic,
78
+ "acceptancePic": acceptance_pic,
79
+ "excludeTime": "",
80
+ "state": "ACTIVE",
81
+ }
82
+ return self._request("POST", f"/ms/vteam/api/user/issue_sprint/{self.project_id}", data=data)
83
+
84
+ def start_sprint(self, sprint_data: dict) -> dict:
85
+ """启用迭代"""
86
+ return self._request("PUT", f"/ms/vteam/api/user/issue_sprint/{self.project_id}/start", data=sprint_data)
87
+
88
+ def delete_sprint(self, sprint_id: str) -> dict:
89
+ """删除迭代"""
90
+ return self._request("DELETE", f"/ms/vteam/api/user/issue_sprint/{self.project_id}/{sprint_id}")
91
+
92
+ def done_sprint(self, sprint_id: str) -> dict:
93
+ """完成迭代"""
94
+ return self._request("PUT", f"/ms/vteam/api/user/issue_sprint/{self.project_id}/complete/{sprint_id}")
95
+
96
+ def list_sprints(self) -> dict:
97
+ """查询迭代列表"""
98
+ return self._request("GET",
99
+ f"/ms/vteam/api/user/issue_sprint/{self.project_id}/flat?num=1&count=1&size=20&content=&start_time=&end_time=&state=ACTIVE%2CNOT_STARTED&sort_field=CREATED_TIME&sort_rule=DESC")
100
+
101
+ def list_projects(self) -> dict:
102
+ """查询项目列表"""
103
+ return self._request("GET",
104
+ f"/ms/projectmanager/api/user/project/cw/selectByType?showTree=false&haveUser=false")
105
+
106
+ def list_zteam_projects(self) -> dict:
107
+ """查询 ZTeam 项目列表(任务字段选项)"""
108
+ return self._request(
109
+ "GET",
110
+ f"/ms/vteam/api/user/issue_field_value/{self.project_id}/option/5abdcb4c783e11edbef4fa819a160800?all=false&classify=TASK",
111
+ )
112
+
113
+ # ========== 任务操作 ==========
114
+
115
+ def create_task(
116
+ self,
117
+ title: str,
118
+ model_type_id: str,
119
+ priority: str = "CENTRAL",
120
+ editor_type: str = "MARKDOWN",
121
+ desc: str = "",
122
+ parent_id: str = "",
123
+ demand_classify: str = "-1",
124
+ instance_values: Optional[list] = None,
125
+ ) -> dict:
126
+ """创建 TASK 任务"""
127
+ data = {
128
+ "title": title,
129
+ "modelTypeId": model_type_id,
130
+ "priority": priority,
131
+ "editorType": editor_type,
132
+ "desc": desc,
133
+ "parentId": parent_id,
134
+ "relationIssue": {},
135
+ "demandClassify": demand_classify,
136
+ "fileVO": [],
137
+ "labelId": [],
138
+ "instanceValue": instance_values or [],
139
+ }
140
+ return self._request("POST", f"/ms/vteam/api/user/issue/{self.project_id}", data=data)
141
+
142
+ def list_tasks(
143
+ self,
144
+ creator: Optional[str] = None,
145
+ start_date: Optional[str] = None,
146
+ end_date: Optional[str] = None,
147
+ num: int = 1,
148
+ size: int = 20,
149
+ remember: bool = False,
150
+ ) -> dict:
151
+ """按条件查询 TASK 列表"""
152
+
153
+ data = [ {"name": "exclude", "value": []}]
154
+
155
+ if creator:
156
+ data.insert(0, {"name": "createUser", "value": [creator]})
157
+ if start_date and end_date:
158
+ data.insert(0, {"name": "estimate_start_time", "value": [start_date, end_date]})
159
+ data.insert(0, {"name": "estimate_end_time", "value": [start_date, end_date]})
160
+ remember_value = str(remember).lower()
161
+ return self._request(
162
+ "POST",
163
+ f"/ms/vteam/api/user/issue/{self.project_id}/table/TASK?num={num}&size={size}&remember={remember_value}",
164
+ data=data,
165
+ )