Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

zentao-api-old

v1.0.1

Integrate with ZenTao Legacy API 1.0 to manage projects, tasks, bugs, products, and workflows with session persistence and role-specific operations.

0· 13·0 current·0 all-time
by张贝@hellotombruce
MIT-0
Download zip
LicenseMIT-0 · Free to use, modify, and redistribute. No attribution required.
Security Scan
VirusTotalVirusTotal
Pending
View report →
OpenClawOpenClaw
Suspicious
medium confidence
Purpose & Capability
The name/description (ZenTao Legacy API integration) matches the included code (zentao_client.py, zentao_cli.py) and the SKILL.md usage examples. However the registry metadata claimed 'instruction-only' / no required config paths while SKILL.md declares a required file (TOOLS.md) for credentials and the package actually contains code files and requirements.txt. That mismatch between declared metadata and actual bundle is unexpected.
Instruction Scope
SKILL.md's runtime instructions focus on creating a ZenTao client, reading credentials (via read_credentials()), obtaining a session, and calling ZenTao API methods. The instructions reference reading a project-local TOOLS.md and persisting sessions under a project-root path (.zentao/sessions/). They do not instruct the agent to read or exfiltrate unrelated system files or environment variables.
Install Mechanism
There is no installer that downloads arbitrary code from the network — the package contains Python source and a requirements.txt (requests). That is low-to-moderate risk: code will run locally, but no external install URL or archive extraction is used. The presence of packaged source is normal for a language client.
!
Credentials
The skill clearly needs ZenTao credentials (SKILL.md shows read_credentials() and demands a TOOLS.md section for 'ZenTao API'), but the registry metadata lists no required env vars or config paths and no primary credential. Credentials are expected to come from a file (TOOLS.md) but that requirement is not reflected in the metadata — this mismatch is a concern because users may not realize where secrets must be placed or how they will be stored/read. Also session persistence to .zentao/sessions/ will create files on disk containing session IDs.
Persistence & Privilege
The skill persists session state under the project root (.zentao/sessions/), which is within the skill's scope but is still writable persistent storage. always:false so it won't be force-enabled. Persisting session tokens locally is functionally justified for a client but you should verify how long tokens are kept and whether they are stored encrypted.
What to consider before installing
This package appears to be a genuine ZenTao API client, but there are a few things to check before installing: - Inspect TOOLS.md (present in the bundle) to see exactly how credentials are stored and formatted. The SKILL.md requires that file, but the registry metadata did not declare it — do not drop secrets into your global config until you verify the format and location. - Open lib/zentao_client.py and scripts/zentao_cli.py to confirm they only call the expected ZenTao endpoints and do not send data to unexpected third-party endpoints. Pay attention to any hard-coded URLs, telemetry, or callbacks. - Note that sessions are persisted under .zentao/sessions/ in the project directory. If that directory will be on shared storage or backed up, consider where session files end up and whether that is acceptable. - The package depends on requests (requirements.txt). Run the code in an isolated environment (development VM or container) if you want to test before trusting it with real credentials. I rate this as suspicious (not clearly malicious) because the credential handling and required-file declaration are inconsistent; reviewing the credential-read code will likely resolve the uncertainty.

Like a lobster shell, security has layers — review code before you run it.

latestvk977nxjmhr4zd9mggpjmq0ahh1847m8n

License

MIT-0
Free to use, modify, and redistribute. No attribution required.

SKILL.md

适用 Zentao Legacy API 1.0

禅道项目管理技能

快速参考指南,帮助 AI 助手高效调用禅道 API


🚀 快速开始

1. 初始化客户端

from pathlib import Path
import sys

# 导入禅道客户端
lib_path = Path(__file__).parent.parent / 'lib'
sys.path.insert(0, str(lib_path))
from zentao_client import ZenTaoClient, read_credentials

# 读取凭证
credentials = read_credentials()

# 创建客户端
client = ZenTaoClient(
    credentials['endpoint'],
    credentials['username'],
    credentials['password']
)

# 获取会话(首次登录,后续自动加载持久化的 Session)
sid = client.get_session()

1.1 Session 持久化

客户端自动管理 Session,无需每次都登录:

