jira-issues
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseJira Issues Skill
Jira Issues Skill
Purpose
用途
Create, read, update, and delete issues in Jira Cloud. Manage issue fields, transitions, and metadata.
在Jira Cloud中创建、读取、更新和删除问题。管理问题字段、状态流转和元数据。
When to Use
使用场景
- Creating new issues (Story, Task, Bug, Epic)
- Updating issue fields (summary, description, assignee, etc.)
- Reading issue details
- Deleting issues
- 创建新问题(Story、Task、Bug、Epic)
- 更新问题字段(摘要、描述、经办人等)
- 读取问题详情
- 删除问题
Prerequisites
前提条件
- Authenticated JiraClient (see jira-auth skill)
- Project access permissions
- Issue type IDs for the target project
- 已认证的JiraClient(请查看jira-auth技能)
- 项目访问权限
- 目标项目的问题类型ID
Implementation Pattern
实现模式
Step 1: Define Issue Types
步骤1:定义问题类型
typescript
interface JiraIssue {
id: string;
key: string;
self: string;
fields: {
summary: string;
description?: {
type: 'doc';
version: 1;
content: Array<{
type: string;
content?: Array<{
type: string;
text: string;
}>;
}>;
};
status: { name: string; id: string };
assignee?: { accountId: string; displayName: string };
reporter?: { accountId: string; displayName: string };
priority?: { name: string; id: string };
issuetype: { name: string; id: string };
project: { key: string; id: string };
created: string;
updated: string;
labels?: string[];
components?: Array<{ id: string; name: string }>;
};
}
interface CreateIssueInput {
projectKey: string;
summary: string;
issueType: 'Story' | 'Task' | 'Bug' | 'Epic' | string;
description?: string;
assigneeAccountId?: string;
labels?: string[];
priority?: string;
}typescript
interface JiraIssue {
id: string;
key: string;
self: string;
fields: {
summary: string;
description?: {
type: 'doc';
version: 1;
content: Array<{
type: string;
content?: Array<{
type: string;
text: string;
}>;
}>;
};
status: { name: string; id: string };
assignee?: { accountId: string; displayName: string };
reporter?: { accountId: string; displayName: string };
priority?: { name: string; id: string };
issuetype: { name: string; id: string };
project: { key: string; id: string };
created: string;
updated: string;
labels?: string[];
components?: Array<{ id: string; name: string }>;
};
}
interface CreateIssueInput {
projectKey: string;
summary: string;
issueType: 'Story' | 'Task' | 'Bug' | 'Epic' | string;
description?: string;
assigneeAccountId?: string;
labels?: string[];
priority?: string;
}Step 2: Create Issue
步骤2:创建问题
typescript
async function createIssue(
client: JiraClient,
input: CreateIssueInput
): Promise<{ id: string; key: string; self: string }> {
const body: any = {
fields: {
project: { key: input.projectKey },
summary: input.summary,
issuetype: { name: input.issueType },
},
};
// Add description in Atlassian Document Format (ADF)
if (input.description) {
body.fields.description = {
type: 'doc',
version: 1,
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: input.description,
},
],
},
],
};
}
if (input.assigneeAccountId) {
body.fields.assignee = { id: input.assigneeAccountId };
}
if (input.labels) {
body.fields.labels = input.labels;
}
if (input.priority) {
body.fields.priority = { name: input.priority };
}
return client.request<{ id: string; key: string; self: string }>('/issue', {
method: 'POST',
body: JSON.stringify(body),
});
}typescript
async function createIssue(
client: JiraClient,
input: CreateIssueInput
): Promise<{ id: string; key: string; self: string }> {
const body: any = {
fields: {
project: { key: input.projectKey },
summary: input.summary,
issuetype: { name: input.issueType },
},
};
// 添加Atlassian文档格式(ADF)的描述
if (input.description) {
body.fields.description = {
type: 'doc',
version: 1,
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: input.description,
},
],
},
],
};
}
if (input.assigneeAccountId) {
body.fields.assignee = { id: input.assigneeAccountId };
}
if (input.labels) {
body.fields.labels = input.labels;
}
if (input.priority) {
body.fields.priority = { name: input.priority };
}
return client.request<{ id: string; key: string; self: string }>('/issue', {
method: 'POST',
body: JSON.stringify(body),
});
}Step 3: Get Issue
步骤3:获取问题
typescript
async function getIssue(
client: JiraClient,
issueKeyOrId: string,
options: {
fields?: string[];
expand?: string[];
} = {}
): Promise<JiraIssue> {
const params = new URLSearchParams();
if (options.fields) params.set('fields', options.fields.join(','));
if (options.expand) params.set('expand', options.expand.join(','));
const query = params.toString() ? `?${params.toString()}` : '';
return client.request<JiraIssue>(`/issue/${issueKeyOrId}${query}`);
}typescript
async function getIssue(
client: JiraClient,
issueKeyOrId: string,
options: {
fields?: string[];
expand?: string[];
} = {}
): Promise<JiraIssue> {
const params = new URLSearchParams();
if (options.fields) params.set('fields', options.fields.join(','));
if (options.expand) params.set('expand', options.expand.join(','));
const query = params.toString() ? `?${params.toString()}` : '';
return client.request<JiraIssue>(`/issue/${issueKeyOrId}${query}`);
}Step 4: Update Issue
步骤4:更新问题
typescript
interface UpdateIssueInput {
summary?: string;
description?: string;
assigneeAccountId?: string | null;
labels?: string[];
priority?: string;
}
async function updateIssue(
client: JiraClient,
issueKeyOrId: string,
input: UpdateIssueInput
): Promise<void> {
const body: any = { fields: {} };
if (input.summary) {
body.fields.summary = input.summary;
}
if (input.description !== undefined) {
body.fields.description = input.description
? {
type: 'doc',
version: 1,
content: [
{
type: 'paragraph',
content: [{ type: 'text', text: input.description }],
},
],
}
: null;
}
if (input.assigneeAccountId !== undefined) {
body.fields.assignee = input.assigneeAccountId
? { id: input.assigneeAccountId }
: null;
}
if (input.labels) {
body.fields.labels = input.labels;
}
if (input.priority) {
body.fields.priority = { name: input.priority };
}
await client.request(`/issue/${issueKeyOrId}`, {
method: 'PUT',
body: JSON.stringify(body),
});
}typescript
interface UpdateIssueInput {
summary?: string;
description?: string;
assigneeAccountId?: string | null;
labels?: string[];
priority?: string;
}
async function updateIssue(
client: JiraClient,
issueKeyOrId: string,
input: UpdateIssueInput
): Promise<void> {
const body: any = { fields: {} };
if (input.summary) {
body.fields.summary = input.summary;
}
if (input.description !== undefined) {
body.fields.description = input.description
? {
type: 'doc',
version: 1,
content: [
{
type: 'paragraph',
content: [{ type: 'text', text: input.description }],
},
],
}
: null;
}
if (input.assigneeAccountId !== undefined) {
body.fields.assignee = input.assigneeAccountId
? { id: input.assigneeAccountId }
: null;
}
if (input.labels) {
body.fields.labels = input.labels;
}
if (input.priority) {
body.fields.priority = { name: input.priority };
}
await client.request(`/issue/${issueKeyOrId}`, {
method: 'PUT',
body: JSON.stringify(body),
});
}Step 5: Delete Issue
步骤5:删除问题
typescript
async function deleteIssue(
client: JiraClient,
issueKeyOrId: string,
deleteSubtasks: boolean = false
): Promise<void> {
const query = deleteSubtasks ? '?deleteSubtasks=true' : '';
await client.request(`/issue/${issueKeyOrId}${query}`, {
method: 'DELETE',
});
}typescript
async function deleteIssue(
client: JiraClient,
issueKeyOrId: string,
deleteSubtasks: boolean = false
): Promise<void> {
const query = deleteSubtasks ? '?deleteSubtasks=true' : '';
await client.request(`/issue/${issueKeyOrId}${query}`, {
method: 'DELETE',
});
}Step 6: Bulk Create Issues
步骤6:批量创建问题
typescript
async function bulkCreateIssues(
client: JiraClient,
issues: CreateIssueInput[]
): Promise<Array<{ id: string; key: string; self: string }>> {
const results: Array<{ id: string; key: string; self: string }> = [];
// Jira doesn't have a native bulk create, so we batch with Promise.all
const batches = [];
const batchSize = 10;
for (let i = 0; i < issues.length; i += batchSize) {
batches.push(issues.slice(i, i + batchSize));
}
for (const batch of batches) {
const batchResults = await Promise.all(
batch.map((issue) => createIssue(client, issue))
);
results.push(...batchResults);
}
return results;
}typescript
async function bulkCreateIssues(
client: JiraClient,
issues: CreateIssueInput[]
): Promise<Array<{ id: string; key: string; self: string }>> {
const results: Array<{ id: string; key: string; self: string }> = [];
// Jira没有原生的批量创建接口,因此我们使用Promise.all进行分批处理
const batches = [];
const batchSize = 10;
for (let i = 0; i < issues.length; i += batchSize) {
batches.push(issues.slice(i, i + batchSize));
}
for (const batch of batches) {
const batchResults = await Promise.all(
batch.map((issue) => createIssue(client, issue))
);
results.push(...batchResults);
}
return results;
}curl Examples
curl示例
Create Issue
创建问题
bash
curl -X POST "$JIRA_BASE_URL/rest/api/3/issue" \
-H "Authorization: Basic $(echo -n 'email:token' | base64)" \
-H "Content-Type: application/json" \
-d '{
"fields": {
"project": { "key": "SCRUM" },
"summary": "New feature implementation",
"issuetype": { "name": "Story" },
"description": {
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [{ "type": "text", "text": "Description here" }]
}
]
}
}
}'bash
curl -X POST "$JIRA_BASE_URL/rest/api/3/issue" \
-H "Authorization: Basic $(echo -n 'email:token' | base64)" \
-H "Content-Type: application/json" \
-d '{
"fields": {
"project": { "key": "SCRUM" },
"summary": "New feature implementation",
"issuetype": { "name": "Story" },
"description": {
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [{ "type": "text", "text": "Description here" }]
}
]
}
}
}'Get Issue
获取问题
bash
curl -X GET "$JIRA_BASE_URL/rest/api/3/issue/SCRUM-123" \
-H "Authorization: Basic $(echo -n 'email:token' | base64)" \
-H "Accept: application/json"bash
curl -X GET "$JIRA_BASE_URL/rest/api/3/issue/SCRUM-123" \
-H "Authorization: Basic $(echo -n 'email:token' | base64)" \
-H "Accept: application/json"Update Issue
更新问题
bash
curl -X PUT "$JIRA_BASE_URL/rest/api/3/issue/SCRUM-123" \
-H "Authorization: Basic $(echo -n 'email:token' | base64)" \
-H "Content-Type: application/json" \
-d '{
"fields": {
"summary": "Updated summary"
}
}'bash
curl -X PUT "$JIRA_BASE_URL/rest/api/3/issue/SCRUM-123" \
-H "Authorization: Basic $(echo -n 'email:token' | base64)" \
-H "Content-Type: application/json" \
-d '{
"fields": {
"summary": "Updated summary"
}
}'Delete Issue
删除问题
bash
curl -X DELETE "$JIRA_BASE_URL/rest/api/3/issue/SCRUM-123" \
-H "Authorization: Basic $(echo -n 'email:token' | base64)"bash
curl -X DELETE "$JIRA_BASE_URL/rest/api/3/issue/SCRUM-123" \
-H "Authorization: Basic $(echo -n 'email:token' | base64)"API Endpoints Summary
API端点汇总
| Operation | Method | Path |
|---|---|---|
| Create issue | POST | |
| Get issue | GET | |
| Update issue | PUT | |
| Delete issue | DELETE | |
| 操作 | 方法 | 路径 |
|---|---|---|
| 创建问题 | POST | |
| 获取问题 | GET | |
| 更新问题 | PUT | |
| 删除问题 | DELETE | |
Required Fields by Issue Type
按问题类型划分的必填字段
Story
Story
- (required)
project.key - (required)
summary - = "Story" (required)
issuetype.name
- (必填)
project.key - (必填)
summary - = "Story"(必填)
issuetype.name
Task
Task
- (required)
project.key - (required)
summary - = "Task" (required)
issuetype.name
- (必填)
project.key - (必填)
summary - = "Task"(必填)
issuetype.name
Bug
Bug
- (required)
project.key - (required)
summary - = "Bug" (required)
issuetype.name - (recommended)
description
- (必填)
project.key - (必填)
summary - = "Bug"(必填)
issuetype.name - (推荐填写)
description
Description Format (ADF)
描述格式(ADF)
Jira uses Atlassian Document Format for rich text:
json
{
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [
{ "type": "text", "text": "Normal text" }
]
},
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Bold text",
"marks": [{ "type": "strong" }]
}
]
}
]
}Jira使用Atlassian文档格式(ADF)来处理富文本:
json
{
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [
{ "type": "text", "text": "Normal text" }
]
},
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Bold text",
"marks": [{ "type": "strong" }]
}
]
}
]
}Common Mistakes
常见错误
- Using plain text for description instead of ADF format
- Not using account ID for assignee (email doesn't work)
- Forgetting project key in create request
- Using issue type name that doesn't exist in project
- 使用纯文本格式填写描述而非ADF格式
- 未使用账户ID指定经办人(邮箱格式无效)
- 创建请求时遗漏项目Key
- 使用项目中不存在的问题类型名称
References
参考资料
Version History
版本历史
- 2025-12-10: Created
- 2025-12-10:创建