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: 1
we 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).
-
complianceFrameworkId
should return projects having compliance framework id matchingcomplianceFrameworkId
-
complianceFrameworkIdNot
should return projects not having a compliance framework and not matching the compliance framework id. -
withoutComplianceFramework
should return projects not having a compliance framework. - following code snippet can be used in
Project.rb
to 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