# 首次调用自动登录并保存 Session
sid = client.get_session()

# 新实例自动加载已有 Session
client2 = ZenTaoClient(credentials['endpoint'], credentials['username'], credentials['password'])
sid2 = client2.get_session()  # 直接加载,无需登录

# 强制刷新 Session
client.get_session(force_refresh=True)

# 清除保存的 Session
client.clear_session()

存储位置:项目根目录 .zentao/sessions/

2. 快速查询

# 查看我的任务
success, tasks = client.get_my_tasks("assignedTo")

# 查看我的Bug
success, bugs = client.get_my_bugs("assignedTo")

# 查看产品列表
success, products = client.get_products()

# 查看项目列表
projects = client.get_project_list_old("all")

# 查看项目任务
tasks = client.get_project_tasks_old(project_id, "all")

📊 API 分类速查

按使用频率分级

⭐⭐⭐⭐⭐ 最高频(日常必用)

角色API场景
全员get_my_tasks("assignedTo")查看指派给我的任务
全员get_my_bugs("assignedTo")查看指派给我的Bug
研发start_task(task_id)开始任务
研发record_estimate(task_id, records)记录工时
研发finish_task(task_id)完成任务
测试create_bug(...)创建Bug
测试resolve_bug(bug_id, ...)解决Bug

⭐⭐⭐⭐ 高频(日常工作)

角色API场景
产品create_story(...)创建需求
项目经理create_subtasks(...)创建子任务
项目经理assign_task(task_id, user)指派任务
全员get_task_detail(task_id)查看任务详情
全员get_bug(bug_id)查看Bug详情
测试close_bug(bug_id)关闭Bug
研发pause_task(task_id)暂停任务

⭐⭐⭐ 中频(项目管理)

角色API场景
产品create_product(...)创建产品
产品get_products()查询产品列表
产品create_plan(...)创建发布计划
项目经理create_project(...)创建项目
项目经理get_project(project_id)查询项目详情
项目经理start_project(...)启动项目
项目经理get_project_list_old()查询项目列表
项目经理get_project_tasks_old()查询项目任务
测试create_testcase(...)创建测试用例
测试create_testtask(...)创建测试任务

👥 角色场景速查

产品经理

# ========== 需求管理 ==========

# 创建需求
success, result = client.create_story(
    product_id="1",
    title="用户登录功能",
    pri="3",              # 优先级: 0-4
    estimate="8",         # 预计工时
    spec="实现用户登录功能",
    reviewer="admin"
)

# 查看我的需求
success, stories = client.get_my_stories("assignedTo")
# 类型: assignedTo(指派给我), openedBy(我创建的), reviewedBy(我评审的)

# 编辑需求
success, result = client.edit_story(story_id, title="新标题", pri="2")

# 关闭需求
success, result = client.close_story(story_id)

# ========== 产品管理 ==========

# 创建产品
success, result = client.create_product(
    name="新产品",
    code="NEW",
    po="admin",           # 产品负责人
    status="normal"
)

# 查询产品列表
success, products = client.get_products()

# 创建发布计划
success, result = client.create_plan(
    product_id="1",
    title="V1.0版本",
    begin="2026-03-01",
    end="2026-03-31"
)

# 查询发布计划
success, plans = client.get_plans(product_id)

项目经理

# ========== 项目管理 ==========

# 创建项目
success, result = client.create_project(
    name="V1.0开发项目",
    begin="2026-04-01",
    end="2026-04-30",
    code="V1",
    days="22",
    products=["1"],      # 关联产品ID列表
    plans=["1"],         # 关联计划ID列表
    desc="项目描述"
)

# 查询项目详情
success, project = client.get_project("1")
print(f"项目: {project['name']}, 状态: {project['status']}")

# 启动项目 (wait → doing)
success, result = client.start_project("1")

# 关闭项目
success, result = client.close_project("1")

# ========== 项目查询 ==========

# 查询项目列表
projects = client.get_project_list_old("all")  # 状态: all, doing, done, suspended

# 查询项目任务
tasks = client.get_project_tasks_old(project_id, "all")  # 状态: all, wait, doing, done, pause, cancel

# ========== 任务分解 ==========

