Add not_applicable compliance control status
What does this MR do and why?
Adds not_applicable as a status for compliance controls. Use it when a control can't be evaluated for a project, for example because the resource it checks doesn't exist. Before this change, those controls had to be reported as pass, fail, or pending, which made compliance reports misleading.
- Adds
not_applicable: 3to the control status enum. No migration is needed because thestatuscolumn has no CHECK constraint. - Lets external controls set
not_applicable, the same way they setpassandfail. This applies to bothUpdateStatusServiceand thePATCH .../compliance_external_controls/:control_id/statusREST endpoint.pendingstill can't be set from outside. - Adds a
compliance_control_status_not_applicableaudit event type. The service builds the audit event name from the new status, so the new value needs its own type definition. - The GraphQL
ProjectComplianceControlStatusenum getsNOT_APPLICABLE("Not applicable") automatically, because it is built from the Rails enum witheach_key. - Updates the generated GraphQL reference, OpenAPI spec, and audit event types docs.
Differences from the workplan
- No explicit GraphQL
value 'NOT_APPLICABLE'override.'not_applicable'.humanizealready returns"Not applicable". Our GraphQL guidelines say to build enum values from the Rails enum witheach_key, so an override would duplicate what the loop already does. - REST API allowlist updated.
API::ComplianceExternalControls::VALID_STATUS_VALUEShas its own%w[pass fail]list, separate from the service. Without this change, the planned update tocompliance_external_controls_spec.rbwould fail with a 400. - New audit event type YAML. The workplan didn't include this, but the audit event fails validation without it.
Out of scope (sibling tasks under https://gitlab.com/gitlab-org/gitlab/-/work_items/621132)
- Counting
not_applicablein requirement rollups (RefreshStatusService/not_applicable_count): https://gitlab.com/gitlab-org/gitlab/-/work_items/622256 - Coverage statistics: https://gitlab.com/gitlab-org/gitlab/-/work_items/622257
- Evaluator worker: https://gitlab.com/gitlab-org/gitlab/-/work_items/622258
- UI: https://gitlab.com/gitlab-org/gitlab/-/work_items/622259
- User-facing docs, including the
statusattribute description indoc/api/external_controls.md: https://gitlab.com/gitlab-org/gitlab/-/work_items/622260
Until https://gitlab.com/gitlab-org/gitlab/-/work_items/622256 lands, RefreshStatusService ignores not_applicable controls when it counts statuses.
References
- https://gitlab.com/gitlab-org/gitlab/-/work_items/622255
- Parent: https://gitlab.com/gitlab-org/gitlab/-/work_items/621132
Screenshots or screen recordings
Not applicable: backend only.
How to set up and validate locally
-
Set up an Ultimate project with a compliance framework that has an external control.
-
In the Rails console:
control = ComplianceManagement::ComplianceFramework::ComplianceRequirementsControl.external.last project = Project.find(<id>) ComplianceManagement::ComplianceFramework::ComplianceRequirementsControls::UpdateStatusService .new(current_user: User.first, control: control, project: project, status_value: 'not_applicable') .execute # => success, payload: { status: "not_applicable" } -
In GraphiQL, check that
ProjectComplianceControlStatusincludesNOT_APPLICABLE.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.