Skip rule diffing for policy types without rules
What does this MR do and why?
Policy types without rules (pipeline execution and pipeline execution schedule) now always get an empty rules_diff in PolicyComparer. This stops Security::PersistSecurityPoliciesWorker from failing on policies that have a stray rules: key.
The JSON schemas for these two policy types don't set additionalProperties: false, so a policy YAML with a rules: key passes validation.
- On create,
Security::Policy.upsert_policyskips rules becausesupports_policy_rules?is false. - On every later update,
PolicyComparer#compare_rulescompares the YAMLrulesagainst no rules in the database. It reports them as created rules. UpdateSecurityPoliciesService#create_new_rulesthen callsSecurity::Policy#upsert_rule.Security::PolicyRule.for_policy_typeraisesArgumentError: unrecognized policy_type.
The worker fails. Changes to pipeline execution policies roll back, and the policy types persisted after them (vulnerability management, pipeline execution schedule, dependency firewall) are skipped. Every retry or resync fails again.
On GitLab.com this was the most common failure in security policy management Sidekiq jobs: about 13.4k failed jobs in 7 days, roughly half of all failures in that feature category. They came from a handful of projects.
The fix: compare_rules returns early when db_policy.supports_policy_rules? is false. Every consumer of rules_diff goes through this comparer, so one guard covers all of them (3 lines in ee/lib/security/security_orchestration_policies/policy_comparer.rb).
I did not tighten the JSON schemas. That would reject YAML that is accepted today.
Tests:
policy_comparer_spec.rb: a table-driven spec covers both policy types with a strayrules:key and expects an empty rules diff.persist_policy_service_spec.rb: persists a pipeline execution policy with a strayrules:key, then updates it, and expects the update to succeed. Before the fix it raised the sameArgumentErroras production.
No database changes, no feature flag (small fix to an error path), no UI or documentation changes.
References
No linked issue.
Screenshots or screen recordings
No UI changes. The before/after behavior is in the table below.
How to set up and validate locally
- Create a security policy project with
.gitlab/security-policies/policy.ymlcontaining apipeline_execution_policythat has an extrarules:list, for example:Link the policy project to a project.rules: - type: pipeline branches: [main] - Edit the policy, for example change
description, and merge or commit the change. To sync right away, run this in the Rails console:Security::SyncScanPoliciesWorker.perform_async(<configuration_id>) - Check
log/sidekiq.logand the stored policy.
| Before | After | |
|---|---|---|
Security::PersistSecurityPoliciesWorker |
job_status is fail with ArgumentError: unrecognized policy_type |
Job succeeds |
PolicyUpdatedEvent rules_diff |
Not published, the job fails first | Empty |
Security::Policy description |
Keeps the old description | Shows the new description |
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.