diff options
author | Kamil TrzciĆski <ayufan@ayufan.eu> | 2018-05-08 17:01:53 +0000 |
---|---|---|
committer | Filipa Lacerda <filipa@gitlab.com> | 2018-05-09 10:01:13 +0100 |
commit | 84ea440042518659f95cb84a9f5254df93a24a01 (patch) | |
tree | 2f8a3bf076fcf36d73e6feda703caa18bb51c85e | |
parent | 9bf4ae3d86c4bee53bfdff74c3b1d6c055e66fac (diff) | |
download | gitlab-ce-84ea440042518659f95cb84a9f5254df93a24a01.tar.gz |
Merge branch 'fix/gb/add-pipeline-builds-foreign-key' into 'master'
Add database foreign key between pipelines and builds
Closes #46035
See merge request gitlab-org/gitlab-ce!18822
4 files changed, 74 insertions, 0 deletions
diff --git a/changelogs/unreleased/fix-gb-add-pipeline-builds-foreign-key.yml b/changelogs/unreleased/fix-gb-add-pipeline-builds-foreign-key.yml new file mode 100644 index 00000000000..bded7bb7cc4 --- /dev/null +++ b/changelogs/unreleased/fix-gb-add-pipeline-builds-foreign-key.yml @@ -0,0 +1,5 @@ +--- +title: Add database foreign key constraint between pipelines and build +merge_request: 18822 +author: +type: fixed diff --git a/db/migrate/20180420010016_add_pipeline_build_foreign_key.rb b/db/migrate/20180420010016_add_pipeline_build_foreign_key.rb new file mode 100644 index 00000000000..6fabe07bc9c --- /dev/null +++ b/db/migrate/20180420010016_add_pipeline_build_foreign_key.rb @@ -0,0 +1,27 @@ +class AddPipelineBuildForeignKey < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + execute <<~SQL + DELETE FROM ci_builds WHERE project_id IS NULL OR commit_id IS NULL + SQL + + execute <<~SQL + DELETE FROM ci_builds WHERE NOT EXISTS + (SELECT true FROM ci_pipelines WHERE ci_pipelines.id = ci_builds.commit_id) + AND stage_id IS NULL + SQL + + add_concurrent_foreign_key(:ci_builds, :ci_pipelines, column: :commit_id) + end + + def down + return unless foreign_key_exists?(:ci_builds, :ci_pipelines, column: :commit_id) + + remove_foreign_key(:ci_builds, column: :commit_id) + end +end diff --git a/spec/migrations/add_pipeline_build_foreign_key_spec.rb b/spec/migrations/add_pipeline_build_foreign_key_spec.rb new file mode 100644 index 00000000000..e9413f52f19 --- /dev/null +++ b/spec/migrations/add_pipeline_build_foreign_key_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' +require Rails.root.join('db', 'migrate', '20180420010016_add_pipeline_build_foreign_key.rb') + +describe AddPipelineBuildForeignKey, :migration do + let(:namespaces) { table(:namespaces) } + let(:projects) { table(:projects) } + let(:pipelines) { table(:ci_pipelines) } + let(:builds) { table(:ci_builds) } + + before do + namespaces.create(id: 10, name: 'gitlab-org', path: 'gitlab-org') + projects.create!(id: 11, namespace_id: 10, name: 'gitlab', path: 'gitlab') + pipelines.create!(id: 12, project_id: 11, ref: 'master', sha: 'adf43c3a') + + builds.create!(id: 101, commit_id: 12, project_id: 11) + builds.create!(id: 102, commit_id: 222, project_id: 11) + builds.create!(id: 103, commit_id: 333, project_id: 11) + builds.create!(id: 104, commit_id: 12, project_id: 11) + builds.create!(id: 106, commit_id: nil, project_id: 11) + builds.create!(id: 107, commit_id: 12, project_id: nil) + end + + it 'adds foreign key after removing orphans' do + expect(builds.all.count).to eq 6 + expect(foreign_key_exists?(:ci_builds, :ci_pipelines, column: :commit_id)).to be_falsey + + migrate! + + expect(builds.all.pluck(:id)).to eq [101, 104] + expect(foreign_key_exists?(:ci_builds, :ci_pipelines, column: :commit_id)).to be_truthy + end +end diff --git a/spec/support/helpers/migrations_helpers.rb b/spec/support/helpers/migrations_helpers.rb index 5d6f662e8fe..84abec75c26 100644 --- a/spec/support/helpers/migrations_helpers.rb +++ b/spec/support/helpers/migrations_helpers.rb @@ -24,6 +24,16 @@ module MigrationsHelpers end end + def foreign_key_exists?(source, target = nil, column: nil) + ActiveRecord::Base.connection.foreign_keys(source).any? do |key| + if column + key.options[:column].to_s == column.to_s + else + key.to_table.to_s == target.to_s + end + end + end + def reset_column_in_all_models clear_schema_cache! |