Merge branch '51651-fill-pipeline-source-for-external-pipelines' into 'master'
Resolve "Fill pipeline source for external pipelines" Closes #51651 See merge request gitlab-org/gitlab-ce!21814
This commit is contained in:
commit
2155ba8b40
6 changed files with 171 additions and 0 deletions
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Retroactively fill pipeline source for external pipelines.
|
||||||
|
merge_request: 21814
|
||||||
|
author:
|
||||||
|
type: other
|
|
@ -0,0 +1,20 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
|
||||||
|
# for more information on how to write migrations for GitLab.
|
||||||
|
|
||||||
|
class AddIndexPipelinesProjectIdSource < ActiveRecord::Migration
|
||||||
|
include Gitlab::Database::MigrationHelpers
|
||||||
|
|
||||||
|
DOWNTIME = false
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
add_concurrent_index :ci_pipelines, [:project_id, :source]
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_concurrent_index :ci_pipelines, [:project_id, :source]
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,33 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
|
||||||
|
# for more information on how to write migrations for GitLab.
|
||||||
|
|
||||||
|
class PopulateExternalPipelineSource < ActiveRecord::Migration
|
||||||
|
include Gitlab::Database::MigrationHelpers
|
||||||
|
|
||||||
|
# Set this constant to true if this migration requires downtime.
|
||||||
|
DOWNTIME = false
|
||||||
|
MIGRATION = 'PopulateExternalPipelineSource'.freeze
|
||||||
|
BATCH_SIZE = 500
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
class Pipeline < ActiveRecord::Base
|
||||||
|
include EachBatch
|
||||||
|
self.table_name = 'ci_pipelines'
|
||||||
|
end
|
||||||
|
|
||||||
|
def up
|
||||||
|
Pipeline.where(source: nil).tap do |relation|
|
||||||
|
queue_background_migration_jobs_by_range_at_intervals(relation,
|
||||||
|
MIGRATION,
|
||||||
|
5.minutes,
|
||||||
|
batch_size: BATCH_SIZE)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
# noop
|
||||||
|
end
|
||||||
|
end
|
|
@ -475,6 +475,7 @@ ActiveRecord::Schema.define(version: 20180917172041) do
|
||||||
add_index "ci_pipelines", ["project_id", "iid"], name: "index_ci_pipelines_on_project_id_and_iid", unique: true, where: "(iid IS NOT NULL)", using: :btree
|
add_index "ci_pipelines", ["project_id", "iid"], name: "index_ci_pipelines_on_project_id_and_iid", unique: true, where: "(iid IS NOT NULL)", using: :btree
|
||||||
add_index "ci_pipelines", ["project_id", "ref", "status", "id"], name: "index_ci_pipelines_on_project_id_and_ref_and_status_and_id", using: :btree
|
add_index "ci_pipelines", ["project_id", "ref", "status", "id"], name: "index_ci_pipelines_on_project_id_and_ref_and_status_and_id", using: :btree
|
||||||
add_index "ci_pipelines", ["project_id", "sha"], name: "index_ci_pipelines_on_project_id_and_sha", using: :btree
|
add_index "ci_pipelines", ["project_id", "sha"], name: "index_ci_pipelines_on_project_id_and_sha", using: :btree
|
||||||
|
add_index "ci_pipelines", ["project_id", "source"], name: "index_ci_pipelines_on_project_id_and_source", using: :btree
|
||||||
add_index "ci_pipelines", ["project_id", "status", "config_source"], name: "index_ci_pipelines_on_project_id_and_status_and_config_source", using: :btree
|
add_index "ci_pipelines", ["project_id", "status", "config_source"], name: "index_ci_pipelines_on_project_id_and_status_and_config_source", using: :btree
|
||||||
add_index "ci_pipelines", ["project_id"], name: "index_ci_pipelines_on_project_id", using: :btree
|
add_index "ci_pipelines", ["project_id"], name: "index_ci_pipelines_on_project_id", using: :btree
|
||||||
add_index "ci_pipelines", ["status"], name: "index_ci_pipelines_on_status", using: :btree
|
add_index "ci_pipelines", ["status"], name: "index_ci_pipelines_on_status", using: :btree
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
# rubocop:disable Style/Documentation
|
||||||
|
|
||||||
|
module Gitlab
|
||||||
|
module BackgroundMigration
|
||||||
|
class PopulateExternalPipelineSource
|
||||||
|
module Migratable
|
||||||
|
class Pipeline < ActiveRecord::Base
|
||||||
|
self.table_name = 'ci_pipelines'
|
||||||
|
|
||||||
|
def self.sources
|
||||||
|
{
|
||||||
|
unknown: nil,
|
||||||
|
push: 1,
|
||||||
|
web: 2,
|
||||||
|
trigger: 3,
|
||||||
|
schedule: 4,
|
||||||
|
api: 5,
|
||||||
|
external: 6
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class CommitStatus < ActiveRecord::Base
|
||||||
|
self.table_name = 'ci_builds'
|
||||||
|
self.inheritance_column = :_type_disabled
|
||||||
|
|
||||||
|
scope :has_pipeline, -> { where('ci_builds.commit_id=ci_pipelines.id') }
|
||||||
|
scope :of_type, -> (type) { where('type=?', type) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform(start_id, stop_id)
|
||||||
|
external_pipelines(start_id, stop_id)
|
||||||
|
.update_all(source: Migratable::Pipeline.sources[:external])
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def external_pipelines(start_id, stop_id)
|
||||||
|
Migratable::Pipeline.where(id: (start_id..stop_id))
|
||||||
|
.where(
|
||||||
|
'EXISTS (?) AND NOT EXISTS (?)',
|
||||||
|
Migratable::CommitStatus.of_type('GenericCommitStatus').has_pipeline.select(1),
|
||||||
|
Migratable::CommitStatus.of_type('Ci::Build').has_pipeline.select(1)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,62 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Gitlab::BackgroundMigration::PopulateExternalPipelineSource, :migration, schema: 20180916011959 do
|
||||||
|
let(:migration) { described_class.new }
|
||||||
|
|
||||||
|
let!(:internal_pipeline) { create(:ci_pipeline, source: :web) }
|
||||||
|
let(:pipelines) { [internal_pipeline, unknown_pipeline].map(&:id) }
|
||||||
|
|
||||||
|
let!(:unknown_pipeline) do
|
||||||
|
build(:ci_pipeline, source: :unknown)
|
||||||
|
.tap { |pipeline| pipeline.save(validate: false) }
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { migration.perform(pipelines.min, pipelines.max) }
|
||||||
|
|
||||||
|
shared_examples 'no changes' do
|
||||||
|
it 'does not change the pipeline source' do
|
||||||
|
expect { subject }.not_to change { unknown_pipeline.reload.source }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when unknown pipeline is external' do
|
||||||
|
before do
|
||||||
|
create(:generic_commit_status, pipeline: unknown_pipeline)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'populates the pipeline source' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(unknown_pipeline.reload.source).to eq('external')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'can be repeated without effect' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect { subject }.not_to change { unknown_pipeline.reload.source }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when unknown pipeline has just a build' do
|
||||||
|
before do
|
||||||
|
create(:ci_build, pipeline: unknown_pipeline)
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'no changes'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when unknown pipeline has no statuses' do
|
||||||
|
it_behaves_like 'no changes'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when unknown pipeline has a build and a status' do
|
||||||
|
before do
|
||||||
|
create(:generic_commit_status, pipeline: unknown_pipeline)
|
||||||
|
create(:ci_build, pipeline: unknown_pipeline)
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'no changes'
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue