Skip to content

Add database and model support for "Group-level Protected Branches"

What does this MR do and why?

Related to #372815 (closed), this MR is basic database support for the feature "Group-level Protected Branches". There are three changes:

  1. Add a column namespace_id to the table protected_branches.
  2. Update the constraint in protected_branches, check that either project_id or namespace_id exist.
  3. Update the model validation and association to accommodate database changes.

How to set up and validate locally

  1. Open a Rails console in GitLab project.
  2. Add a protected branch into group: ProtectedBranch.last.update!(project: nil, group: Group.last)
  3. Get all protected branches of the last group: Group.last.protected_branches

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Migration outout logs

$ bundle exec rake db:drop db:create db:schema:load db:migrate
Dropped database 'gitlabhq_test'
Dropped database 'gitlabhq_test_ci'
Dropped database 'gitlabhq_geo_test'
Created database 'gitlabhq_test'
Created database 'gitlabhq_test_ci'
Created database 'gitlabhq_geo_test'
==> 'bundle exec rake db:drop db:create db:schema:load db:migrate' succeeded in 37 seconds.
$ setup_db_praefect
SELECT pg_catalog.set_config('search_path', '', false);
CREATE DATABASE praefect_test ENCODING 'UTF8';
==> 'setup_db_praefect' succeeded in 0 seconds.
$ git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME:$CI_MERGE_REQUEST_TARGET_BRANCH_NAME --depth 20
From https://gitlab.com/gitlab-jh/jh-team/gitlab
 * [new branch]          master     -> master
 * [new branch]          master     -> origin/master
