Add memberRoleId argument to BaseAccessLevelInputType and update BranchRules::UpdateService
## Context
| | |
|---|---|
| **Phase** | 3 of 6 |
| **Parallel with** | https://gitlab.com/gitlab-org/gitlab/-/work_items/594880+ <br> https://gitlab.com/gitlab-org/gitlab/-/work_items/594881+ <br> https://gitlab.com/gitlab-org/gitlab/-/work_items/594882+ <br> https://gitlab.com/gitlab-org/gitlab/-/work_items/594884+ |
| **Blocked by** | https://gitlab.com/gitlab-org/gitlab/-/work_items/594877+ <br> https://gitlab.com/gitlab-org/gitlab/-/work_items/594878+ <br> https://gitlab.com/gitlab-org/gitlab/-/work_items/594879+ |
| **Unblocks** | https://gitlab.com/gitlab-org/gitlab/-/work_items/594889+ |
## Summary
Add `memberRoleId` as an accepted argument to the `BaseAccessLevelInputType` GraphQL input type, and update `EE::BranchRules::UpdateService` permitted params so that `member_role_id` flows through the `branchRuleUpdate` mutation.
## Background
The GraphQL mutation `branchRuleUpdate` accepts `branch_protection` input of type `BranchProtectionInputType`, which contains arrays of `push_access_levels` and `merge_access_levels` of type `BaseAccessLevelInputType`. The EE extension of this input type currently accepts `user_id` and `group_id` as optional arguments.
The `EE::BranchRules::UpdateService` defines `permitted_params` which explicitly allowlists the keys that may be passed through to the protected branches create/update service. `member_role_id` must be added there.
## Relevant files
- `ee/app/graphql/ee/types/branch_protections/base_access_level_input_type.rb` — add argument here
- `ee/app/services/ee/branch_rules/update_service.rb` — add to `permitted_params`
- `app/graphql/types/branch_protections/base_access_level_input_type.rb` — CE base (do not modify)
## Changes required
### `ee/app/graphql/ee/types/branch_protections/base_access_level_input_type.rb`
```ruby
module EE
module Types
module BranchProtections
module BaseAccessLevelInputType
extend ActiveSupport::Concern
prepended do
argument :user_id, ::Types::GlobalIDType[::User],
prepare: ->(global_id, _ctx) { global_id.model_id.to_i },
required: false,
description: 'User associated with the access level.'
argument :group_id, ::Types::GlobalIDType[::Group],
prepare: ->(global_id, _ctx) { global_id.model_id.to_i },
required: false,
description: 'Group associated with the access level.'
argument :member_role_id, ::Types::GlobalIDType[::MemberRole],
prepare: ->(global_id, _ctx) { global_id.model_id.to_i },
required: false,
description: 'Custom member role associated with the access level.'
end
end
end
end
end
```
### `ee/app/services/ee/branch_rules/update_service.rb`
```ruby
override :permitted_params
def permitted_params
[
:name,
{
branch_protection: [
:allow_force_push,
:code_owner_approval_required,
{
push_access_levels: %i[access_level deploy_key_id user_id group_id member_role_id],
merge_access_levels: %i[access_level user_id group_id member_role_id],
unprotect_access_levels: %i[access_level user_id group_id member_role_id]
}
]
}
]
end
```
Note: `unprotect_access_levels` is not currently in `permitted_params` — check if it should be added here or if it is handled separately.
## GraphQL mutation example
```graphql
mutation {
branchRuleUpdate(input: {
id: "gid://gitlab/Projects::BranchRule/1"
name: "main"
branchProtection: {
mergeAccessLevels: [
{ memberRoleId: "gid://gitlab/MemberRole/42" }
]
}
}) {
errors
branchRule {
branchProtection {
mergeAccessLevels {
nodes {
accessLevelDescription
memberRole { id name }
}
}
}
}
}
}
```
## Testing
- Mutation spec: `branchRuleUpdate` with `memberRoleId` creates access level row with correct `member_role_id`
- Mutation spec: passing invalid `memberRoleId` (wrong namespace) returns errors
- Mutation spec: removing a custom role access level by excluding it from the input
- `permitted_params` spec: verify `member_role_id` is in the allowlist
## Dependencies
- Issue 3 (EE concern) — model must accept `member_role_id`
- Issue 9 (GraphQL type) — `memberRole` field should be available in the mutation response
## Labels
issue