Skip to content

gitlab-rake db:migrate:status hides unkown migrations

On a GitLab CE instance, if a migration can't be found on disk, we see the NO FILE output:

   up     20260421104929  ********** NO FILE **********
   up     20260421104930  ********** NO FILE **********

This comes from Rails: https://github.com/rails/rails/blob/v7.1.5.1/activerecord/lib/active_record/migration.rb#L1340-L1342

However, we have ActiveRecord patches only for GitLab EE (https://gitlab.com/gitlab-org/gitlab/-/blob/9a652e8743622b2f93ad1f046816f123260142f7/ee/config/initializers/active_record_database_tasks.rb) that hides this output. I would think we would want to make this consistent with CE and EE.

This makes troubleshooting harder because we suspect a customer applied GitLab 18.2 migrations to their instance, but they are still running GitLab 18.1. gitlab rake db:migrate:status doesn't show any unknown migrations.

Duo says:

Looking at the code in ee/config/initializers/active_record_database_tasks.rb, I can see exactly why migrations present in schema_migrations but not on disk are omitted.

The issue is in the status_with_milestones method:

def status_with_milestones
  conn = ActiveRecord::Base.connection

  versions = conn.schema_migration.versions.map(&:to_i)

  conn.migration_context.migrations.sort_by(&:version).map do |m|
    [
      (versions.include?(m.version.to_i) ? 'up' : 'down'),
      m.version.to_s,
      m.version.try(:type).to_s,
      m.try(:milestone).to_s,
      m.name
    ]
  end
end

The problem: The method only iterates over conn.migration_context.migrations, which contains only the migration files that exist on disk. It completely ignores any migration versions that exist in the schema_migrations table but don't have corresponding files on disk.

In contrast, Rails' original implementation (which this patch overrides) would show these "missing" migrations. The original Rails code typically does something like:

  1. Get all versions from schema_migrations table
  2. Get all migration files from disk
  3. Show the union of both sets, marking missing files appropriately

The fix would be to modify status_with_milestones to:

  1. Get all versions from both the database (schema_migrations) and disk (migration_context.migrations)
  2. Create entries for versions that exist in the database but not on disk
  3. Mark them appropriately (perhaps as "up" status but with missing file indicators)

This is a significant limitation of the current patch - it hides migrations that have been run but whose files have been deleted or are otherwise missing from the filesystem. This could make it difficult to diagnose migration-related issues where the database state doesn't match the expected migration files.

Relates to https://gitlab.com/gitlab-com/request-for-help/-/issues/3203#note_2659935475

Edited by 🤖 GitLab Bot 🤖