[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.