Let fine-grained tokens read closing merge requests and related branches
What does this MR do and why?
A fine-grained personal access token gets no closing merge requests or related branches for a work item it can read, and workItemAddClosingMergeRequest returns null for the link it creates. The two types declare no authorize_granular_token directive, so no fine-grained token can read them.
| Type | Returned by | Declares |
|---|---|---|
WorkItemClosingMergeRequest |
WorkItemWidgetDevelopment.closingMergeRequests and the workItemAddClosingMergeRequest payload |
parent_authorizes: :read_work_item |
WorkItemRelatedBranch |
WorkItemWidgetDevelopment.relatedBranches |
parent_authorizes: :read_branch |
A closing link is returned only below a parent that authorizes the token, a WorkItem with read_work_item or the mutation with update_work_item. Its merge request keeps its own read_merge_request check, which a new example covers.
Related branches are branch names of the project, and comparePath names its default branch: data the Branch type gates with read_branch on the project, which Work Item: Read does not grant. So relatedBranches checks read_branch on the project of the work item with a field directive, and the development widget delegates project to its work item for that check.
Both types leave authorization_todo.txt. WorkItemLinkedResource, which the linked resources widget returns, stays on it as on master, for a separate change.
References
- Related to #593878, the GraphQL gaps left for fine-grained tokens.
- !266046 (merged) did the same for linked items.
I found this while working on gitlab-mcp-server.
Screenshots or screen recordings
Not applicable: no UI change.
How to set up and validate locally
-
Give a work item a closing merge request and a branch named after it, and create a fine-grained token with Work Item: Read and Branch: Read on its project.
-
Run with it:
query { workItem(id: "gid://gitlab/WorkItem/<id>") { features { development { closingMergeRequests { nodes { id } } relatedBranches { nodes { name } } } } } } -
On master the token reads neither the link nor the branch name; on this branch it reads both. With Work Item: Read alone it reads the link, and
relatedBranchesisnull.
I ran steps 2 and 3 as the closing merge requests and related branches examples of spec/requests/api/graphql/work_item_spec.rb, which post the two halves of this query.
Checks I ran (Ruby 3.3.11)
- With master's types and todo list: 13 examples, 8 failures, all in the new or changed examples.
- With the types of the previous version (d6cbc3ba): 7 examples, 4 failures, all new; a token with Work Item: Read alone got the branch name and a
comparePathnamingmaster. - On this branch, the request, type, model and entity specs the change reaches: 332 examples, 0 failures, 5 pending (skips of the shared examples).
gitlab:permissions:validate, RuboCop and the commit linter pass;graphql:compile_docsadds therelatedBranchesrow under Branch: Read, and bothcompile_docstasks change nothing more. Withparent_authorizes: :read_branchand no field directive,gitlab:permissions:validatefails onWorkItemWidgetDevelopment.relatedBranches. Left to the pipeline: Ruby 3.4.10 and FOSS.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.