2019-04-11 08:17:24 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2017-02-10 10:19:29 -05:00
|
|
|
require 'spec_helper'
|
|
|
|
|
2022-03-23 14:08:47 -04:00
|
|
|
RSpec.describe Ci::RetryJobService do
|
2020-10-05 05:08:17 -04:00
|
|
|
let_it_be(:reporter) { create(:user) }
|
|
|
|
let_it_be(:developer) { create(:user) }
|
2020-01-10 04:07:49 -05:00
|
|
|
let_it_be(:project) { create(:project, :repository) }
|
|
|
|
let_it_be(:pipeline) do
|
2019-12-20 22:07:37 -05:00
|
|
|
create(:ci_pipeline, project: project,
|
|
|
|
sha: 'b83d6e391c22777fca1ed3012fce84f633d7fed0')
|
|
|
|
end
|
2017-09-05 04:13:46 -04:00
|
|
|
|
2020-10-05 05:08:17 -04:00
|
|
|
let_it_be(:stage) do
|
2018-04-17 07:47:35 -04:00
|
|
|
create(:ci_stage_entity, project: project,
|
|
|
|
pipeline: pipeline,
|
|
|
|
name: 'test')
|
2018-01-25 09:15:51 -05:00
|
|
|
end
|
|
|
|
|
2022-03-23 14:08:47 -04:00
|
|
|
let_it_be_with_refind(:build) { create(:ci_build, :success, pipeline: pipeline, stage_id: stage.id) }
|
2021-04-21 05:09:15 -04:00
|
|
|
|
2020-10-05 05:08:17 -04:00
|
|
|
let(:user) { developer }
|
2017-02-10 10:19:29 -05:00
|
|
|
|
|
|
|
let(:service) do
|
2017-02-14 04:38:17 -05:00
|
|
|
described_class.new(project, user)
|
2017-02-10 10:19:29 -05:00
|
|
|
end
|
|
|
|
|
2020-10-05 05:08:17 -04:00
|
|
|
before_all do
|
|
|
|
project.add_developer(developer)
|
|
|
|
project.add_reporter(reporter)
|
|
|
|
end
|
|
|
|
|
2022-03-23 14:08:47 -04:00
|
|
|
clone_accessors = ::Ci::Build.clone_accessors.without(::Ci::Build.extra_accessors)
|
2017-03-02 05:51:24 -05:00
|
|
|
|
2020-05-19 08:08:21 -04:00
|
|
|
reject_accessors =
|
2018-12-06 04:42:18 -05:00
|
|
|
%i[id status user token token_encrypted coverage trace runner
|
2019-03-22 08:38:45 -04:00
|
|
|
artifacts_expire_at
|
2018-12-06 04:42:18 -05:00
|
|
|
created_at updated_at started_at finished_at queued_at erased_by
|
2018-02-06 09:18:32 -05:00
|
|
|
erased_at auto_canceled_by job_artifacts job_artifacts_archive
|
2018-09-27 17:15:08 -04:00
|
|
|
job_artifacts_metadata job_artifacts_trace job_artifacts_junit
|
2020-05-29 20:08:33 -04:00
|
|
|
job_artifacts_sast job_artifacts_secret_detection job_artifacts_dependency_scanning
|
2021-07-06 05:07:05 -04:00
|
|
|
job_artifacts_container_scanning job_artifacts_cluster_image_scanning job_artifacts_dast
|
2021-06-14 11:09:48 -04:00
|
|
|
job_artifacts_license_scanning
|
2020-07-10 08:09:15 -04:00
|
|
|
job_artifacts_performance job_artifacts_browser_performance job_artifacts_load_performance
|
2020-07-09 11:08:59 -04:00
|
|
|
job_artifacts_lsif job_artifacts_terraform job_artifacts_cluster_applications
|
2019-07-29 03:43:10 -04:00
|
|
|
job_artifacts_codequality job_artifacts_metrics scheduled_at
|
2020-01-15 16:08:48 -05:00
|
|
|
job_variables waiting_for_resource_at job_artifacts_metrics_referee
|
2020-03-17 14:09:44 -04:00
|
|
|
job_artifacts_network_referee job_artifacts_dotenv
|
2020-06-08 08:08:26 -04:00
|
|
|
job_artifacts_cobertura needs job_artifacts_accessibility
|
2020-10-07 17:08:21 -04:00
|
|
|
job_artifacts_requirements job_artifacts_coverage_fuzzing
|
2021-09-23 02:12:14 -04:00
|
|
|
job_artifacts_api_fuzzing terraform_state_versions].freeze
|
2017-03-02 05:51:24 -05:00
|
|
|
|
2020-05-19 08:08:21 -04:00
|
|
|
ignore_accessors =
|
2017-09-25 12:54:08 -04:00
|
|
|
%i[type lock_version target_url base_tags trace_sections
|
2018-11-04 19:37:40 -05:00
|
|
|
commit_id deployment erased_by_id project_id
|
2017-03-02 05:51:24 -05:00
|
|
|
runner_id tag_taggings taggings tags trigger_request_id
|
2018-02-28 14:06:12 -05:00
|
|
|
user_id auto_canceled_by_id retried failure_reason
|
2019-04-10 06:28:01 -04:00
|
|
|
sourced_pipelines artifacts_file_store artifacts_metadata_store
|
Backport the EE schema and migrations to CE
This backports all EE schema changes to CE, including EE migrations,
ensuring both use the same schema.
== Updated tests
A spec related to ghost and support bot users had to be modified to make
it pass. The spec in question assumes that the "support_bot" column
exists when defining the spec. In the single codebase setup this is not
the case, as the column is backported in a later migration. Any attempt
to use a different schema version or use of "around" blocks to
conditionally disable specs won't help, as reverting the backport
migration would also drop the "support_bot" column. Removing the
"support_bot" tests entirely appears to be the only solution.
We also need to update some foreign key tests now that we have
backported the EE columns. Fortunately, these changes are very minor.
== Backporting migrations
This commit moves EE specific migrations (except those for the Geo
tracking database) and related files to CE, and also removes any traces
of the ee/db directory.
Some migrations had to be modified or removed, as they no longer work
with the schema being backported. These migrations were all quite old,
so we opted for removing them where modifying them would take too much
time and effort.
Some old migrations were modified in EE, while also existing in CE. In
these cases we took the EE code, and in one case removed them entirely.
It's not worth spending time trying to merge these changes somehow as we
plan to remove old migrations around the release of 12.0, see
https://gitlab.com/gitlab-org/gitlab-ce/issues/59177 for more details.
2019-04-29 08:16:03 -04:00
|
|
|
metadata runner_session trace_chunks upstream_pipeline_id
|
2020-01-17 10:08:37 -05:00
|
|
|
artifacts_file artifacts_metadata artifacts_size commands
|
2020-02-26 10:08:56 -05:00
|
|
|
resource resource_group_id processed security_scans author
|
2021-05-19 11:10:40 -04:00
|
|
|
pipeline_id report_results pending_state pages_deployments
|
2022-02-07 10:15:53 -05:00
|
|
|
queuing_entry runtime_metadata trace_metadata
|
|
|
|
dast_site_profile dast_scanner_profile].freeze
|
2017-03-02 05:51:24 -05:00
|
|
|
|
2017-02-15 10:04:05 -05:00
|
|
|
shared_examples 'build duplication' do
|
2020-10-05 05:08:17 -04:00
|
|
|
let_it_be(:another_pipeline) { create(:ci_empty_pipeline, project: project) }
|
2017-06-07 04:05:40 -04:00
|
|
|
|
2020-10-05 05:08:17 -04:00
|
|
|
let_it_be(:build) do
|
2021-06-08 05:09:56 -04:00
|
|
|
create(:ci_build, :failed, :picked, :expired, :erased, :queued, :coverage, :tags,
|
2019-12-19 10:07:55 -05:00
|
|
|
:allowed_to_fail, :on_tag, :triggered, :teardown_environment, :resource_group,
|
2018-01-25 09:15:51 -05:00
|
|
|
description: 'my-job', stage: 'test', stage_id: stage.id,
|
2018-09-26 01:37:11 -04:00
|
|
|
pipeline: pipeline, auto_canceled_by: another_pipeline,
|
|
|
|
scheduled_at: 10.seconds.since)
|
2018-01-25 09:15:51 -05:00
|
|
|
end
|
|
|
|
|
2021-12-06 16:10:14 -05:00
|
|
|
let_it_be(:internal_job_variable) { create(:ci_job_variable, job: build) }
|
|
|
|
|
2020-10-05 05:08:17 -04:00
|
|
|
before_all do
|
2018-01-25 09:15:51 -05:00
|
|
|
# Make sure that build has both `stage_id` and `stage` because FactoryBot
|
|
|
|
# can reset one of the fields when assigning another. We plan to deprecate
|
|
|
|
# and remove legacy `stage` column in the future.
|
2020-09-07 14:08:32 -04:00
|
|
|
build.update!(stage: 'test', stage_id: stage.id)
|
2018-09-27 17:15:08 -04:00
|
|
|
|
|
|
|
# Make sure we have one instance for every possible job_artifact_X
|
|
|
|
# associations to check they are correctly rejected on build duplication.
|
|
|
|
Ci::JobArtifact::TYPE_AND_FORMAT_PAIRS.each do |file_type, file_format|
|
|
|
|
create(:ci_job_artifact, file_format,
|
|
|
|
file_type: file_type, job: build, expire_at: build.artifacts_expire_at)
|
|
|
|
end
|
|
|
|
|
2021-12-06 16:10:14 -05:00
|
|
|
create(:ci_job_variable, :dotenv_source, job: build)
|
2019-08-01 10:26:49 -04:00
|
|
|
create(:ci_build_need, build: build)
|
2021-09-23 02:12:14 -04:00
|
|
|
create(:terraform_state_version, build: build)
|
2017-02-15 10:04:05 -05:00
|
|
|
end
|
|
|
|
|
2022-03-23 14:08:47 -04:00
|
|
|
before do
|
|
|
|
build.update!(retried: false, status: :success)
|
|
|
|
end
|
|
|
|
|
2017-03-02 05:51:24 -05:00
|
|
|
describe 'clone accessors' do
|
2020-02-26 10:08:56 -05:00
|
|
|
let(:forbidden_associations) do
|
|
|
|
Ci::Build.reflect_on_all_associations.each_with_object(Set.new) do |assoc, memo|
|
|
|
|
memo << assoc.name unless assoc.macro == :belongs_to
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-05-19 08:08:21 -04:00
|
|
|
clone_accessors.each do |attribute|
|
2021-06-18 08:10:03 -04:00
|
|
|
it "clones #{attribute} build attribute", :aggregate_failures do
|
2020-02-26 10:08:56 -05:00
|
|
|
expect(attribute).not_to be_in(forbidden_associations), "association #{attribute} must be `belongs_to`"
|
2018-01-25 09:15:51 -05:00
|
|
|
expect(build.send(attribute)).not_to be_nil
|
2017-09-01 04:54:07 -04:00
|
|
|
expect(new_build.send(attribute)).not_to be_nil
|
2017-02-16 07:13:10 -05:00
|
|
|
expect(new_build.send(attribute)).to eq build.send(attribute)
|
|
|
|
end
|
|
|
|
end
|
2017-09-06 10:09:41 -04:00
|
|
|
|
|
|
|
context 'when job has nullified protected' do
|
|
|
|
before do
|
|
|
|
build.update_attribute(:protected, nil)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "clones protected build attribute" do
|
2017-09-06 12:13:49 -04:00
|
|
|
expect(new_build.protected).to be_nil
|
2017-09-06 10:09:41 -04:00
|
|
|
expect(new_build.protected).to eq build.protected
|
|
|
|
end
|
|
|
|
end
|
2020-02-26 10:08:56 -05:00
|
|
|
|
|
|
|
it 'clones only the needs attributes' do
|
|
|
|
expect(new_build.needs.exists?).to be_truthy
|
|
|
|
expect(build.needs.exists?).to be_truthy
|
|
|
|
|
|
|
|
expect(new_build.needs_attributes).to match(build.needs_attributes)
|
|
|
|
expect(new_build.needs).not_to match(build.needs)
|
|
|
|
end
|
2021-12-06 16:10:14 -05:00
|
|
|
|
2021-12-10 10:10:24 -05:00
|
|
|
it 'clones only internal job variables' do
|
|
|
|
expect(new_build.job_variables.count).to eq(1)
|
|
|
|
expect(new_build.job_variables).to contain_exactly(having_attributes(key: internal_job_variable.key, value: internal_job_variable.value))
|
2021-12-06 16:10:14 -05:00
|
|
|
end
|
2017-02-16 07:13:10 -05:00
|
|
|
end
|
2017-02-15 10:04:05 -05:00
|
|
|
|
2020-02-26 10:08:56 -05:00
|
|
|
describe 'reject accessors' do
|
2020-05-19 08:08:21 -04:00
|
|
|
reject_accessors.each do |attribute|
|
2017-02-16 07:13:10 -05:00
|
|
|
it "does not clone #{attribute} build attribute" do
|
|
|
|
expect(new_build.send(attribute)).not_to eq build.send(attribute)
|
|
|
|
end
|
2017-02-15 10:04:05 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-06-18 08:10:03 -04:00
|
|
|
it 'has correct number of known attributes', :aggregate_failures do
|
2020-05-19 08:08:21 -04:00
|
|
|
processed_accessors = clone_accessors + reject_accessors
|
|
|
|
known_accessors = processed_accessors + ignore_accessors
|
2017-03-01 05:39:36 -05:00
|
|
|
|
|
|
|
# :tag_list is a special case, this accessor does not exist
|
|
|
|
# in reflected associations, comes from `act_as_taggable` and
|
|
|
|
# we use it to copy tags, instead of reusing tags.
|
|
|
|
#
|
|
|
|
current_accessors =
|
2017-03-02 05:51:24 -05:00
|
|
|
Ci::Build.attribute_names.map(&:to_sym) +
|
2020-02-26 10:08:56 -05:00
|
|
|
Ci::Build.attribute_aliases.keys.map(&:to_sym) +
|
2017-03-02 05:51:24 -05:00
|
|
|
Ci::Build.reflect_on_all_associations.map(&:name) +
|
2021-12-10 10:10:24 -05:00
|
|
|
[:tag_list, :needs_attributes, :job_variables_attributes] -
|
2022-03-23 14:08:47 -04:00
|
|
|
# ee-specific accessors should be tested in ee/spec/services/ci/retry_job_service_spec.rb instead
|
|
|
|
Ci::Build.extra_accessors -
|
2021-06-18 08:10:03 -04:00
|
|
|
[:dast_site_profiles_build, :dast_scanner_profiles_build] # join tables
|
2020-08-28 14:10:51 -04:00
|
|
|
|
2017-03-01 05:39:36 -05:00
|
|
|
current_accessors.uniq!
|
|
|
|
|
2019-04-10 06:28:01 -04:00
|
|
|
expect(current_accessors).to include(*processed_accessors)
|
|
|
|
expect(known_accessors).to include(*current_accessors)
|
2017-02-15 10:04:05 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-02-14 04:38:17 -05:00
|
|
|
describe '#execute' do
|
2018-07-07 07:46:23 -04:00
|
|
|
let(:new_build) do
|
2020-10-02 08:09:03 -04:00
|
|
|
travel_to(1.second.from_now) do
|
2022-03-23 14:08:47 -04:00
|
|
|
service.execute(build)[:job]
|
2018-07-07 07:46:23 -04:00
|
|
|
end
|
|
|
|
end
|
2017-02-10 10:19:29 -05:00
|
|
|
|
2017-02-14 04:38:17 -05:00
|
|
|
context 'when user has ability to execute build' do
|
2017-02-10 10:19:29 -05:00
|
|
|
before do
|
2017-07-18 10:32:34 -04:00
|
|
|
stub_not_protect_default_branch
|
2017-02-10 10:19:29 -05:00
|
|
|
end
|
|
|
|
|
2017-02-15 10:04:05 -05:00
|
|
|
it_behaves_like 'build duplication'
|
|
|
|
|
2017-02-10 10:19:29 -05:00
|
|
|
it 'creates a new build that represents the old one' do
|
|
|
|
expect(new_build.name).to eq build.name
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'enqueues the new build' do
|
|
|
|
expect(new_build).to be_pending
|
|
|
|
end
|
|
|
|
|
2020-08-21 11:10:03 -04:00
|
|
|
context 'when there are subsequent processables that are skipped' do
|
2017-02-10 10:19:29 -05:00
|
|
|
let!(:subsequent_build) do
|
2018-01-25 09:15:51 -05:00
|
|
|
create(:ci_build, :skipped, stage_idx: 2,
|
|
|
|
pipeline: pipeline,
|
|
|
|
stage: 'deploy')
|
2017-02-10 10:19:29 -05:00
|
|
|
end
|
|
|
|
|
2020-08-21 11:10:03 -04:00
|
|
|
let!(:subsequent_bridge) do
|
|
|
|
create(:ci_bridge, :skipped, stage_idx: 2,
|
|
|
|
pipeline: pipeline,
|
|
|
|
stage: 'deploy')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'resumes pipeline processing in the subsequent stage' do
|
2017-02-14 04:38:17 -05:00
|
|
|
service.execute(build)
|
2017-02-10 10:19:29 -05:00
|
|
|
|
|
|
|
expect(subsequent_build.reload).to be_created
|
2020-08-21 11:10:03 -04:00
|
|
|
expect(subsequent_bridge.reload).to be_created
|
2017-02-10 10:19:29 -05:00
|
|
|
end
|
2020-12-21 10:10:05 -05:00
|
|
|
|
|
|
|
it 'updates ownership for subsequent builds' do
|
|
|
|
expect { service.execute(build) }.to change { subsequent_build.reload.user }.to(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'updates ownership for subsequent bridges' do
|
|
|
|
expect { service.execute(build) }.to change { subsequent_bridge.reload.user }.to(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not cause n+1 when updaing build ownership' do
|
|
|
|
control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) { service.execute(build) }.count
|
|
|
|
|
|
|
|
create_list(:ci_build, 2, :skipped, stage_idx: build.stage_idx + 1, pipeline: pipeline, stage: 'deploy')
|
|
|
|
|
|
|
|
expect { service.execute(build) }.not_to exceed_all_query_limit(control_count)
|
|
|
|
end
|
2017-02-10 10:19:29 -05:00
|
|
|
end
|
2020-05-15 11:08:04 -04:00
|
|
|
|
|
|
|
context 'when pipeline has other builds' do
|
|
|
|
let!(:stage2) { create(:ci_stage_entity, project: project, pipeline: pipeline, name: 'deploy') }
|
|
|
|
let!(:build2) { create(:ci_build, pipeline: pipeline, stage_id: stage.id ) }
|
|
|
|
let!(:deploy) { create(:ci_build, pipeline: pipeline, stage_id: stage2.id) }
|
|
|
|
let!(:deploy_needs_build2) { create(:ci_build_need, build: deploy, name: build2.name) }
|
|
|
|
|
|
|
|
context 'when build has nil scheduling_type' do
|
|
|
|
before do
|
|
|
|
build.pipeline.processables.update_all(scheduling_type: nil)
|
|
|
|
build.reload
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'populates scheduling_type of processables' do
|
|
|
|
expect(new_build.scheduling_type).to eq('stage')
|
|
|
|
expect(build.reload.scheduling_type).to eq('stage')
|
|
|
|
expect(build2.reload.scheduling_type).to eq('stage')
|
|
|
|
expect(deploy.reload.scheduling_type).to eq('dag')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when build has scheduling_type' do
|
|
|
|
it 'does not call populate_scheduling_type!' do
|
2022-03-23 14:08:47 -04:00
|
|
|
expect_any_instance_of(Ci::Pipeline).not_to receive(:ensure_scheduling_type!) # rubocop: disable RSpec/AnyInstanceOf
|
2020-05-15 11:08:04 -04:00
|
|
|
|
|
|
|
expect(new_build.scheduling_type).to eq('stage')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2020-09-17 08:09:37 -04:00
|
|
|
|
|
|
|
context 'when the pipeline is a child pipeline and the bridge is depended' do
|
|
|
|
let!(:parent_pipeline) { create(:ci_pipeline, project: project) }
|
|
|
|
let!(:bridge) { create(:ci_bridge, :strategy_depend, pipeline: parent_pipeline, status: 'success') }
|
|
|
|
let!(:source_pipeline) { create(:ci_sources_pipeline, pipeline: pipeline, source_job: bridge) }
|
|
|
|
|
|
|
|
it 'marks source bridge as pending' do
|
|
|
|
service.execute(build)
|
|
|
|
|
|
|
|
expect(bridge.reload).to be_pending
|
|
|
|
end
|
|
|
|
end
|
2021-12-30 13:13:34 -05:00
|
|
|
|
|
|
|
context 'when there is a failed job todo for the MR' do
|
|
|
|
let!(:merge_request) { create(:merge_request, source_project: project, author: user, head_pipeline: pipeline) }
|
|
|
|
let!(:todo) { create(:todo, :build_failed, user: user, project: project, author: user, target: merge_request) }
|
|
|
|
|
|
|
|
it 'resolves the todo for the old failed build' do
|
|
|
|
expect do
|
|
|
|
service.execute(build)
|
|
|
|
end.to change { todo.reload.state }.from('pending').to('done')
|
|
|
|
end
|
|
|
|
end
|
2017-02-10 10:19:29 -05:00
|
|
|
end
|
|
|
|
|
2017-02-14 04:38:17 -05:00
|
|
|
context 'when user does not have ability to execute build' do
|
2020-10-05 05:08:17 -04:00
|
|
|
let(:user) { reporter }
|
|
|
|
|
2017-02-10 10:19:29 -05:00
|
|
|
it 'raises an error' do
|
2017-02-14 04:38:17 -05:00
|
|
|
expect { service.execute(build) }
|
2017-02-10 10:19:29 -05:00
|
|
|
.to raise_error Gitlab::Access::AccessDeniedError
|
|
|
|
end
|
2022-03-23 14:08:47 -04:00
|
|
|
|
|
|
|
context 'when the job is not retryable' do
|
|
|
|
let(:build) { create(:ci_build, :created, pipeline: pipeline) }
|
|
|
|
|
|
|
|
it 'returns a ServiceResponse error' do
|
|
|
|
response = service.execute(build)
|
|
|
|
|
|
|
|
expect(response).to be_a(ServiceResponse)
|
|
|
|
expect(response).to be_error
|
|
|
|
expect(response.message).to eq("Job cannot be retried")
|
|
|
|
end
|
|
|
|
end
|
2017-02-10 10:19:29 -05:00
|
|
|
end
|
|
|
|
end
|
2017-02-14 09:22:49 -05:00
|
|
|
|
2021-09-23 18:34:10 -04:00
|
|
|
describe '#clone!' do
|
2018-07-07 07:46:23 -04:00
|
|
|
let(:new_build) do
|
2020-10-02 08:09:03 -04:00
|
|
|
travel_to(1.second.from_now) do
|
2021-09-23 18:34:10 -04:00
|
|
|
service.clone!(build)
|
2018-07-07 07:46:23 -04:00
|
|
|
end
|
|
|
|
end
|
2017-02-14 09:22:49 -05:00
|
|
|
|
2021-09-22 14:11:13 -04:00
|
|
|
it 'raises an error when an unexpected class is passed' do
|
2021-09-23 18:34:10 -04:00
|
|
|
expect { service.clone!(create(:ci_build).present) }.to raise_error(TypeError)
|
2021-09-22 14:11:13 -04:00
|
|
|
end
|
|
|
|
|
2017-02-14 09:22:49 -05:00
|
|
|
context 'when user has ability to execute build' do
|
|
|
|
before do
|
2017-07-18 10:32:34 -04:00
|
|
|
stub_not_protect_default_branch
|
2017-02-14 09:22:49 -05:00
|
|
|
end
|
|
|
|
|
2017-02-15 10:04:05 -05:00
|
|
|
it_behaves_like 'build duplication'
|
|
|
|
|
2017-02-14 09:22:49 -05:00
|
|
|
it 'creates a new build that represents the old one' do
|
|
|
|
expect(new_build.name).to eq build.name
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not enqueue the new build' do
|
|
|
|
expect(new_build).to be_created
|
2020-01-17 10:08:37 -05:00
|
|
|
expect(new_build).not_to be_processed
|
2017-02-14 09:22:49 -05:00
|
|
|
end
|
2017-04-16 07:14:39 -04:00
|
|
|
|
2020-01-17 10:08:37 -05:00
|
|
|
it 'does mark old build as retried' do
|
2017-04-16 07:14:39 -04:00
|
|
|
expect(new_build).to be_latest
|
2017-10-13 11:26:17 -04:00
|
|
|
expect(build).to be_retried
|
2020-01-17 10:08:37 -05:00
|
|
|
expect(build).to be_processed
|
2017-04-16 07:14:39 -04:00
|
|
|
end
|
2019-10-15 08:06:06 -04:00
|
|
|
|
2021-12-10 13:14:42 -05:00
|
|
|
shared_examples_for 'when build with deployment is retried' do
|
2019-10-15 08:06:06 -04:00
|
|
|
let!(:build) do
|
2019-12-20 22:07:37 -05:00
|
|
|
create(:ci_build, :with_deployment, :deploy_to_production,
|
|
|
|
pipeline: pipeline, stage_id: stage.id, project: project)
|
2019-10-15 08:06:06 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'creates a new deployment' do
|
|
|
|
expect { new_build }.to change { Deployment.count }.by(1)
|
|
|
|
end
|
2020-03-03 19:07:52 -05:00
|
|
|
|
|
|
|
it 'persists expanded environment name' do
|
|
|
|
expect(new_build.metadata.expanded_environment_name).to eq('production')
|
|
|
|
end
|
2021-10-28 17:10:02 -04:00
|
|
|
|
|
|
|
it 'does not create a new environment' do
|
|
|
|
expect { new_build }.not_to change { Environment.count }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-12-10 13:14:42 -05:00
|
|
|
shared_examples_for 'when build with dynamic environment is retried' do
|
2022-03-18 14:07:26 -04:00
|
|
|
let_it_be(:other_developer) { create(:user).tap { |u| project.add_developer(u) } }
|
2021-10-28 17:10:02 -04:00
|
|
|
|
|
|
|
let(:environment_name) { 'review/$CI_COMMIT_REF_SLUG-$GITLAB_USER_ID' }
|
|
|
|
|
|
|
|
let!(:build) do
|
|
|
|
create(:ci_build, :with_deployment, environment: environment_name,
|
|
|
|
options: { environment: { name: environment_name } },
|
|
|
|
pipeline: pipeline, stage_id: stage.id, project: project,
|
|
|
|
user: other_developer)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 're-uses the previous persisted environment' do
|
|
|
|
expect(build.persisted_environment.name).to eq("review/#{build.ref}-#{other_developer.id}")
|
|
|
|
|
|
|
|
expect(new_build.persisted_environment.name).to eq("review/#{build.ref}-#{other_developer.id}")
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'creates a new deployment' do
|
|
|
|
expect { new_build }.to change { Deployment.count }.by(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not create a new environment' do
|
|
|
|
expect { new_build }.not_to change { Environment.count }
|
|
|
|
end
|
2019-10-15 08:06:06 -04:00
|
|
|
end
|
2020-07-15 08:09:26 -04:00
|
|
|
|
2021-12-10 13:14:42 -05:00
|
|
|
it_behaves_like 'when build with deployment is retried'
|
|
|
|
it_behaves_like 'when build with dynamic environment is retried'
|
|
|
|
|
2020-07-15 08:09:26 -04:00
|
|
|
context 'when build has needs' do
|
|
|
|
before do
|
|
|
|
create(:ci_build_need, build: build, name: 'build1')
|
|
|
|
create(:ci_build_need, build: build, name: 'build2')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'bulk inserts all needs' do
|
|
|
|
expect(Ci::BuildNeed).to receive(:bulk_insert!).and_call_original
|
|
|
|
|
|
|
|
new_build
|
|
|
|
end
|
|
|
|
end
|
2017-02-14 09:22:49 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'when user does not have ability to execute build' do
|
2020-10-05 05:08:17 -04:00
|
|
|
let(:user) { reporter }
|
|
|
|
|
2017-02-14 09:22:49 -05:00
|
|
|
it 'raises an error' do
|
2021-09-23 18:34:10 -04:00
|
|
|
expect { service.clone!(build) }
|
2017-02-14 09:22:49 -05:00
|
|
|
.to raise_error Gitlab::Access::AccessDeniedError
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2017-02-10 10:19:29 -05:00
|
|
|
end
|