feat(workitems): Add an initial "Work Items" service with "Get" and "List" methods.

What does this MR do?

This MR introduces an initial WorkItemsService to the GitLab Go client, providing high-level API access to GitLab's work items (epics, issues, and tasks) through GraphQL. This first iteration implements two methods for retrieving work items: GetWorkItem and ListWorkItems.

Why was this MR needed?

The GitLab Go package currently lacks convenient API access for work items:

  • No task support: Tasks have no high-level API at all
  • Deprecated epic API: The REST API for epics is deprecated in favor of work items
  • GraphQL friction: While GraphQL.Do() allows arbitrary queries, it forces developers to:
    • Learn GraphQL syntax and construct queries manually
    • Define custom Go structs matching their query structure
    • Handle type conversions (e.g., IID returned as string but typically needed as int64)

What's in this MR?

Core implementation

  • WorkItemsService with two retrieval methods:
    • GetWorkItem(fullPath string, iid int64) - Get by project/group path and IID
    • ListWorkItems(fullPath string, opt *ListWorkItemsOptions) - List and filter work items in a namespace
  • WorkItem struct exposing common fields in idiomatic Go types
  • ListWorkItemsOptions struct supporting comprehensive filtering:
    • Assignee, author, and state filters
    • Label, milestone, and iteration filters
    • Time-based filters (created, updated, closed, due dates)
    • Pagination support (first, last, after, before)
    • Search and sorting capabilities
  • Internal GraphQL query handling with automatic response parsing
  • WithNext request option for implementation-agnostic pagination
    • Updated Scan2 to use WithNext
    • Added example, demonstrating how to use the function
  • PageInfo: new type with GraphQL's cursor-based pagination information; has been added to Response

Type conversion utilities

  • gidGQL: Parses GraphQL global IDs (e.g., gid://gitlab/WorkItem/179785913) into structured type + numeric ID
  • iidGQL: Converts IID strings to int64
  • userCoreBasicGQL: Converts GraphQL UserCore to BasicUser (used for author and assignees)
  • workItemGQL: Internal representation matching GraphQL response structure, with unwrap() method to convert to public WorkItem type
  • connectionGQL[T any]: Internal representation of GraphQL connection responses

Testing

  • Comprehensive test coverage including:
    • Successful work item retrieval by project/IID
    • Not found scenarios (non-existent IID, non-existent project)
    • List operations with various filter combinations
    • Query validation against GraphQL schema
    • Embedded testdata with real GraphQL response structure
    • ListWorkItems iteration / pagination

Implementation notes

This follows established patterns in the Go client:

  • Service-based architecture consistent with IssuesService, MergeRequestsService, etc.
  • RequestOptionFunc support for extensibility
  • ErrNotFound for non-existent resources
  • Separate internal GraphQL types (workItemGQL, userCoreBasicGQL) from public API types (WorkItem, BasicUser)

What's next?

This is an initial implementation establishing the foundation. Future work will add:

  • Create/update operations
  • Additional work item fields as needed

Related to #2213

Edited by Florian Forster

Merge request reports

Loading