From 56753c8044b656e92b36d7f65ede140cf01ac4a8 Mon Sep 17 00:00:00 2001
From: Andreas Brandl <abrandl@gitlab.com>
Date: Mon, 30 Aug 2021 20:32:07 +0200
Subject: [PATCH] Add docs section with background on versioning

---
 doc/development/migration_style_guide.md      | 27 +++++++++++++++++++
 .../migration/versioned_migration_class.rb    |  4 +--
 .../versioned_migration_class_spec.rb         |  4 +--
 3 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index 836e61eadb07f..a27ba8964bf7a 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -217,6 +217,33 @@ In case you need to insert, update, or delete a significant amount of data, you:
 - Must disable the single transaction with `disable_ddl_transaction!`.
 - Should consider doing it in a [Background Migration](background_migrations.md).
 
+## Migration helpers and versioning
+
+Various helper methods are available for many common patterns in database migrations. Those
+helpers can be found in `Gitlab::Database::MigrationHelpers` and related modules.
+
+In order to allow changing a helper's behavior over time, we implement a versioning scheme
+for migration helpers. This allows us to maintain the behavior of a helper for already
+existing migrations but change the behavior for any new migrations.
+
+For that purpose, all database migrations should inherit from `Gitlab::Database::Migration`,
+which is a "versioned" class. For new migrations, the latest version should be used (which
+can be looked up in `Gitlab::Database::Migration::MIGRATION_CLASSES`) to use the latest version
+of migration helpers.
+
+In this example, we use version 1.0 of the migration class:
+
+```ruby
+class TestMigration < Gitlab::Database::Migration[1.0]
+  def change
+  end
+end
+```
+
+Note that it is discouraged to include `Gitlab::Database::MigrationHelpers` directly into a
+migration. Instead, the latest version of `Gitlab::Database::Migration` will expose the latest
+version of migration helpers automatically.
+
 ## Retry mechanism when acquiring database locks
 
 When changing the database schema, we use helper methods to invoke DDL (Data Definition
diff --git a/rubocop/cop/migration/versioned_migration_class.rb b/rubocop/cop/migration/versioned_migration_class.rb
index 33debf716b408..4936e65d74c61 100644
--- a/rubocop/cop/migration/versioned_migration_class.rb
+++ b/rubocop/cop/migration/versioned_migration_class.rb
@@ -10,8 +10,8 @@ class VersionedMigrationClass < RuboCop::Cop::Cop
 
         ENFORCED_SINCE = 2021_08_30_00_00_00
 
-        MSG_INHERIT = 'Don\'t inherit from ActiveRecord::Migration but use Gitlab::Database::Migration[1.0] instead.'
-        MSG_INCLUDE = 'Don\'t include migration helper modules directly. Inherit from Gitlab::Database::Migration[1.0] instead.'
+        MSG_INHERIT = 'Don\'t inherit from ActiveRecord::Migration but use Gitlab::Database::Migration[1.0] instead. See https://docs.gitlab.com/ee/development/migration_style_guide.html#migration-helpers-and-versioning.'
+        MSG_INCLUDE = 'Don\'t include migration helper modules directly. Inherit from Gitlab::Database::Migration[1.0] instead. See https://docs.gitlab.com/ee/development/migration_style_guide.html#migration-helpers-and-versioning.'
 
         MIGRATION_CLASS = 'Gitlab::Database::Migration'
 
diff --git a/spec/rubocop/cop/migration/versioned_migration_class_spec.rb b/spec/rubocop/cop/migration/versioned_migration_class_spec.rb
index 89b0d1a9c8552..af50e5598ceca 100644
--- a/spec/rubocop/cop/migration/versioned_migration_class_spec.rb
+++ b/spec/rubocop/cop/migration/versioned_migration_class_spec.rb
@@ -51,7 +51,7 @@ def down
       it 'adds an offence if inheriting from ActiveRecord::Migration' do
         expect_offense(<<~RUBY)
           class MyMigration < ActiveRecord::Migration[6.1]
-          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't inherit from ActiveRecord::Migration but use Gitlab::Database::Migration[1.0] instead.
+          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't inherit from ActiveRecord::Migration but use Gitlab::Database::Migration[1.0] instead. See https://docs.gitlab.com/ee/development/migration_style_guide.html#migration-helpers-and-versioning.
           end
         RUBY
       end
@@ -60,7 +60,7 @@ class MyMigration < ActiveRecord::Migration[6.1]
         expect_offense(<<~RUBY)
           class MyMigration < Gitlab::Database::Migration[1.0]
             include Gitlab::Database::MigrationHelpers
-            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't include migration helper modules directly. Inherit from Gitlab::Database::Migration[1.0] instead.
+            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't include migration helper modules directly. Inherit from Gitlab::Database::Migration[1.0] instead. See https://docs.gitlab.com/ee/development/migration_style_guide.html#migration-helpers-and-versioning.
           end
         RUBY
       end
-- 
GitLab