$ scripts/validate_migration_schema
$ git diff --name-only --diff-filter=A master -- db/migrate db/post_migrate
db/migrate/20220613112029_add_namespace_id_to_protected_branches.rb
db/migrate/20220613112030_add_namespace_id_indexes_foreign_key_to_protected_branches.rb
db/migrate/20220613112031_add_group_or_project_constraint_in_protected_branches.rb
db/migrate/20220613112032_change_project_id_null_in_protected_branches.rb
$ scripts/db_tasks db:migrate:down VERSION=20220613112032
main: == 20220613112032 ChangeProjectIdNullInProtectedBranches: reverting ===========
main: -- change_column_null(:protected_branches, :project_id, false)
main:    -> 0.0038s
main: == 20220613112032 ChangeProjectIdNullInProtectedBranches: reverted (0.0065s) ==
$ scripts/db_tasks db:schema:dump
$ scripts/db_tasks db:migrate:down VERSION=20220613112031
main: == 20220613112031 AddGroupOrProjectConstraintInProtectedBranches: reverting ===
main: -- transaction_open?()
main:    -> 0.0000s
main: -- transaction_open?()
main:    -> 0.0000s
main: -- execute("ALTER TABLE protected_branches\nDROP CONSTRAINT IF EXISTS protected_branches_project_id_namespace_id_any_not_null\n")
main:    -> 0.0013s
main: == 20220613112031 AddGroupOrProjectConstraintInProtectedBranches: reverted (0.0140s) 
$ scripts/db_tasks db:schema:dump
$ scripts/db_tasks db:migrate:down VERSION=20220613112030
main: == 20220613112030 AddNamespaceIdIndexesForeignKeyToProtectedBranches: reverting 
main: -- transaction_open?()
main:    -> 0.0000s
main: -- remove_foreign_key(:protected_branches, {:column=>:namespace_id})
main:    -> 0.0196s
main: -- transaction_open?()
main:    -> 0.0000s
main: -- index_exists?(:protected_branches, :namespace_id, {:name=>"index_protected_branches_namespace_id", :algorithm=>:concurrently})
main:    -> 0.0066s
main: -- execute("SET statement_timeout TO 0")
main:    -> 0.0006s
main: -- remove_index(:protected_branches, {:name=>"index_protected_branches_namespace_id", :algorithm=>:concurrently, :column=>:namespace_id})
main:    -> 0.0066s
main: -- execute("RESET statement_timeout")
main:    -> 0.0007s
main: == 20220613112030 AddNamespaceIdIndexesForeignKeyToProtectedBranches: reverted (0.0609s) 
$ scripts/db_tasks db:schema:dump
$ scripts/db_tasks db:migrate:down VERSION=20220613112029
main: == 20220613112029 AddNamespaceIdToProtectedBranches: reverting ================
main: -- remove_column(:protected_branches, :namespace_id, :bigint)
main:    -> 0.0025s
main: == 20220613112029 AddNamespaceIdToProtectedBranches: reverted (0.0060s) =======
$ scripts/db_tasks db:schema:dump
$ git diff master -- db/structure.sql
$ scripts/db_tasks db:migrate
main: == 20220613112029 AddNamespaceIdToProtectedBranches: migrating ================
main: -- add_column(:protected_branches, :namespace_id, :bigint)
main:    -> 0.0021s
main: == 20220613112029 AddNamespaceIdToProtectedBranches: migrated (0.0031s) =======
main: == 20220613112030 AddNamespaceIdIndexesForeignKeyToProtectedBranches: migrating 
main: -- transaction_open?()
main:    -> 0.0000s
main: -- index_exists?(:protected_branches, :namespace_id, {:name=>"index_protected_branches_namespace_id", :where=>"namespace_id IS NOT NULL", :algorithm=>:concurrently})
main:    -> 0.0073s
main: -- execute("SET statement_timeout TO 0")
main:    -> 0.0006s
main: -- add_index(:protected_branches, :namespace_id, {:name=>"index_protected_branches_namespace_id", :where=>"namespace_id IS NOT NULL", :algorithm=>:concurrently})
main:    -> 0.0024s
main: -- execute("RESET statement_timeout")
main:    -> 0.0005s
main: -- transaction_open?()
main:    -> 0.0000s
main: -- foreign_keys(:protected_branches)
main:    -> 0.0052s
main: -- transaction_open?()
main:    -> 0.0000s
main: -- execute("ALTER TABLE protected_branches\nADD CONSTRAINT fk_de9216e774\nFOREIGN KEY (namespace_id)\nREFERENCES namespaces (id)\nON DELETE CASCADE\nNOT VALID;\n")
main:    -> 0.0020s
main: -- execute("ALTER TABLE protected_branches VALIDATE CONSTRAINT fk_de9216e774;")
main:    -> 0.0025s
main: == 20220613112030 AddNamespaceIdIndexesForeignKeyToProtectedBranches: migrated (0.0347s) 
main: == 20220613112031 AddGroupOrProjectConstraintInProtectedBranches: migrating ===
main: -- transaction_open?()
main:    -> 0.0000s
main: -- current_schema()
main:    -> 0.0006s
main: -- transaction_open?()
main:    -> 0.0000s
main: -- execute("           ALTER TABLE protected_branches\n           ADD CONSTRAINT protected_branches_project_id_namespace_id_any_not_null\n           CHECK ( (project_id IS NULL) <> (namespace_id IS NULL)\n)\n           NOT VALID;\n")
main:    -> 0.0010s
main: -- current_schema()
main:    -> 0.0004s
main: -- execute("ALTER TABLE protected_branches VALIDATE CONSTRAINT protected_branches_project_id_namespace_id_any_not_null;")
main:    -> 0.0008s
main: == 20220613112031 AddGroupOrProjectConstraintInProtectedBranches: migrated (0.0102s) 
main: == 20220613112032 ChangeProjectIdNullInProtectedBranches: migrating ===========
main: -- change_column_null(:protected_branches, :project_id, true)
main:    -> 0.0009s
main: == 20220613112032 ChangeProjectIdNullInProtectedBranches: migrated (0.0011s) ==

/cc @daveliu

Edited by Song Huang

Merge request reports

Loading