Description
The ProtectedBranch resource currently ignores UserID and GroupID fields in PushAccessLevels, MergeAccessLevels, and UnprotectAccessLevels, only using the AccessLevel field. This prevents users from configuring granular, user-specific or group-specific branch protection rules that GitLab's API supports.
Current Behavior
When creating a ProtectedBranch with user or group-specific access:
apiVersion: projects.gitlab.m.crossplane.io/v1alpha1
kind: ProtectedBranch
metadata:
name: example-protected-branch
spec:
forProvider:
projectId: "123"
branchName: "main"
pushAccessLevels:
- accessLevel: 40 # Maintainer level
- userId: 456 # Specific user
- groupId: 789 # Specific group
mergeAccessLevels:
- accessLevel: 30 # Developer level
- groupId: 789 # Specific group
Result: Only the accessLevel is applied; userId and groupId are silently ignored.
Expected Behavior
All access level entries (including user-specific and group-specific rules) should be applied to the protected branch, allowing for granular access control as supported by GitLab's API.
Root Cause
In pkg/namespaced/clients/projects/protectedbranch.go (lines 174-188), the GenerateProtectRepositoryBranchesOptions function only extracts the first element from each access level array and only uses the AccessLevel field:
if len(p.PushAccessLevels) > 0 && p.PushAccessLevels[0].AccessLevel != nil {
accessLevel := gitlab.AccessLevelValue(*p.PushAccessLevels[0].AccessLevel)
opt.PushAccessLevel = &accessLevel // ← Only uses AccessLevel from first element
}
// UserID and GroupID are never used
The same pattern applies to MergeAccessLevels and UnprotectAccessLevels.
Use Cases Being Blocked
- CI/CD Bot Access: Allow only a specific CI/CD bot user to push to protected branches
- Release Team: Restrict push access to a specific "Release Team" group
- Mixed Permissions: Combine role-based, user-specific, and group-specific access rules
- Security Teams: Allow only security team members to modify certain branches
Proposed Solution
Update the client code to properly handle all elements in the access level arrays and include UserID and GroupID:
// Pseudocode - proper implementation would use GitLab client-go's actual structs
opt.AllowedToPush = []gitlab.BranchAccessDescription{}
for _, level := range p.PushAccessLevels {
access := gitlab.BranchAccessDescription{}
if level.AccessLevel != nil {
access.AccessLevel = level.AccessLevel
}
if level.UserID != nil {
access.UserID = level.UserID
}
if level.GroupID != nil {
access.GroupID = level.GroupID
}
opt.AllowedToPush = append(opt.AllowedToPush, access)
}
// Similar for MergeAccessLevels and UnprotectAccessLevels
Files Affected
pkg/namespaced/clients/projects/protectedbranch.go - Lines 159-190
pkg/cluster/clients/projects/zz_protectedbranch.go - Similar pattern
Additional Context
The CRD types correctly define these fields as *int64:
apis/namespaced/projects/v1alpha1/protectedbranch_types.go:42 - UserID *int64
apis/namespaced/projects/v1alpha1/protectedbranch_types.go:46 - GroupID *int64
This is a pre-existing limitation, not introduced by recent changes. The types are correct; only the client implementation needs updating.
References
Description
The
ProtectedBranchresource currently ignoresUserIDandGroupIDfields inPushAccessLevels,MergeAccessLevels, andUnprotectAccessLevels, only using theAccessLevelfield. This prevents users from configuring granular, user-specific or group-specific branch protection rules that GitLab's API supports.Current Behavior
When creating a ProtectedBranch with user or group-specific access:
Result: Only the
accessLevelis applied;userIdandgroupIdare silently ignored.Expected Behavior
All access level entries (including user-specific and group-specific rules) should be applied to the protected branch, allowing for granular access control as supported by GitLab's API.
Root Cause
In
pkg/namespaced/clients/projects/protectedbranch.go(lines 174-188), theGenerateProtectRepositoryBranchesOptionsfunction only extracts the first element from each access level array and only uses theAccessLevelfield:The same pattern applies to
MergeAccessLevelsandUnprotectAccessLevels.Use Cases Being Blocked
Proposed Solution
Update the client code to properly handle all elements in the access level arrays and include
UserIDandGroupID:Files Affected
pkg/namespaced/clients/projects/protectedbranch.go- Lines 159-190pkg/cluster/clients/projects/zz_protectedbranch.go- Similar patternAdditional Context
The CRD types correctly define these fields as
*int64:apis/namespaced/projects/v1alpha1/protectedbranch_types.go:42-UserID *int64apis/namespaced/projects/v1alpha1/protectedbranch_types.go:46-GroupID *int64This is a pre-existing limitation, not introduced by recent changes. The types are correct; only the client implementation needs updating.
References