Filter a groups projects by compliance framework - backend
In order to see which projects have a particular compliance framework applied to them as shown in the designs here: #385303 (closed) we will need to be able to query for groups projects with a new filter.
Proposal
The frontend implementation plan had a suggestion to use a GraphQL query for fetching this data, which would return results similar to this API endpoint ( https://docs.gitlab.com/ee/api/groups.html#list-a-groups-projects ). Allow passing additional parameter, e.g.
compliance_framework: "1234"
(show all projects in the group which have compliance_framework with ID 1234 applied)
It would be ideal if this filter could work in addition to searching projects, e.g.
compliance_framework: "1234", search: "foo"
(show all projects in the group which have compliance_framework with ID 1234 applied, that also match search query foo)
From the discussion below we should support both including projects with the given framework, but also be able to exclude projects with a given framework. We should also be able to filter for projects which do not have any framework applied yet.
Example
We have 3 projects: project_a project_b and project_c.
-
project_a has a compliance_framework with id 1
-
project_b has a compliance framework with id 2
-
project_c has no compliance framework
-
for
Id: 1, we should return project_a only -
for
not id: 1we should return both project_b and project_c. -
for
presence 'ANY'we should return project_a and project b only. -
for
presence 'NONE'we should return only project_c
Proposed implementation plan
- In Namespace projects resolver add params complianceFrameworkId (int), complianceFrameworkIdNot (int), and withoutAnyComnplianceFramework (boolean).
-
complianceFrameworkIdshould return projects having compliance framework id matchingcomplianceFrameworkId -
complianceFrameworkIdNotshould return projects not having a compliance framework and not matching the compliance framework id. -
withoutComplianceFrameworkshould return projects not having a compliance framework. - following code snippet can be used in
Project.rbto implement these filters.
scope :compliance_framework_id_in, -> (id) do
joins(:compliance_framework_setting).where(compliance_framework_setting: { framework_id: id})
end
scope :compliance_framework_id_not_in, -> (id) do
left_outer_joins(:compliance_framework_setting).where.not(compliance_framework_setting: { framework_id: id }).or(
left_outer_joins(:compliance_framework_setting).where(compliance_framework_setting: { framework_id: nil }))
end
scope :without_compliance_framework, -> { where.missing(:compliance_framework_setting) }
- Write relevant test cases.
Sample Queries
query SearchGroup {
group(fullPath: "YOUR_GROUP_PATH") {
name
projects(complianceFrameworkFilters:{id: "FRAMEWORK_GID"}) {
nodes {
id
complianceFrameworks {
edges {
node {
id
}
}
}
name
}
pageInfo {
endCursor
startCursor
hasNextPage
}
}
}
}
query SearchGroup {
group(fullPath: "YOUR_GROUP_PATH") {
name
projects(complianceFrameworkFilters: {not: {id: "VALID_GID"}}) {
nodes {
id
fullPath
complianceFrameworks {
edges {
node {
id
}
}
}
name
}
pageInfo {
endCursor
startCursor
hasNextPage
}
}
}
}
query SearchGroup {
group(fullPath: "complianceframework") {
name
projects(complianceFrameworkFilters: {presence_filter: NONE}) {
nodes {
id
fullPath
complianceFrameworks {
edges {
node {
id
}
}
}
name
}
pageInfo {
endCursor
startCursor
hasNextPage
}
}
}
}
query SearchGroup {
group(fullPath: "complianceframework") {
name
projects(complianceFrameworkFilters: {presence_filter: ANY}) {
nodes {
id
fullPath
complianceFrameworks {
edges {
node {
id
}
}
}
name
}
pageInfo {
endCursor
startCursor
hasNextPage
}
}
}
}
Verification Process
- Create 1 group : compliance_framework
- Create three projects
- project_a has a compliance_framework with id 1
- project_b has a compliance framework with id 2
- project_c has no compliance framework
- Test above listed GraphQL APIs