# 创建任务
success, result = client.create_task(
    project_id="1",       # 项目ID
    name="用户登录功能开发",
    type="devel",         # 任务类型: devel, test, design, study, discuss, ui, affair, misc
    assignedTo="dev1",
    pri="3",              # 优先级: 0-4
    estimate="8",         # 预计工时
    desc="实现用户登录功能"
)

# 批量创建任务
success, result = client.create_tasks(
    project_id="1",
    tasks=[
        {"name": "前端开发", "type": "devel", "assignedTo": "dev1", "estimate": "8", "pri": "3"},
        {"name": "后端开发", "type": "devel", "assignedTo": "dev2", "estimate": "16", "pri": "3"},
        {"name": "接口联调", "type": "devel", "assignedTo": "dev1", "estimate": "4", "pri": "3"}
    ]
)

# 创建子任务
success, result = client.create_subtasks(
    execution_id="1",     # 项目/执行ID
    parent_id="100",      # 父任务ID
    tasks=[
        {"name": "前端开发", "estimate": "8", "assignedTo": "dev1", "type": "devel", "pri": "3"},
        {"name": "后端开发", "estimate": "16", "assignedTo": "dev2", "type": "devel", "pri": "3"},
        {"name": "接口联调", "estimate": "4", "assignedTo": "dev1", "type": "devel", "pri": "3"}
    ]
)

# ========== 任务指派 ==========

# 指派任务
success, result = client.assign_task(task_id, "zhangsan", "请处理")

# ========== 任务管理 ==========

# 取消任务
success, result = client.cancel_task(task_id)

# 删除任务
success, result = client.delete_task(task_id)

研发工程师

# ========== 日常查询 ==========

# 查看我的任务
success, tasks = client.get_my_tasks("assignedTo")
# 类型: assignedTo(指派给我), openedBy(我创建的), finishedBy(我完成的)

# 查看任务详情
success, task = client.get_task_detail(task_id)
print(f"状态: {task['status']}")      # wait, doing, pause, done, cancel, closed
print(f"预计: {task['estimate']}h")   # 预计工时
print(f"消耗: {task['consumed']}h")   # 已消耗工时
print(f"剩余: {task['left']}h")       # 剩余工时

# ========== 任务流转 ==========

# 开始任务 (wait → doing)
success, result = client.start_task(task_id, "开始开发")

# 记录工时
from datetime import datetime
today = datetime.now().strftime("%Y-%m-%d")
success, result = client.record_estimate(task_id, [
    {
        "date": today,
        "consumed": "3",      # 本次消耗
        "left": "5",          # 剩余
        "work": "完成了登录功能开发"
    }
])

# 暂停任务 (doing → pause)
success, result = client.pause_task(task_id, "等待依赖接口")

# 继续任务 (pause → doing)
success, result = client.restart_task(task_id, "依赖已就绪")

# 完成任务 (doing → done) - 重要:先记录工时left=0,再完成
client.record_estimate(task_id, [
    {"date": today, "consumed": "5", "left": "0", "work": "全部完成"}
])
success, result = client.finish_task(task_id, "开发完成")

# 关闭任务 (done → closed)
success, result = client.close_task(task_id, "已验收")

# 激活任务 (done/closed → doing)
success, result = client.activate_task(task_id, "重新开始")

# ========== Bug处理 ==========

# 查看我的Bug
success, bugs = client.get_my_bugs("assignedTo")
# 类型: assignedTo(指派给我), openedBy(我创建的), resolvedBy(我解决的)

# 查看Bug详情
success, bug = client.get_bug(bug_id)

# 解决Bug
success, result = client.resolve_bug(
    bug_id=bug_id,
    resolution="fixed",       # fixed, postponed, willnotfix, duplicate, tostory
    resolved_build="trunk",
    comment="已修复登录校验问题"
)

测试工程师

# ========== Bug管理 ==========

# 创建Bug
success, result = client.create_bug(
    product_id="1",
    title="登录页面报错:500错误",
    severity="3",             # 严重程度: 1-4 (1最严重)
    pri="3",                  # 优先级: 0-4
    type="codeerror",         # 类型: codeerror, config, install, security, etc.
    steps="1.打开登录页\n2.输入账号密码\n3.点击登录\n4.出现500错误",
    assignedTo="dev1",
    project_id="1"
)

