Remove cancel_pipelines_when_policy_disabled feature flag

What does this MR do and why?

Removes the cancel_pipelines_when_policy_disabled feature flag (introduced in 19.1 as gitlab_com_derisk, promoted to beta and enabled by default in 19.2), making the behavior unconditional: running policy schedule pipelines are always cancelled when a pipeline execution schedule policy is disabled or unlinked from a project.

Changes:

  • Delete the flag definition YAML.
  • Remove the Feature.enabled? guards in Security::SecurityOrchestrationPolicies::BaseProjectPolicyService and Security::PipelineExecutionPolicies::CancelPolicyPipelinesService.
  • Remove the flag-disabled spec contexts, plus the project-scoped-configuration context that only existed to cover the flag's namespace fallback.

The flag was default_enabled: true from 19.2, so this removal is a no-op at runtime and is zero-downtime-upgrade safe. Changelog: other follows the flag-removal flowchart for a default-on flag removed keeping the new code.

References

Screenshots or screen recordings

Screen recording: N/A — this MR changes no frontend code and adds no interaction; the only observable effect is a backend state transition on a pipeline, captured below.

Verified on the GDK with the flag deleted from the codebase — no flag set anywhere. A schedule policy scoped to target-project produced pending pipeline #842; disabling the policy cancelled it within seconds, via the real chain (CancelPolicyPipelinesWorker ran with root_caller_id: Security::PersistSecurityPoliciesWorker).

Before After
Policy enabled 02-before-policy-enabled Policy disabled 05-after-policy-disabled
Pipeline #842 pending 01-before-pipelines-list Pipeline #842 cancelled 04-after-pipelines-list

How to set up and validate locally

Adapted from !236748 (merged), minus the feature flag step: the behavior is now unconditional, so no Feature.enable call is needed.

Step 1: Create a group with a security policy project

  1. Create a group.

  2. Create a project named security-policies in that group.

  3. Create another project named target-project in that group. Note its ID.

  4. Add a policy-ci.yml file to security-policies with a job that stays pending, so it is still cancelable when you disable the policy. A tag no runner has is more reliable than a sleeping job, which a local runner can claim and fail:

    policy-long-running-job:
      tags: [no-runner-has-this-tag]
      script:
        - echo "waiting"
  5. Add a .gitlab/security-policies/policy.yml file to security-policies (replace GROUP_PATH with your group's path and TARGET_PROJECT_ID with the ID from above):

    ---
    experiments:
      pipeline_execution_schedule_policy:
        enabled: true
    pipeline_execution_schedule_policy:
    - name: Test Schedule Policy
      description: Policy for testing cancellation
      enabled: true
      content:
        include:
        - project: GROUP_PATH/security-policies
          file: policy-ci.yml
      schedules:
      - type: daily
        start_time: '10:00'
        time_window:
          value: 600
          distribution: random
      policy_scope:
        projects:
          including:
          - id: TARGET_PROJECT_ID
  6. On the group page, go to Secure > Policies and link security-policies as the security policy project.

Step 2: Prepare a merge request that disables the policy

  1. On the group's Secure > Policies page, select Test Schedule Policy, then Edit policy.
  2. Select Disabled, then Update via merge request.
  3. Do not merge the merge request yet.

Step 3: Verify the cancellation

  1. Trigger a scheduled pipeline from the Rails console (replace GROUP_PATH):

    target_project = Project.find_by_full_path('GROUP_PATH/target-project')
    schedule = Security::PipelineExecutionProjectSchedule.find_by(project_id: target_project.id)
    Security::PipelineExecutionPolicies::RunScheduleWorker.new.perform(schedule.id)
  2. In target-project, go to Build > Pipelines. The pipeline should be created, pending, or running.

  3. Merge the merge request that disables the policy.

  4. Within a few seconds the pipeline should be cancelled — with no feature flag set anywhere.

Unlinking the project from the policy scope cancels the pipeline the same way. If you poll for the status from a rails runner script rather than the UI, wrap the reads in Ci::ApplicationRecord.uncached — ActiveRecord::Base.uncached does not reach the ci pool.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist.

Edited by Alexander Turinske

Merge request reports

Loading
Loading