Skip to content

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.

  1. project_a has a compliance_framework with id 1

  2. project_b has a compliance framework with id 2

  3. project_c has no compliance framework

  4. for Id: 1, we should return project_a only

  5. for not id: 1 we should return both project_b and project_c.

  6. for presence 'ANY' we should return project_a and project b only.

  7. for presence 'NONE' we should return only project_c

Proposed implementation plan

  1. In Namespace projects resolver add params complianceFrameworkId (int), complianceFrameworkIdNot (int), and withoutAnyComnplianceFramework (boolean).
  2. complianceFrameworkId should return projects having compliance framework id matching complianceFrameworkId
  3. complianceFrameworkIdNot should return projects not having a compliance framework and not matching the compliance framework id.
  4. withoutComplianceFramework should return projects not having a compliance framework.
  5. 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) }
  1. 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

  1. Create 1 group : compliance_framework
  2. Create three projects
  3. project_a has a compliance_framework with id 1
  4. project_b has a compliance framework with id 2
  5. project_c has no compliance framework
  6. Test above listed GraphQL APIs
Edited by Harsimar Sandhu