将 Epic API 迁移到工作项
- 版本:Premium、Ultimate
- 产品形态:GitLab.com、GitLab 自管版、GitLab 专属版
- 状态:Beta
在 GitLab 17.2 中,我们引入了将 Epic 作为工作项的功能。
为确保您的集成能够继续正常工作:
- 如果您使用 Epic GraphQL API,请在其被移除前迁移到工作项 API。
- 如果您使用 REST API,可以继续使用,但建议您进行迁移以确保集成的未来兼容性。
- 对于新功能(例如负责人、健康状态、与其他类型的关联项),您必须
使用
WorkItemGraphQL API。
API 状态
REST API (/api/v4/)
Epic 的 REST API:
- 仍受支持但已弃用。
- 可继续与现有端点配合使用。
- 不会接收新功能。
- 没有设定具体的移除日期,但将在某个主要版本中移除。
GraphQL API
WorkItem GraphQL API:
Epic GraphQL API 计划在 GitLab 19.0 中移除。
迁移到工作项 API
工作项 API 使用组件来表示 Epic 的属性,例如健康状态、负责人和层级结构。
设置 GraphiQL 浏览器
要运行这些示例,您可以使用 GraphiQL,它是一个交互式的 GraphQL API 浏览器,您可以在其中试用现有的查询:
- 打开 GraphiQL 浏览器工具:
- 对于 GitLab.com,请访问 https://gitlab.com/-/graphql-explorer。
- 对于 GitLab 自管版,请访问
https://gitlab.example.com/-/graphql-explorer。 请将gitlab.example.com替换为您的实例 URL。
- 将示例中列出的查询粘贴到您的 GraphiQL 浏览器工具的左侧窗口中。
- 选择 Play。
查询 Epic
Epic ID 与工作项 ID 不同,但 IID(每个组内递增的 ID)保持不变。
例如,位于 /gitlab-org/-/epics/123 的 Epic 与作为工作项时具有相同的 IID 123。
之前(Epic API):
query Epics {
group(fullPath: "gitlab-org") {
epics {
nodes {
id
iid
title
}
}
}
}示例响应:
{
"data": {
"group": {
"epics": {
"nodes": [
{
"id": "gid://gitlab/Epic/2335843",
"iid": "15596",
"title": "First epic"
},
{
"id": "gid://gitlab/Epic/2335762",
"iid": "15595",
"title": "Second epic"
}
]
}
}
}
}之后(工作项 API):
query EpicsAsWorkItem {
group(fullPath: "gitlab-org") {
workItems(types: [EPIC]) {
nodes {
id
iid
title
}
}
}
}示例响应:
{
"data": {
"group": {
"workItems": {
"nodes": [
{
"id": "gid://gitlab/WorkItem/154888575",
"iid": "15596",
"title": "First epic"
},
{
"id": "gid://gitlab/WorkItem/154877868",
"iid": "15595",
"title": "Second epic"
}
]
}
}
}
}创建 Epic
之前(Epic API):
mutation CreateEpic {
createEpic(input: { title: "New epic", groupPath: "gitlab-org" }) {
epic {
id
title
}
}
}示例响应:
{
"data": {
"createEpic": {
"epic": {
"id": "gid://gitlab/Epic/806",
"title": "New epic"
}
}
}
}之后(工作项 API):
要创建 Epic:
-
获取您命名空间中 Epic 的工作项类型 ID (
workItemTypeId)。Epic 的
workItemTypeId在不同的 GitLab 实例或命名空间之间不能保证相同。 确保默认工作项类型具有相同 ID 的工作正在 epic 15272 中进行跟踪。query WorkItemTypes { namespace(fullPath: "gitlab-org") { workItemTypes(name: EPIC) { nodes { id name } } } }示例响应:
{ "data": { "namespace": { "workItemTypes": { "nodes": [ { // the <WorkItemTypeId> will be different based on your namespace and instance "id": "gid://gitlab/WorkItems::Type/<WorkItemTypeId>", "name": "Epic" } ] } } } } -
使用该 ID 创建 Epic(类型为
epic的工作项):mutation CreateWorkItemEpic { workItemCreate( input: { title: "New work item epic" namespacePath: "gitlab-org" workItemTypeId: "gid://gitlab/WorkItems::Type/<WorkItemTypeID>" } ) { workItem { id title } } }示例响应:
{ "data": { "workItemCreate": { "workItem": { "id": "gid://gitlab/WorkItem/2243", "title": "New work item epic" } } } }
组件
工作项 API 引入了组件的概念。 组件代表工作项类型的特定功能或属性。 它们可以是从健康状态或负责人等属性,到日期或层级结构等各种内容。 每种工作项类型都有一组独特的可用组件。
使用组件查询 Epic
要检索 Epic 的详细信息,您可以在 GraphQL 查询中使用各种组件。 以下示例演示了如何查询 Epic 的:
- 层级结构(父级/子级关系)
- 负责人
- Emoji 表情回应
- 颜色
- 健康状态
- 开始日期和截止日期
有关所有可用组件,请参阅工作项组件参考。
要使用组件查询 Epic:
之前(Epic API):
query DetailedEpicQuery {
group(fullPath: "gitlab-org") {
epic(iid: 1000) {
id
iid
title
confidential
author {
id
name
}
state
color
parent {
id
title
}
startDate
dueDate
ancestors {
nodes {
id
title
}
}
children {
nodes {
id
title
}
}
notes {
nodes {
body
createdAt
author {
name
}
}
}
}
}
}示例响应:
{
"data": {
"group": {
"epic": {
"id": "gid://gitlab/Epic/5579",
"iid": "1000",
"title": "Pajamas component: Pagination - Style",
"confidential": false,
"author": {
"id": "gid://gitlab/User/3079878",
"name": "Sidney Jones"
},
"state": "opened",
"color": "#1068bf",
"parent": {
"id": "gid://gitlab/Epic/5576",
"title": "Pajamas component: Pagination"
},
"startDate": null,
"dueDate": null,
"ancestors": {
"nodes": [
{
"id": "gid://gitlab/Epic/5523",
"title": "Components of Pajamas Design System"
},
{
"id": "gid://gitlab/Epic/5576",
"title": "Pajamas component: Pagination"
}
]
},
"children": {
"nodes": []
},
"notes": {
"nodes": [
{
"body": "changed the description",
"createdAt": "2019-04-02T17:03:05Z",
"author": {
"name": "Sidney Jones"
}
},
{
"body": "mentioned in epic &997",
"createdAt": "2019-04-26T15:45:49Z",
"author": {
"name": "Zhang Wei"
}
},
{
"body": "added issue gitlab-ui#302",
"createdAt": "2019-06-27T09:20:43Z",
"author": {
"name": "Alex Garcia"
}
},
{
"body": "added issue gitlab-ui#304",
"createdAt": "2019-06-27T09:20:43Z",
"author": {
"name": "Alex Garcia"
}
},
{
"body": "added issue gitlab-ui#316",
"createdAt": "2019-07-11T08:26:25Z",
"author": {
"name": "Alex Garcia"
}
},
{
"body": "mentioned in issue gitlab-design#528",
"createdAt": "2019-08-05T14:12:51Z",
"author": {
"name": "Jan Kowalski"
}
}
]
}
}
}
}
}之后(工作项 API):
query DetailedEpicWorkItem {
namespace(fullPath: "gitlab-org") {
workItem(iid: "10") {
id
title
confidential
author {
id
name
}
state
widgets {
... on WorkItemWidgetColor {
color
textColor
__typename
}
... on WorkItemWidgetHierarchy {
children {
nodes {
id
title
}
}
parent {
title
}
__typename
}
... on WorkItemWidgetHealthStatus {
type
healthStatus
}
... on WorkItemWidgetAssignees {
assignees {
nodes {
name
}
}
__typename
}
... on WorkItemWidgetAwardEmoji {
downvotes
upvotes
awardEmoji {
nodes {
unicode
}
}
__typename
}
... on WorkItemWidgetStartAndDueDate {
dueDate
isFixed
startDate
__typename
}
... on WorkItemWidgetNotes {
discussions {
nodes {
notes {
edges {
node {
body
id
author {
name
}
}
}
}
}
}
}
__typename
}
}
}
}示例响应:
{
"data": {
"namespace": {
"workItem": {
"id": "gid://gitlab/WorkItem/146171815",
"title": "Pajamas component: Pagination - Style",
"confidential": false,
"author": {
"id": "gid://gitlab/User/3079878",
"name": "Sidney Jones"
},
"state": "OPEN",
"widgets": [
{
"assignees": {
"nodes": []
},
"__typename": "WorkItemWidgetAssignees"
},
{
"__typename": "WorkItemWidgetDescription"
},
{
"children": {
"nodes": [
{
"id": "gid://gitlab/WorkItem/24697619",
"title": "Pagination does not conform with button styling and interaction styling"
},
{
"id": "gid://gitlab/WorkItem/22693964",
"title": "Remove next and previous labels on mobile and smaller viewports for pagination component"
},
{
"id": "gid://gitlab/WorkItem/22308883",
"title": "Update pagination border and background colors according to the specs"
},
{
"id": "gid://gitlab/WorkItem/22294339",
"title": "Pagination \"active\" page contains gray border on right side"
}
]
},
"parent": {
"title": "Pajamas component: Pagination"
},
"__typename": "WorkItemWidgetHierarchy"
},
{
"__typename": "WorkItemWidgetLabels"
},
{
"discussions": {
"nodes": [
{
"notes": {
"edges": [
{
"node": {
"body": "changed the description",
"id": "gid://gitlab/Note/156548315",
"author": {
"name": "Sidney Jones"
}
}
}
]
}
},
{
"notes": {
"edges": [
{
"node": {
"body": "added ~10161862 label",
"id": "gid://gitlab/LabelNote/853dc8176d8eff789269d69c31c019ecd9918996",
"author": {
"name": "Jan Kowalski"
}
}
}
]
}
},
{
"notes": {
"edges": [
{
"node": {
"body": "mentioned in epic &997",
"id": "gid://gitlab/Note/164703873",
"author": {
"name": "Zhang Wei"
}
}
}
]
}
},
{
"notes": {
"edges": [
{
"node": {
"body": "added issue gitlab-ui#302",
"id": "gid://gitlab/Note/185977331",
"author": {
"name": "Alex Garcia"
}
}
}
]
}
},
{
"notes": {
"edges": [
{
"node": {
"body": "added issue gitlab-ui#304",
"id": "gid://gitlab/Note/185977335",
"author": {
"name": "Alex Garcia"
}
}
}
]
}
},
{
"notes": {
"edges": [
{
"node": {
"body": "added issue gitlab-ui#316",
"id": "gid://gitlab/Note/190661279",
"author": {
"name": "Alex Garcia"
}
}
}
]
}
},
{
"notes": {
"edges": [
{
"node": {
"body": "mentioned in issue gitlab-design#528",
"id": "gid://gitlab/Note/200228415",
"author": {
"name": "Jan Kowalski"
}
}
}
]
}
},
{
"notes": {
"edges": [
{
"node": {
"body": "added ~8547186 ~10161725 labels and removed ~10161862 label",
"id": "gid://gitlab/LabelNote/dfa79f5c4e6650850cc9e767f0dc0d3896bfd0f9",
"author": {
"name": "Sidney Jones"
}
}
}
]
}
}
]
},
"__typename": "WorkItemWidgetNotes"
},
{
"dueDate": null,
"isFixed": false,
"startDate": null,
"__typename": "WorkItemWidgetStartAndDueDate"
},
{
"type": "HEALTH_STATUS",
"healthStatus": null,
"__typename": "WorkItemWidgetHealthStatus"
},
{
"__typename": "WorkItemWidgetVerificationStatus"
},
{
"__typename": "WorkItemWidgetNotifications"
},
{
"downvotes": 0,
"upvotes": 0,
"awardEmoji": {
"nodes": []
},
"__typename": "WorkItemWidgetAwardEmoji"
},
{
"__typename": "WorkItemWidgetLinkedItems"
},
{
"__typename": "WorkItemWidgetCurrentUserTodos"
},
{
"__typename": "WorkItemWidgetRolledupDates"
},
{
"__typename": "WorkItemWidgetParticipants"
},
{
"__typename": "WorkItemWidgetWeight"
},
{
"__typename": "WorkItemWidgetTimeTracking"
},
{
"color": "#1068bf",
"textColor": "#FFFFFF",
"__typename": "WorkItemWidgetColor"
}
]
}
}
}
}使用组件创建工作项 Epic
使用组件作为 input 参数的一部分来创建或更新工作项。
例如,运行以下查询以创建一个包含以下内容的 Epic:
- 标题
- 描述
- 颜色
- 健康状态
- 开始日期
- 截止日期
- 负责人
mutation createEpicWithWidgets {
workItemCreate(
input: {
title: "New work item epic"
namespacePath: "gitlab-org"
workItemTypeId: "gid://gitlab/WorkItems::Type/<WorkItemTypeID>"
colorWidget: { color: "#e24329" }
descriptionWidget: { description: "My new plans ..." }
healthStatusWidget: { healthStatus: onTrack }
startAndDueDateWidget: { startDate: "2024-10-12", dueDate: "2024-12-12", isFixed: true }
assigneesWidget: { assigneeIds: "gid://gitlab/User/<UserID>" }
}
) {
workItem {
id
title
description
widgets {
... on WorkItemWidgetColor {
color
textColor
__typename
}
... on WorkItemWidgetAssignees {
assignees {
nodes {
id
name
}
}
__typename
}
... on WorkItemWidgetHealthStatus {
healthStatus
__typename
}
... on WorkItemWidgetStartAndDueDate {
startDate
dueDate
isFixed
__typename
}
}
}
}
}示例响应:
{
"data": {
"workItemCreate": {
"workItem": {
"id": "gid://gitlab/WorkItem/2252",
"title": "New epic",
"description": "My new plans ...",
"widgets": [
{
"assignees": {
"nodes": [
{
"id": "gid://gitlab/User/46",
"name": "Jane Smith"
}
]
},
"__typename": "WorkItemWidgetAssignees"
},
{
"color": "#e24329",
"textColor": "#FFFFFF",
"__typename": "WorkItemWidgetColor"
},
{
"healthStatus": "onTrack",
"__typename": "WorkItemWidgetHealthStatus"
},
{
"startDate": "2024-10-12",
"dueDate": "2024-12-12",
"isFixed": true,
"__typename": "WorkItemWidgetStartAndDueDate"
}
]
}
}
}
}使用组件更新工作项 Epic
要编辑工作项,请重用使用组件创建工作项 Epic中的组件输入,但改用
workItemUpdate 变更操作。
获取工作项的全局 ID(格式为 gid://gitlab/WorkItem/<WorkItemID>),并将其用作 input 的 id:
mutation updateEpicWorkItemWithWidgets {
workItemUpdate(
input: {
id: "gid://gitlab/WorkItem/<WorkItemID>"
title: "Updated work item epic title"
colorWidget: { color: "#fc6d26" }
descriptionWidget: { description: "My other new plans ..." }
healthStatusWidget: { healthStatus: onTrack }
startAndDueDateWidget: { startDate: "2025-10-12", dueDate: "2025-12-12", isFixed: true }
assigneesWidget: { assigneeIds: "gid://gitlab/User/45" }
}
) {
workItem {
id
title
description
widgets {
... on WorkItemWidgetColor {
color
textColor
__typename
}
... on WorkItemWidgetAssignees {
assignees {
nodes {
id
name
}
}
__typename
}
... on WorkItemWidgetHealthStatus {
healthStatus
__typename
}
... on WorkItemWidgetStartAndDueDate {
startDate
dueDate
isFixed
__typename
}
}
}
}
}示例响应:
{
"data": {
"workItemUpdate": {
"workItem": {
"id": "gid://gitlab/WorkItem/2252",
"title": "Updated work item epic title",
"description": "My other new plans ...",
"widgets": [
{
"assignees": {
"nodes": [
{
"id": "gid://gitlab/User/45",
"name": "Ardella Williamson"
}
]
},
"__typename": "WorkItemWidgetAssignees"
},
{
"color": "#fc6d26",
"textColor": "#FFFFFF",
"__typename": "WorkItemWidgetColor"
},
{
"healthStatus": "onTrack",
"__typename": "WorkItemWidgetHealthStatus"
},
{
"startDate": "2025-10-12",
"dueDate": "2025-12-12",
"isFixed": true,
"__typename": "WorkItemWidgetStartAndDueDate"
}
]
}
}
}
}删除 Epic 工作项
要删除 Epic 工作项,请使用 workItemDelete 变更操作:
mutation deleteEpicWorkItem {
workItemDelete(input: { id: "gid://gitlab/WorkItem/<WorkItemID>" }) {
clientMutationId
errors
namespace {
id
}
}
}示例响应:
{
"data": {
"workItemDelete": {
"clientMutationId": null,
"errors": [],
"namespace": {
"id": "gid://gitlab/Group/24"
}
}
}
}