Read about our upcoming Code of Conduct on this issue

Commit 2a20a4f3 authored by Francisco Javier López's avatar Francisco Javier López Committed by Grzegorz Bizon
Browse files

Rename project's pipelines relation

parent b024c46c4a24
......@@ -51,7 +51,7 @@ project_tree:
- resource_label_events:
- label:
:priorities
- pipelines:
- ci_pipelines:
- notes:
- :author
- events:
......
......@@ -26,6 +26,8 @@ def restore
@project_members = @tree_hash.delete('project_members')
RelationRenameService.rename(@tree_hash)
ActiveRecord::Base.uncached do
ActiveRecord::Base.no_touching do
create_relations
......@@ -214,7 +216,7 @@ def excluded_keys_for_relation(relation)
end
def nil_iid_pipeline?(relation_key, relation_item)
relation_key == 'pipelines' && relation_item['iid'].nil?
relation_key == 'ci_pipelines' && relation_item['iid'].nil?
end
end
end
......
......@@ -34,6 +34,8 @@ def project_json_tree
project_json['project_members'] += group_members_json
RelationRenameService.add_new_associations(project_json)
project_json.to_json
end
......
......@@ -4,6 +4,7 @@ module Gitlab
module ImportExport
class RelationFactory
OVERRIDES = { snippets: :project_snippets,
ci_pipelines: 'Ci::Pipeline',
pipelines: 'Ci::Pipeline',
stages: 'Ci::Stage',
statuses: 'commit_status',
......
# frozen_string_literal: true
# This class is intended to help with relation renames within Gitlab versions
# and allow compatibility between versions.
# If you have to change one relationship name that is imported/exported,
# you should add it to the RENAMES constant indicating the old name and the
# new one.
# The behavior of these renamed relationships should be transient and it should
# only last one release until you completely remove the renaming from the list.
#
# When importing, this class will check the project hash and:
# - if only the old relationship name is found, it will rename it with the new one
# - if only the new relationship name is found, it will do nothing
# - if it finds both, it will use the new relationship data
#
# When exporting, this class will duplicate the keys in the resulting file.
# This way, if we open the file in an old version of the exporter it will work
# and also it will with the newer versions.
module Gitlab
module ImportExport
class RelationRenameService
RENAMES = {
'pipelines' => 'ci_pipelines' # Added in 11.6, remove in 11.7
}.freeze
def self.rename(tree_hash)
return unless tree_hash&.present?
RENAMES.each do |old_name, new_name|
old_entry = tree_hash.delete(old_name)
next if tree_hash[new_name]
next unless old_entry
tree_hash[new_name] = old_entry
end
end
def self.add_new_associations(tree_hash)
RENAMES.each do |old_name, new_name|
next if tree_hash.key?(old_name)
tree_hash[old_name] = tree_hash[new_name]
end
end
end
end
end
......@@ -20,7 +20,7 @@
visit pipelines_project_commit_path(project, project.commit.sha)
page.within('.table-holder') do
expect(page).to have_content project.pipelines[0].id # pipeline ids
expect(page).to have_content project.ci_pipelines[0].id # pipeline ids
end
end
end
......
......@@ -300,7 +300,7 @@
let(:pipeline) do
commit_sha = project.commit('HEAD').sha
project.pipelines.create(
project.ci_pipelines.create(
ref: 'HEAD',
sha: commit_sha,
source: :push,
......
......@@ -103,7 +103,7 @@ merge_request_diff_commits:
- merge_request_diff
merge_request_diff_files:
- merge_request_diff
pipelines:
ci_pipelines:
- project
- user
- stages
......@@ -265,7 +265,8 @@ project:
- notification_settings
- import_data
- commit_statuses
- pipelines
- ci_pipelines
- all_pipelines
- stages
- builds
- runner_projects
......
......@@ -197,9 +197,9 @@
end
it 'has the correct number of pipelines and statuses' do
expect(@project.pipelines.size).to eq(5)
expect(@project.ci_pipelines.size).to eq(5)
@project.pipelines.zip([2, 2, 2, 2, 2])
@project.ci_pipelines.zip([2, 2, 2, 2, 2])
.each do |(pipeline, expected_status_size)|
expect(pipeline.statuses.size).to eq(expected_status_size)
end
......
......@@ -119,16 +119,16 @@
end
it 'has pipeline stages' do
expect(saved_project_json.dig('pipelines', 0, 'stages')).not_to be_empty
expect(saved_project_json.dig('ci_pipelines', 0, 'stages')).not_to be_empty
end
it 'has pipeline statuses' do
expect(saved_project_json.dig('pipelines', 0, 'stages', 0, 'statuses')).not_to be_empty
expect(saved_project_json.dig('ci_pipelines', 0, 'stages', 0, 'statuses')).not_to be_empty
end
it 'has pipeline builds' do
builds_count = saved_project_json
.dig('pipelines', 0, 'stages', 0, 'statuses')
.dig('ci_pipelines', 0, 'stages', 0, 'statuses')
.count { |hash| hash['type'] == 'Ci::Build' }
expect(builds_count).to eq(1)
......@@ -142,11 +142,11 @@
end
it 'has pipeline commits' do
expect(saved_project_json['pipelines']).not_to be_empty
expect(saved_project_json['ci_pipelines']).not_to be_empty
end
it 'has ci pipeline notes' do
expect(saved_project_json['pipelines'].first['notes']).not_to be_empty
expect(saved_project_json['ci_pipelines'].first['notes']).not_to be_empty
end
it 'has labels with no associations' do
......
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::ImportExport::RelationRenameService do
let(:renames) do
{
'example_relation1' => 'new_example_relation1',
'example_relation2' => 'new_example_relation2'
}
end
let(:user) { create(:admin) }
let(:group) { create(:group, :nested) }
let!(:project) { create(:project, :builds_disabled, :issues_disabled, name: 'project', path: 'project') }
let(:shared) { project.import_export_shared }
before do
stub_const("#{described_class}::RENAMES", renames)
end
context 'when importing' do
let(:project_tree_restorer) { Gitlab::ImportExport::ProjectTreeRestorer.new(user: user, shared: shared, project: project) }
let(:import_path) { 'spec/lib/gitlab/import_export' }
let(:file_content) { IO.read("#{import_path}/project.json") }
let!(:json_file) { ActiveSupport::JSON.decode(file_content) }
let(:tree_hash) { project_tree_restorer.instance_variable_get(:@tree_hash) }
before do
allow(shared).to receive(:export_path).and_return(import_path)
allow(ActiveSupport::JSON).to receive(:decode).with(file_content).and_return(json_file)
end
context 'when the file has only old relationship names' do
# Configuring the json as an old version exported file, with only
# the previous association with the old name
before do
renames.each do |old_name, _|
json_file[old_name.to_s] = []
end
end
it 'renames old relationships to the new name' do
expect(json_file.keys).to include(*renames.keys)
project_tree_restorer.restore
expect(json_file.keys).to include(*renames.values)
expect(json_file.keys).not_to include(*renames.keys)
end
end
context 'when the file has both the old and new relationships' do
# Configuring the json as the new version exported file, with both
# the old association name and the new one
before do
renames.each do |old_name, new_name|
json_file[old_name.to_s] = [1]
json_file[new_name.to_s] = [2]
end
end
it 'uses the new relationships and removes the old ones from the hash' do
expect(json_file.keys).to include(*renames.keys)
project_tree_restorer.restore
expect(json_file.keys).to include(*renames.values)
expect(json_file.values_at(*renames.values).flatten.uniq.first).to eq 2
expect(json_file.keys).not_to include(*renames.keys)
end
end
context 'when the file has only new relationship names' do
# Configuring the json as the future version exported file, with only
# the new association name
before do
renames.each do |_, new_name|
json_file[new_name.to_s] = []
end
end
it 'uses the new relationships' do
expect(json_file.keys).not_to include(*renames.keys)
project_tree_restorer.restore
expect(json_file.keys).to include(*renames.values)
end
end
end
context 'when exporting' do
let(:project_tree_saver) { Gitlab::ImportExport::ProjectTreeSaver.new(project: project, current_user: user, shared: shared) }
let(:project_tree) { project_tree_saver.send(:project_json) }
it 'adds old relationships to the exported file' do
project_tree.merge!(renames.values.map { |new_name| [new_name, []] }.to_h)
allow(project_tree_saver).to receive(:save) do |arg|
project_tree_saver.send(:project_json_tree)
end
result = project_tree_saver.save
saved_data = ActiveSupport::JSON.decode(result)
expect(saved_data.keys).to include(*(renames.keys + renames.values))
end
end
end
......@@ -33,8 +33,9 @@
describe 'associations' do
it 'has a bidirectional relationship with projects' do
expect(described_class.reflect_on_association(:project).has_inverse?).to eq(:pipelines)
expect(Project.reflect_on_association(:pipelines).has_inverse?).to eq(:project)
expect(described_class.reflect_on_association(:project).has_inverse?).to eq(:all_pipelines)
expect(Project.reflect_on_association(:all_pipelines).has_inverse?).to eq(:project)
expect(Project.reflect_on_association(:ci_pipelines).has_inverse?).to eq(:project)
end
end
......@@ -1186,7 +1187,7 @@ def create_build(name, *traits, queued_at: current, started_from: 0, **opts)
create(:ci_build, :allowed_to_fail, :failed, pipeline: pipeline, name: 'rubocop')
create(:ci_build, :allowed_to_fail, :failed, pipeline: pipeline2, name: 'rubocop')
pipelines = project.pipelines.to_a
pipelines = project.ci_pipelines.to_a
pipelines.each(&:number_of_warnings)
......
......@@ -63,7 +63,7 @@
it { is_expected.to have_one(:forked_from_project).through(:fork_network_member) }
it { is_expected.to have_one(:auto_devops).class_name('ProjectAutoDevops') }
it { is_expected.to have_many(:commit_statuses) }
it { is_expected.to have_many(:pipelines) }
it { is_expected.to have_many(:ci_pipelines) }
it { is_expected.to have_many(:builds) }
it { is_expected.to have_many(:build_trace_section_names)}
it { is_expected.to have_many(:runner_projects) }
......@@ -142,6 +142,29 @@
expect(subject.boards.size).to eq 1
end
end
describe 'ci_pipelines association' do
context 'when feature flag pipeline_ci_sources_only is enabled' do
it 'returns only pipelines from ci_sources' do
stub_feature_flags(pipeline_ci_sources_only: true)
expect(Ci::Pipeline).to receive(:ci_sources).and_call_original
subject.ci_pipelines
end
end
context 'when feature flag pipeline_ci_sources_only is disabled' do
it 'returns all pipelines' do
stub_feature_flags(pipeline_ci_sources_only: false)
expect(Ci::Pipeline).not_to receive(:ci_sources).and_call_original
expect(Ci::Pipeline).to receive(:all).and_call_original.at_least(:once)
subject.ci_pipelines
end
end
end
end
describe 'modules' do
......@@ -3373,7 +3396,7 @@ def domain_variable
context 'with a ref that is not the default branch' do
it 'returns the latest successful pipeline for the given ref' do
expect(project.pipelines).to receive(:latest_successful_for).with('foo')
expect(project.ci_pipelines).to receive(:latest_successful_for).with('foo')
project.latest_successful_pipeline_for('foo')
end
......@@ -3401,7 +3424,7 @@ def domain_variable
it 'memoizes and returns the latest successful pipeline for the default branch' do
pipeline = double(:pipeline)
expect(project.pipelines).to receive(:latest_successful_for)
expect(project.ci_pipelines).to receive(:latest_successful_for)
.with(project.default_branch)
.and_return(pipeline)
.once
......
......@@ -16,8 +16,8 @@
let(:get_url) { "/projects/#{project.id}/repository/commits/#{sha}/statuses" }
context 'ci commit exists' do
let!(:master) { project.pipelines.create(source: :push, sha: commit.id, ref: 'master', protected: false) }
let!(:develop) { project.pipelines.create(source: :push, sha: commit.id, ref: 'develop', protected: false) }
let!(:master) { project.ci_pipelines.create(source: :push, sha: commit.id, ref: 'master', protected: false) }
let!(:develop) { project.ci_pipelines.create(source: :push, sha: commit.id, ref: 'develop', protected: false) }
context "reporter user" do
let(:statuses_id) { json_response.map { |status| status['id'] } }
......
......@@ -818,7 +818,7 @@ def push_params(branch_name)
end
context 'when the ref has a pipeline' do
let!(:pipeline) { project.pipelines.create(source: :push, ref: 'master', sha: commit.sha, protected: false) }
let!(:pipeline) { project.ci_pipelines.create(source: :push, ref: 'master', sha: commit.sha, protected: false) }
it 'includes a "created" status' do
get api(route, current_user)
......
......@@ -304,7 +304,7 @@ def expect_variables(variables, expected_variables)
it 'creates and returns a new pipeline' do
expect do
post api("/projects/#{project.id}/pipeline", user), ref: project.default_branch
end.to change { project.pipelines.count }.by(1)
end.to change { project.ci_pipelines.count }.by(1)
expect(response).to have_gitlab_http_status(201)
expect(json_response).to be_a Hash
......@@ -317,8 +317,8 @@ def expect_variables(variables, expected_variables)
it 'creates and returns a new pipeline using the given variables' do
expect do
post api("/projects/#{project.id}/pipeline", user), ref: project.default_branch, variables: variables
end.to change { project.pipelines.count }.by(1)
expect_variables(project.pipelines.last.variables, variables)
end.to change { project.ci_pipelines.count }.by(1)
expect_variables(project.ci_pipelines.last.variables, variables)
expect(response).to have_gitlab_http_status(201)
expect(json_response).to be_a Hash
......@@ -338,8 +338,8 @@ def expect_variables(variables, expected_variables)
it 'creates and returns a new pipeline using the given variables' do
expect do
post api("/projects/#{project.id}/pipeline", user), ref: project.default_branch, variables: variables
end.to change { project.pipelines.count }.by(1)
expect_variables(project.pipelines.last.variables, variables)
end.to change { project.ci_pipelines.count }.by(1)
expect_variables(project.ci_pipelines.last.variables, variables)
expect(response).to have_gitlab_http_status(201)
expect(json_response).to be_a Hash
......@@ -353,7 +353,7 @@ def expect_variables(variables, expected_variables)
it "doesn't create a job" do
expect do
post api("/projects/#{project.id}/pipeline", user), ref: project.default_branch
end.not_to change { project.pipelines.count }
end.not_to change { project.ci_pipelines.count }
expect(response).to have_gitlab_http_status(400)
end
......
......@@ -39,7 +39,7 @@
end
context 'Have a commit' do
let(:pipeline) { project.pipelines.last }
let(:pipeline) { project.ci_pipelines.last }
it 'creates pipeline' do
post api("/projects/#{project.id}/trigger/pipeline"), options.merge(ref: 'master')
......
......@@ -44,7 +44,7 @@ def execute_service(
expect(pipeline).to be_valid
expect(pipeline).to be_persisted
expect(pipeline).to be_push
expect(pipeline).to eq(project.pipelines.last)
expect(pipeline).to eq(project.ci_pipelines.last)
expect(pipeline).to have_attributes(user: user)
expect(pipeline).to have_attributes(status: 'pending')
expect(pipeline.repository_source?).to be true
......@@ -731,8 +731,8 @@ def previous_commit_sha_from_ref(ref)
it 'creates a merge request pipeline in the forked project' do
expect(pipeline).to be_persisted
expect(project.pipelines).to eq([pipeline])
expect(target_project.pipelines).to be_empty
expect(project.ci_pipelines).to eq([pipeline])
expect(target_project.ci_pipelines).to be_empty
end
end
......
......@@ -25,12 +25,12 @@
context 'when there is a scheduled pipeline within next_run_at' do
shared_examples 'successful scheduling' do
it 'creates a new pipeline' do
expect { subject }.to change { project.pipelines.count }.by(1)
expect { subject }.to change { project.ci_pipelines.count }.by(1)
expect(Ci::Pipeline.last).to be_schedule
pipeline_schedule.reload
expect(pipeline_schedule.next_run_at).to be > Time.now
expect(pipeline_schedule).to eq(project.pipelines.last.pipeline_schedule)
expect(pipeline_schedule).to eq(project.ci_pipelines.last.pipeline_schedule)
expect(pipeline_schedule).to be_active
end
end
......@@ -54,7 +54,7 @@
end
it 'does not creates a new pipeline' do
expect { subject }.not_to change { project.pipelines.count }
expect { subject }.not_to change { project.ci_pipelines.count }
end
end
......@@ -64,7 +64,7 @@
end
it 'creates a failed pipeline with the reason' do
expect { subject }.to change { project.pipelines.count }.by(1)
expect { subject }.to change { project.ci_pipelines.count }.by(1)
expect(Ci::Pipeline.last).to be_config_error
expect(Ci::Pipeline.last.yaml_errors).not_to be_nil
end
......@@ -105,7 +105,7 @@
end
it 'does not create a pipeline' do
expect { subject }.not_to change { project.pipelines.count }
expect { subject }.not_to change { project.ci_pipelines.count }
end
it 'does not raise an exception' do
......@@ -135,7 +135,7 @@
end
it 'does not create a pipeline' do
expect { subject }.not_to change { project.pipelines.count }
expect { subject }.not_to change { project.ci_pipelines.count }
end
it 'does not raise an exception' do
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment