summaryrefslogtreecommitdiff
path: root/db/migrate/20180403035759_create_project_ci_cd_settings.rb
blob: 000286897791fa8ebf33b225cfc9193a9aab8ef2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
class CreateProjectCiCdSettings < ActiveRecord::Migration[4.2]
  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

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

      # 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)

      add_foreign_key_with_retry
    end
  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