# 确认Bug
success, result = client.confirm_bug(bug_id, "确认是有效Bug")

# 指派Bug
success, result = client.assign_bug(bug_id, "dev1", "请处理")

# 关闭Bug (resolved → closed)
success, result = client.close_bug(bug_id, "验证通过")

# 激活Bug (closed → active)
success, result = client.activate_bug(bug_id, "问题重现")

# ========== 测试用例 ==========

# 创建测试用例
success, result = client.create_testcase(
    product_id="1",
    title="登录功能测试",
    case_type="feature",      # feature, performance, config, install, security, etc.
    steps="1.打开登录页\n2.输入账号密码\n3.点击登录",
    expect="登录成功"
)

# 查询测试用例
success, cases = client.get_testcases(product_id, "all")

# ========== 测试任务 ==========

# 创建测试任务
success, result = client.create_testtask(
    product_id="1",
    name="Sprint1测试",
    begin="2026-03-20",
    end="2026-03-25"
)

# 开始测试任务
success, result = client.start_testtask(task_id)

# 关闭测试任务
success, result = client.close_testtask(task_id)

🔄 状态流转图

任务状态流转

                    ┌─────────────┐
                    │   wait      │ 待开始
                    └──────┬──────┘
                           │ start_task()
                           ▼
                    ┌─────────────┐
           ┌───────│   doing     │ 进行中◀───────┐
           │       └──────┬──────┘               │
           │              │                      │
    pause_task()    finish_task()         activate_task()
           │              │                      │
           │              ▼                      │
           │       ┌─────────────┐               │
           │       │    done     │ 已完成        │
           │       └──────┬──────┘               │
           │              │                      │
           │       close_task()           restart_task()
           │              │                      │
           │              ▼                      │
    ┌──────┴──────┐ ┌─────────────┐              │
    │   pause     │ │   closed    │ 已关闭       │
    │   暂停      │ └─────────────┘              │
    └──────┬──────┘                              │
           │                                     │
           └─────────────────────────────────────┘
                     restart_task()

    cancel_task() ──────▶ cancel (已取消)

API调用顺序:

当前状态目标状态API说明
waitdoingstart_task(task_id)开始任务
doingpausepause_task(task_id)暂停任务
pausedoingrestart_task(task_id)继续任务
doingdonefinish_task(task_id)完成任务(建议先记录工时left=0)
doneclosedclose_task(task_id)关闭任务
done/closeddoingactivate_task(task_id)激活任务
anycancelcancel_task(task_id)取消任务

Bug状态流转

    ┌─────────────┐
    │   active    │ 激活
    └──────┬──────┘
           │ resolve_bug()
           ▼
    ┌─────────────┐
    │  resolved   │ 已解决
    └──────┬──────┘
           │ close_bug()
           ▼
    ┌─────────────┐
    │   closed    │ 已关闭
    └──────┬──────┘
           │ activate_bug()
           └──────────────┐
                          ▼
                    ┌─────────────┐
                    │   active    │ 激活
                    └─────────────┘

API调用顺序:

当前状态目标状态API说明
activeresolvedresolve_bug(bug_id, resolution)解决Bug
resolvedclosedclose_bug(bug_id)关闭Bug
closedactiveactivate_bug(bug_id)激活Bug

📝 重要注意事项

1. 工时记录是批量接口

# ✅ 正确:一次提交多条记录
client.record_estimate(task_id, [
    {"date": "2026-03-27", "consumed": "2", "left": "6", "work": "开发"},
    {"date": "2026-03-28", "consumed": "3", "left": "3", "work": "测试"}
])

# ❌ 错误:多次调用会覆盖之前记录
client.record_estimate(task_id, [{"date": "2026-03-27", "consumed": "2", ...}])
client.record_estimate(task_id, [{"date": "2026-03-28", "consumed": "3", ...}])  # 会覆盖!

2. 完成任务前先记录工时

