Verified Commit 00925c26 authored by Florian Forster's avatar Florian Forster
Browse files

feat(workitems): Add WorkItems service with Get methods

Introduce a new `WorkItemsService` to provide high-level API access to GitLab's
work items (epics, issues, and tasks) through GraphQL.

This implementation includes:
- `GetWorkItem(projectPath, iid)`: Get work item by project path and IID
- `GetWorkItemByID(gid)`: Get work item by global ID (string or int64)
- `WorkItem` struct with common fields in idiomatic Go types
- Type conversion utilities for GraphQL responses:
  - `gidGQL`: Parse global IDs (e.g. "gid://gitlab/WorkItem/179785913")
  - `iidGQL`: Convert IID strings to int64
  - `userCoreGQL`: Convert GraphQL UserCore to BasicUser
  - `workItemGQL`: Internal GraphQL response representation with unwrap()
- Comprehensive test coverage including success and error scenarios
- Generated mock interfaces and client registration

This addresses the current gaps in the GitLab Go client:
- No API support for tasks
- Deprecated REST API for epics (replaced by work items)
- High friction for GraphQL usage (manual query construction,
  custom struct definitions, type conversions)

The service follows established patterns in the Go client (service-based
architecture, `RequestOptionFunc` support, `ErrNotFound` for missing resources,
separate internal/public types).

Issue: #2213
parent 80379c66
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -302,6 +302,7 @@ type Client struct {
	Validate                         ValidateServiceInterface
	Version                          VersionServiceInterface
	Wikis                            WikisServiceInterface
	WorkItems                        WorkItemsServiceInterface
}

// Interceptor is used to build a *http.Client request pipeline,
@@ -623,6 +624,7 @@ func NewAuthSourceClient(as AuthSource, options ...ClientOptionFunc) (*Client, e
	c.Validate = &ValidateService{client: c}
	c.Version = &VersionService{client: c}
	c.Wikis = &WikisService{client: c}
	c.WorkItems = &WorkItemsService{client: c}

	return c, nil
}
+1 −0
Original line number Diff line number Diff line
@@ -162,4 +162,5 @@ var serviceMap = map[any]any{
	&ValidateService{}:                         (*ValidateServiceInterface)(nil),
	&VersionService{}:                          (*VersionServiceInterface)(nil),
	&WikisService{}:                            (*WikisServiceInterface)(nil),
	&WorkItemsService{}:                        (*WorkItemsServiceInterface)(nil),
}
+56 −0
Original line number Diff line number Diff line
{
    "data": {
        "namespace": {
            "workItems": {
                "nodes": [
                    {
                        "id": "gid://gitlab/WorkItem/179785913",
                        "iid": "756",
                        "workItemType": {
                            "name": "Task"
                        },
                        "state": "OPEN",
                        "title": "Update Helm charts to use Argo Rollouts for progressive deployments",
                        "description": "## Overview\n\nUpdate Runway Helm charts to generate Argo Rollout resources ...",
                        "author": {
                            "id": "gid://gitlab/User/5532616",
                            "username": "swainaina",
                            "name": "Silvester Wainaina",
                            "state": "active",
                            "createdAt": "2020-03-02T06:29:14Z",
                            "avatarUrl": "/uploads/-/system/user/avatar/5532616/avatar.png",
                            "webUrl": "https://gitlab.com/swainaina"
                        },
                        "createdAt": "2026-01-06T15:09:24Z",
                        "updatedAt": "2026-01-09T13:06:08Z",
                        "closedAt": null,
                        "webUrl": "https://gitlab.com/gitlab-com/gl-infra/platform/runway/team/-/work_items/756",
                        "features": {
                            "assignees": {
                                "assignees": {
                                    "nodes": [
                                        {
                                            "id": "gid://gitlab/User/5532616",
                                            "username": "swainaina",
                                            "name": "Silvester Wainaina",
                                            "state": "active",
                                            "createdAt": "2020-03-02T06:29:14Z",
                                            "avatarUrl": "/uploads/-/system/user/avatar/5532616/avatar.png",
                                            "webUrl": "https://gitlab.com/swainaina"
                                        }
                                    ]
                                }
                            },
                            "status": {
                                "status": {
                                    "name": "New"
                                }
                            }
                        }
                    }
                ]
            }
        }
    },
    "correlationId": "9c61267151cfcd9b-IAD"
}
+50 −0
Original line number Diff line number Diff line
{
    "data": {
        "workItem": {
            "id": "gid://gitlab/WorkItem/179785913",
            "iid": "756",
            "workItemType": {
                "name": "Task"
            },
            "state": "OPEN",
            "title": "Update Helm charts to use Argo Rollouts for progressive deployments",
            "description": "## Overview\n\nUpdate Runway Helm charts to generate Argo Rollout resources ...",
            "author": {
                "id": "gid://gitlab/User/5532616",
                "username": "swainaina",
                "name": "Silvester Wainaina",
                "state": "active",
                "createdAt": "2020-03-02T06:29:14Z",
                "avatarUrl": "/uploads/-/system/user/avatar/5532616/avatar.png",
                "webUrl": "https://gitlab.com/swainaina"
            },
            "createdAt": "2026-01-06T15:09:24Z",
            "updatedAt": "2026-01-09T13:06:08Z",
            "closedAt": null,
            "webUrl": "https://gitlab.com/gitlab-com/gl-infra/platform/runway/team/-/work_items/756",
            "features": {
                "assignees": {
                    "assignees": {
                        "nodes": [
                            {
                                "id": "gid://gitlab/User/5532616",
                                "username": "swainaina",
                                "name": "Silvester Wainaina",
                                "state": "active",
                                "createdAt": "2020-03-02T06:29:14Z",
                                "avatarUrl": "/uploads/-/system/user/avatar/5532616/avatar.png",
                                "webUrl": "https://gitlab.com/swainaina"
                            }
                        ]
                    }
                },
                "status": {
                    "status": {
                        "name": "New"
                    }
                }
            }
        }
    },
    "correlationId": "9c611a629371cd9b-IAD"
}
+1 −0
Original line number Diff line number Diff line
@@ -162,3 +162,4 @@ package testing
//go:generate go run go.uber.org/mock/mockgen@v0.6.0 -typed -destination=validate_mock.go -write_package_comment=false -package=testing gitlab.com/gitlab-org/api/client-go ValidateServiceInterface
//go:generate go run go.uber.org/mock/mockgen@v0.6.0 -typed -destination=version_mock.go -write_package_comment=false -package=testing gitlab.com/gitlab-org/api/client-go VersionServiceInterface
//go:generate go run go.uber.org/mock/mockgen@v0.6.0 -typed -destination=wikis_mock.go -write_package_comment=false -package=testing gitlab.com/gitlab-org/api/client-go WikisServiceInterface
//go:generate go run go.uber.org/mock/mockgen@v0.6.0 -typed -destination=workitems_mock.go -write_package_comment=false -package=testing gitlab.com/gitlab-org/api/client-go WorkItemsServiceInterface
Loading