Skip to content

[Breaking change] Migrate Deployment Approval setting data from single-access level to multi-access level

Problem

These configurations are separately stored, to illustrate:

  • If a user has configured for single-access level (i.e. MVC feature), this feature keeps working even after we've shipped this issue. Multi-access levels is still opt-in feature at the moment.
  • If a user has configured for multi-access levels, the system switches to the new process and ignores the legacy setting. The control interface, including commenting, etc, still works as usual.

We'd like to fully switch/migrate to the multi-access levels at some point for the Single-source-of-truth interface. To do so, we should perform a database migration to migrate the data. Later, we can follow-up to adjust the UI/UX with #355708 (closed) and #355853 (closed).

I'll create an issue and check the number of the single-access configurations on SaaS for gauging the impact.

Proposal

  • Create a post deployment migration
  • Use define_batched_model and run in batches
  • Use SQL to to do the migration, something like:
INSERT INTO protected_environment_approval_rules
            (protected_environment_id,
             created_at,
             updated_at,
             access_level,
             required_approvals)
SELECT id,
       Now(),
       Now(),
       30,
       required_approval_count
FROM   protected_environments
WHERE  required_approval_count > 0
       AND NOT EXISTS (SELECT 1
                       FROM   protected_environment_approval_rules
                       WHERE  protected_environment_id =
                              protected_environments.id)  

Records to migrate

Only migrate records for protected_environments a) with required_approval_count > 0, and b) where there are no associated protected_environment_approval_rules records.

So the filter should be something like:

ProtectedEnvironment.where('required_approval_count > 0').tap { |pes| pes.approval_rules.empty? }

Note: the code above is just an illustration of the logic. Please make sure the actual query does not result in N+1 performance. Perhaps you can preload the ProtectedEnvironment#approval_rules association.

Translating protected_environments.required_approval_count to protected_environments_approval_rules

The protected_environments.required_approval_count should be translated to a single protected_environments_approval_rules with access_level = Gitlab::Access::DEVELOPER and required_approvals = protected_environments.required_approval_count. (See rationale here)

So:

# given a `protected_environment`:

protected_environment.approval_rules.create(
  user_id: nil,
  group_id: nil,
  access_level: Gitlab::Access::DEVELOPER,
  required_approvals: protected_environment.required_approval_count
)

Note: the code above is just an illustration of the logic.

Edited by Hunter Stewart