# ✅ 正确流程
client.record_estimate(task_id, [
    {"date": "2026-03-27", "consumed": "8", "left": "0", "work": "完成"}
])
client.finish_task(task_id, "开发完成")

# ❌ 错误:直接完成任务,没有记录最终工时
client.finish_task(task_id)

3. 获取任务详情验证操作结果

# 很多API返回HTML而非JSON,解析会失败,但操作实际成功
success, result = client.start_task(task_id)
# 建议:用get_task_detail验证
ok, task = client.get_task_detail(task_id)
print(f"状态: {task['status']}")  # 应为 'doing'

4. 解决Bug用专用接口

# ✅ 正确:使用resolve_bug
client.resolve_bug(bug_id, "fixed", "trunk", "已修复")

# ❌ 错误:不要用edit_bug修改状态,会丢失其他字段
# client.edit_bug(bug_id, status="resolved")  # 会丢失产品、项目关联!

5. 创建子任务注意ditto

# 子任务数组参数,第一个任务用实际值,后续用ditto继承
client.create_subtasks(execution_id, parent_id, [
    {"name": "前端", "estimate": "8", "assignedTo": "dev1", "type": "devel", "pri": "3"},
    {"name": "后端", "estimate": "16", "assignedTo": "dev2", "type": "devel", "pri": "3"}
    # 第二个任务会继承第一个任务的type和pri(API内部处理)
])

6. 查看我的任务/bug返回格式

# get_my_tasks和get_my_bugs返回的是列表,不是字典
success, tasks = client.get_my_tasks("assignedTo")
if success:
    for task in tasks:  # tasks是列表
        print(f"[{task['id']}] {task['name']} ({task['status']})")

🎯 典型使用场景

场景1:每日站会查询

# 查看我的任务
success, tasks = client.get_my_tasks("assignedTo")

# 统计状态
stats = {"wait": 0, "doing": 0, "pause": 0, "done": 0}
for task in tasks:
    status = task.get("status", "unknown")
    if status in stats:
        stats[status] += 1

print(f"我的任务: 待开始{stats['wait']}, 进行中{stats['doing']}, 暂停{stats['pause']}, 已完成{stats['done']}")

场景2:开始新任务

# 1. 查看任务详情
success, task = client.get_task_detail(task_id)
print(f"任务: {task['name']}, 预计工时: {task['estimate']}h")

# 2. 开始任务
success, result = client.start_task(task_id, "开始开发")

# 3. 验证
ok, task = client.get_task_detail(task_id)
print(f"状态: {task['status']}")  # doing

场景3:每日记录工时

from datetime import datetime

# 记录今天的工时
today = datetime.now().strftime("%Y-%m-%d")
success, result = client.record_estimate(task_id, [
    {
        "date": today,
        "consumed": "3",      # 今天消耗3小时
        "left": "5",          # 剩余5小时
        "work": "完成了用户登录功能开发"
    }
])

# 验证
ok, task = client.get_task_detail(task_id)
print(f"总消耗: {task['consumed']}h, 剩余: {task['left']}h")

场景4:完成任务

from datetime import datetime

today = datetime.now().strftime("%Y-%m-%d")

# 1. 记录最终工时
client.record_estimate(task_id, [
    {"date": today, "consumed": "5", "left": "0", "work": "全部完成"}
])

# 2. 完成任务
success, result = client.finish_task(task_id, "开发完成,已自测")

# 3. 验证
ok, task = client.get_task_detail(task_id)
print(f"状态: {task['status']}")        # done
print(f"完成人: {task['finishedBy']}")  # admin

场景5:提交Bug

# 创建Bug
success, result = client.create_bug(
    product_id="1",
    title="登录页面500错误",
    severity="2",             # 严重
    pri="3",
    type="codeerror",
    steps="1.打开登录页\n2.输入admin/admin\n3.点击登录\n4.出现500错误",
    assignedTo="dev1",
    comment="优先处理"
)

# 查看我的Bug
success, bugs = client.get_my_bugs("openedBy")
for bug in bugs:
    print(f"[{bug['id']}] {bug['title']} ({bug['status']})")

场景6:解决和关闭Bug

# 1. 查看Bug详情
success, bug = client.get_bug(bug_id)
print(f"标题: {bug['title']}, 状态: {bug['status']}")

