Skip to content

Commit 6237de1

Browse files
committed
feat(gitlab): expand group listing filters and harden access-level enum
- list_groups: add visibility, min_access_level, and all_available filters (documented on GET /groups) plus order_by/sort, now surfaced in the block and forwarded in params - order_by widened to include GitLab's documented 'similarity' value - access-level enum label 'Minimal Access' -> 'Minimal access' to match GitLab verbatim; coercion already case-insensitive - min_access_level guard rejects 0 (GitLab floor is 5); reuse the access-level enum for the block dropdown (drops 'No access') - tests: out-of-enum numeric-string coercion case + full list_groups filter mapping
1 parent 65e38db commit 6237de1

6 files changed

Lines changed: 111 additions & 5 deletions

File tree

apps/sim/blocks/blocks/gitlab.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,13 +242,23 @@ describe('GitLabBlock group operations', () => {
242242
owned: true,
243243
searchQuery: 'plat',
244244
groupsTopLevelOnly: true,
245+
visibility: 'private',
246+
groupMinAccessLevel: '30',
247+
groupAllAvailable: true,
248+
groupOrderBy: 'similarity',
249+
sortOrder: 'asc',
245250
perPage: '50',
246251
page: '2',
247252
})
248253
expect(params).toMatchObject({
249254
owned: true,
250255
search: 'plat',
251256
topLevelOnly: true,
257+
visibility: 'private',
258+
minAccessLevel: 30,
259+
allAvailable: true,
260+
orderBy: 'similarity',
261+
sort: 'asc',
252262
perPage: 50,
253263
page: 2,
254264
})

