20180403035759_create_project_ci_cd_settings.rb 1.89 KB
Newer Older
1
class CreateProjectCiCdSettings < ActiveRecord::Migration[4.2]
2 3 4 5 6 7 8 9 10 11 12 13 14 15
  include Gitlab::Database::MigrationHelpers

  DOWNTIME = false

  disable_ddl_transaction!

  def up
    unless table_exists?(:project_ci_cd_settings)
      create_table(:project_ci_cd_settings) do |t|
        t.integer(:project_id, null: false)
        t.boolean(:group_runners_enabled, default: true, null: false)
      end
    end

16
    disable_statement_timeout do
17 18
      # This particular INSERT will take between 10 and 20 seconds.
      execute 'INSERT INTO project_ci_cd_settings (project_id) SELECT id FROM projects'
19

20 21 22
      # We add the index and foreign key separately so the above INSERT statement
      # takes as little time as possible.
      add_concurrent_index(:project_ci_cd_settings, :project_id, unique: true)
23

24 25
      add_foreign_key_with_retry
    end
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
  end

  def down
    drop_table :project_ci_cd_settings
  end

  def add_foreign_key_with_retry
    if Gitlab::Database.mysql?
      # When using MySQL we don't support online upgrades, thus projects can't
      # be deleted while we are running this migration.
      return add_project_id_foreign_key
    end

    # Between the initial INSERT and the addition of the foreign key some
    # projects may have been removed, leaving orphaned rows in our new settings
    # table.
    loop do
      remove_orphaned_settings

      begin
        add_project_id_foreign_key
        break
      rescue ActiveRecord::InvalidForeignKey
        say 'project_ci_cd_settings contains some orphaned rows, retrying...'
      end
    end
  end

  def add_project_id_foreign_key
    add_concurrent_foreign_key(:project_ci_cd_settings, :projects, column: :project_id)
  end

  def remove_orphaned_settings
    execute <<~SQL
      DELETE FROM project_ci_cd_settings
      WHERE NOT EXISTS (
        SELECT 1
        FROM projects
        WHERE projects.id = project_ci_cd_settings.project_id
      )
    SQL
  end
end