# 2. 解决Bug
success, result = client.resolve_bug(
    bug_id=bug_id,
    resolution="fixed",
    resolved_build="trunk",
    comment="已修复登录校验逻辑"
)

# 3. 关闭Bug
success, result = client.close_bug(bug_id, "验证通过,问题已修复")

# 4. 验证
ok, bug = client.get_bug(bug_id)
print(f"状态: {bug['status']}")        # closed
print(f"关闭人: {bug['closedBy']}")

场景7:创建子任务分解

# 查询父任务
tasks = client.get_project_tasks_old(project_id, "all")
parent_task_id = list(tasks.keys())[0]

# 创建子任务
success, result = client.create_subtasks(
    execution_id=project_id,
    parent_id=parent_task_id,
    tasks=[
        {"name": "前端开发", "estimate": "8", "assignedTo": "dev1"},
        {"name": "后端开发", "estimate": "16", "assignedTo": "dev2"},
        {"name": "接口联调", "estimate": "4", "assignedTo": "dev1"}
    ]
)

🔧 高级用法

批量操作

# 批量创建需求
requirements = ["用户登录", "商品浏览", "购物车", "订单管理"]
for req in requirements:
    client.create_story(product_id, req, pri="3", estimate="8")

# 批量记录工时
from datetime import datetime, timedelta
today = datetime.now()
records = []
for i in range(5):
    records.append({
        "date": (today - timedelta(days=i)).strftime("%Y-%m-%d"),
        "consumed": "2",
        "left": str(10 - i * 2),
        "work": f"开发进度{i*20}%"
    })
client.record_estimate(task_id, records)

状态统计

# 项目任务状态统计
tasks = client.get_project_tasks_old(project_id, "all")
stats = {}
for tid, task in tasks.items():
    status = task.get("status", "unknown")
    stats[status] = stats.get(status, 0) + 1

print(f"任务统计: {stats}")
# 输出: {'wait': 5, 'doing': 3, 'done': 10, 'pause': 1, 'cancel': 2}

数据导出

import json

# 导出我的任务
success, tasks = client.get_my_tasks("assignedTo")
with open("my_tasks.json", "w", encoding="utf-8") as f:
    json.dump(tasks, f, ensure_ascii=False, indent=2)

# 导出我的Bug
success, bugs = client.get_my_bugs("assignedTo")
with open("my_bugs.json", "w", encoding="utf-8") as f:
    json.dump(bugs, f, ensure_ascii=False, indent=2)

📚 API完整列表

产品管理

API说明参数
create_product(name, code, ...)创建产品name, code, type, po, qd, rd, status, desc
get_products()查询产品列表-
get_product(product_id)查询产品详情product_id
edit_product(product_id, ...)编辑产品product_id, **kwargs
close_product(product_id)关闭产品product_id
delete_product(product_id)删除产品product_id

需求管理

API说明参数
create_story(product_id, title, ...)创建需求product_id, title, pri, estimate, spec, ...
get_story(story_id)查询需求详情story_id
get_my_stories(story_type)查询我的需求story_type: assignedTo, openedBy, reviewedBy, closedBy
edit_story(story_id, ...)编辑需求story_id, **kwargs
close_story(story_id)关闭需求story_id
activate_story(story_id)激活需求story_id
delete_story(story_id)删除需求story_id

计划管理

API说明参数
create_plan(product_id, title, ...)创建计划product_id, title, begin, end, desc
get_plans(product_id)查询计划列表product_id
delete_plan(plan_id)删除计划plan_id

项目管理

API说明参数
create_project(name, begin, end, ...)创建项目name, begin, end, code, days, products, plans, desc
get_project(project_id)查询项目详情project_id
start_project(project_id)启动项目project_id
close_project(project_id)关闭项目project_id
get_project_list_old(status)查询项目列表status: all, doing, done, suspended
get_project_tasks_old(project_id, status)查询项目任务project_id, status
get_project_bugs(project_id, status)查询项目Bugproject_id, status

任务管理