apps/sim/blocks/blocks/gitlab.ts

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,34 @@ Return ONLY the commit message - no explanations, no extra text.`,
10101010
value: ['gitlab_list_groups'],
10111011
},
10121012
},
1013+
{
1014+
id: 'groupAllAvailable',
1015+
title: 'All Available',
1016+
type: 'switch',
1017+
mode: 'advanced',
1018+
description:
1019+
'Include groups you can access but are not a member of (ignored when Owned Only or Minimum Access Level is set)',
1020+
condition: {
1021+
field: 'operation',
1022+
value: ['gitlab_list_groups'],
1023+
},
1024+
},
1025+
{
1026+
id: 'groupMinAccessLevel',
1027+
title: 'Minimum Access Level',
1028+
type: 'dropdown',
1029+
options: [
1030+
{ label: 'Any', id: '' },
1031+
...GITLAB_ACCESS_LEVEL_OPTIONS.filter((option) => option.id !== '0'),
1032+
],
1033+
value: () => '',
1034+
mode: 'advanced',
1035+
description: 'Only groups where you have at least this access level',
1036+
condition: {
1037+
field: 'operation',
1038+
value: ['gitlab_list_groups'],
1039+
},
1040+
},
10131041
{
10141042
id: 'membership',
10151043
title: 'Member Only',
@@ -1035,7 +1063,7 @@ Return ONLY the commit message - no explanations, no extra text.`,
10351063
mode: 'advanced',
10361064
condition: {
10371065
field: 'operation',
1038-
value: ['gitlab_list_projects'],
1066+
value: ['gitlab_list_projects', 'gitlab_list_groups'],
10391067
},
10401068
},
10411069
// List-issues filters
@@ -1105,6 +1133,24 @@ Return ONLY the commit message - no explanations, no extra text.`,
11051133
value: ['gitlab_list_projects'],
11061134
},
11071135
},
1136+
{
1137+
id: 'groupOrderBy',
1138+
title: 'Order By',
1139+
type: 'dropdown',
1140+
options: [
1141+
{ label: 'Default (name)', id: '' },
1142+
{ label: 'Name', id: 'name' },
1143+
{ label: 'Path', id: 'path' },
1144+
{ label: 'ID', id: 'id' },
1145+
{ label: 'Similarity (requires search)', id: 'similarity' },
1146+
],
1147+
value: () => '',
1148+
mode: 'advanced',
1149+
condition: {
1150+
field: 'operation',
1151+
value: ['gitlab_list_groups'],
1152+
},
1153+
},
11081154
{
11091155
id: 'issueOrderBy',
11101156
title: 'Order By',
@@ -1200,6 +1246,7 @@ Return ONLY the commit message - no explanations, no extra text.`,
12001246
field: 'operation',
12011247
value: [
12021248
'gitlab_list_projects',
1249+
'gitlab_list_groups',
12031250
'gitlab_list_issues',
12041251
'gitlab_list_merge_requests',
12051252
'gitlab_list_pipelines',
@@ -1985,6 +2032,13 @@ Return ONLY the JSON array - no explanations, no extra text.`,
19852032
owned: params.owned || undefined,
19862033
search: params.searchQuery?.trim() || undefined,
19872034
topLevelOnly: params.groupsTopLevelOnly || undefined,
2035+
visibility: params.visibility || undefined,
2036+
minAccessLevel: params.groupMinAccessLevel
2037+
? Number(params.groupMinAccessLevel)
2038+
: undefined,
2039+
allAvailable: params.groupAllAvailable || undefined,
2040+
orderBy: params.groupOrderBy || undefined,
2041+
sort: params.sortOrder || undefined,
19882042
perPage: params.perPage ? Number(params.perPage) : undefined,
19892043
page: params.page ? Number(params.page) : undefined,
19902044
}
@@ -2815,7 +2869,7 @@ Return ONLY the JSON array - no explanations, no extra text.`,
28152869
searchQuery: { type: 'string', description: 'Search filter for project/issue listings' },
28162870
owned: { type: 'boolean', description: 'Only owned projects' },
28172871
membership: { type: 'boolean', description: 'Only projects the user is a member of' },
2818-
visibility: { type: 'string', description: 'Project visibility filter' },
2872+
visibility: { type: 'string', description: 'Project or group visibility filter' },
28192873
assigneeId: { type: 'number', description: 'Assignee user ID filter for issues' },
28202874
milestoneTitle: { type: 'string', description: 'Milestone title filter for issues' },
28212875
sourceBranchFilter: { type: 'string', description: 'Source branch filter for MR listings' },
@@ -2902,6 +2956,18 @@ Return ONLY the JSON array - no explanations, no extra text.`,
29022956
type: 'boolean',
29032957
description: 'Limit group listings to top-level groups, excluding subgroups',
29042958
},
2959+
groupOrderBy: {
2960+
type: 'string',
2961+
description: "Order group listings by field ('name', 'path', 'id', or 'similarity')",
2962+
},
2963+
groupAllAvailable: {
2964+
type: 'boolean',
2965+
description: 'Include groups the user can access but is not a member of',
2966+
},
2967+
groupMinAccessLevel: {
2968+
type: 'string',
2969+
description: 'Minimum access level filter for group listings (integer access level)',
2970+
},
29052971
membershipType: {
29062972
type: 'string',
29072973
description: "Membership source filter ('Project' or 'Namespace'; '' for all)",

apps/sim/tools/gitlab/list_groups.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,32 @@ export const gitlabListGroupsTool: ToolConfig<GitLabListGroupsParams, GitLabList
3939
visibility: 'user-or-llm',
4040
description: 'Limit to top-level groups, excluding subgroups',
4141
},
42+
visibility: {
43+
type: 'string',
44+
required: false,
45+
visibility: 'user-or-llm',
46+
description: 'Filter by visibility: public, internal, or private',
47+
},
48+
minAccessLevel: {
49+
type: 'number',
50+
required: false,
51+
visibility: 'user-or-llm',
52+
description:
53+
'Only groups where the current user has at least this access level, as an integer (e.g. 30 for Developer). Valid values: 5, 10, 15, 20, 25, 30, 40, 50.',
54+
},
55+
allAvailable: {
56+
type: 'boolean',
57+
required: false,
58+
visibility: 'user-or-llm',
59+
description:
60+
'Include all groups the user can access, not only groups they are a member of (ignored when owned or a minimum access level is set)',
61+
},
4262
orderBy: {
4363
type: 'string',
4464
required: false,
4565
visibility: 'user-or-llm',
46-
description: 'Order by field (name, path, id)',
66+
description:
67+
'Order by field (name, path, id, similarity). similarity requires a search term.',
4768
},
4869
sort: {
4970
type: 'string',
@@ -71,6 +92,11 @@ export const gitlabListGroupsTool: ToolConfig<GitLabListGroupsParams, GitLabList
7192
if (params.owned) queryParams.append('owned', 'true')
7293
if (params.search) queryParams.append('search', params.search)
7394
if (params.topLevelOnly) queryParams.append('top_level_only', 'true')
95+
if (params.visibility) queryParams.append('visibility', params.visibility)
96+
if (params.minAccessLevel && params.minAccessLevel > 0) {
97+
queryParams.append('min_access_level', String(params.minAccessLevel))
98+
}
99+
if (params.allAvailable) queryParams.append('all_available', 'true')
74100
if (params.orderBy) queryParams.append('order_by', params.orderBy)
75101
if (params.sort) queryParams.append('sort', params.sort)
76102
if (params.perPage) queryParams.append('per_page', String(params.perPage))

apps/sim/tools/gitlab/types.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,10 @@ export interface GitLabListGroupsParams extends GitLabBaseParams {
273273
owned?: boolean
274274
search?: string
275275
topLevelOnly?: boolean
276-
orderBy?: 'name' | 'path' | 'id'
276+
visibility?: 'public' | 'internal' | 'private'
277+
minAccessLevel?: number
278+
allAvailable?: boolean
279+
orderBy?: 'name' | 'path' | 'id' | 'similarity'
277280
sort?: 'asc' | 'desc'
278281
perPage?: number
279282
page?: number

apps/sim/tools/gitlab/utils.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ describe('coerceGitLabAccessLevel', () => {
126126
it('throws for values outside the enum', () => {
127127
expect(() => coerceGitLabAccessLevel(999)).toThrow(InvalidGitLabAccessLevelError)
128128
expect(() => coerceGitLabAccessLevel(31)).toThrow(InvalidGitLabAccessLevelError)
129+
expect(() => coerceGitLabAccessLevel('35')).toThrow(InvalidGitLabAccessLevelError)
129130
expect(() => coerceGitLabAccessLevel('root')).toThrow(InvalidGitLabAccessLevelError)
130131
expect(() => coerceGitLabAccessLevel('')).toThrow(InvalidGitLabAccessLevelError)
131132
expect(() => coerceGitLabAccessLevel(' ')).toThrow(InvalidGitLabAccessLevelError)

apps/sim/tools/gitlab/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export function getGitLabApiBase(rawHost: unknown): string {
7777
*/
7878
export const GITLAB_ACCESS_LEVELS = [
7979
{ name: 'No access', value: 0 },
80-
{ name: 'Minimal Access', value: 5 },
80+
{ name: 'Minimal access', value: 5 },
8181
{ name: 'Guest', value: 10 },
8282
{ name: 'Planner', value: 15 },
8383
{ name: 'Reporter', value: 20 },

0 commit comments

Comments
 (0)