API说明参数
create_task(project, name, type, ...)创建任务project, name, type, story, module, assignedTo, pri, estimate, desc
create_tasks(project, tasks)批量创建任务project, tasks列表
get_my_tasks(task_type)查询我的任务task_type: assignedTo, openedBy, finishedBy, closedBy, canceledBy
get_task_detail(task_id)查询任务详情task_id
create_subtasks(execution_id, parent_id, tasks)创建子任务execution_id, parent_id, tasks列表
start_task(task_id, comment)开始任务task_id, comment
pause_task(task_id, comment)暂停任务task_id, comment
restart_task(task_id, comment)继续任务task_id, comment
finish_task(task_id, comment)完成任务task_id, comment
close_task(task_id, comment)关闭任务task_id, comment
activate_task(task_id, comment)激活任务task_id, comment
cancel_task(task_id)取消任务task_id
delete_task(task_id)删除任务task_id
assign_task(task_id, assigned_to, comment)指派任务task_id, assigned_to, comment
record_estimate(task_id, records)记录工时task_id, records列表

Bug管理

API说明参数
get_my_bugs(bug_type)查询我的Bugbug_type: assignedTo, openedBy, resolvedBy, closedBy
get_bug(bug_id)查询Bug详情bug_id
create_bug(product_id, title, ...)创建Bugproduct_id, title, severity, pri, type, steps, assignedTo, ...
resolve_bug(bug_id, resolution, ...)解决Bugbug_id, resolution, resolved_build, comment
close_bug(bug_id, comment)关闭Bugbug_id, comment
activate_bug(bug_id, comment)激活Bugbug_id, comment
assign_bug(bug_id, assigned_to, comment)指派Bugbug_id, assigned_to, comment
confirm_bug(bug_id, comment)确认Bugbug_id, comment
delete_bug(bug_id)删除Bugbug_id

测试管理

API说明参数
get_testcases(product_id, browse_type)查询测试用例product_id, browse_type
get_testcase(case_id)查询用例详情case_id
create_testcase(product_id, title, ...)创建测试用例product_id, title, case_type, steps, expect, ...
delete_testcase(case_id)删除测试用例case_id
get_testsuites(product_id)查询测试套件product_id
create_testsuite(product_id, name, desc)创建测试套件product_id, name, desc
get_testtasks(product_id, task_type)查询测试任务product_id, task_type
create_testtask(product_id, name, ...)创建测试任务product_id, name, begin, end, desc
start_testtask(task_id)开始测试任务task_id
close_testtask(task_id)关闭测试任务task_id

🆘 故障排查

常见问题

Q: 认证失败怎么办?

# 检查凭证
credentials = read_credentials()
print(credentials)  # 确保endpoint, username, password正确

# 手动获取session
sid = client.get_session()
if not sid:
    print("认证失败,请检查用户名密码")

Q: API返回success=False但操作成功?

# 很多API返回HTML而非JSON,解析会失败
# 建议:用查询接口验证操作结果
success, result = client.start_task(task_id)
# 返回False但实际成功
ok, task = client.get_task_detail(task_id)
print(task['status'])  # 验证状态是否变为doing

Q: 工时记录不生效?

# 确保参数格式正确
from datetime import datetime
today = datetime.now().strftime("%Y-%m-%d")  # 必须是YYYY-MM-DD格式

success, result = client.record_estimate(task_id, [
    {
        "date": today,
        "consumed": "2",  # 字符串格式
        "left": "6",      # 字符串格式
        "work": "开发中"
    }
])

# 验证
ok, task = client.get_task_detail(task_id)
print(f"消耗: {task['consumed']}, 剩余: {task['left']}")

Q: 创建子任务失败?

# 确保参数完整
tasks = [
    {
        "name": "前端开发",      # 必需
        "estimate": "8",         # 必需
        "assignedTo": "admin",   # 必需
        "type": "devel",         # 可选,默认devel
        "pri": "3"               # 可选,默认3
    }
]

success, result = client.create_subtasks(
    execution_id="1",     # 项目/执行ID
    parent_id="100",      # 父任务ID
    tasks=tasks
)

📖 参考资料


📄 许可证

MIT License - 自由使用、修改和分发

Files

66 total
Select a file
Select a file to preview.

Comments

Loading comments…