Commit 6c28fd6b authored by Robert Speicher's avatar Robert Speicher

Merge branch...

Merge branch '235686-review-app-dynamic-environment-created-from-child-pipeline-does-not-show-up-in-merge-requests' into 'master'

Include environments created from child pipelines in merge requests

See merge request gitlab-org/gitlab!62080
parents 2bfb9663 6edd3da0
......@@ -922,6 +922,12 @@ module Ci
Ci::Build.latest.where(pipeline: self_and_descendants)
end
def environments_in_self_and_descendants
environment_ids = self_and_descendants.joins(:deployments).select(:'deployments.environment_id')
Environment.where(id: environment_ids)
end
# Without using `unscoped`, caller scope is also included into the query.
# Using `unscoped` here will be redundant after Rails 6.1
def self_and_descendants
......
......@@ -100,7 +100,7 @@ class EnvironmentStatus
def self.build_environments_status(mr, user, pipeline)
return [] unless pipeline
pipeline.environments.includes(:project).available.map do |environment|
pipeline.environments_in_self_and_descendants.includes(:project).available.map do |environment|
next unless Ability.allowed?(user, :read_environment, environment)
EnvironmentStatus.new(pipeline.project, environment, mr, pipeline.sha)
......
......@@ -3162,6 +3162,81 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
describe '#environments_in_self_and_descendants' do
subject { pipeline.environments_in_self_and_descendants }
context 'when pipeline is not child nor parent' do
let_it_be(:pipeline) { create(:ci_pipeline, :created) }
let_it_be(:build) { create(:ci_build, :with_deployment, :deploy_to_production, pipeline: pipeline) }
it 'returns just the pipeline environment' do
expect(subject).to contain_exactly(build.deployment.environment)
end
end
context 'when pipeline is in extended family' do
let_it_be(:parent) { create(:ci_pipeline) }
let_it_be(:parent_build) { create(:ci_build, :with_deployment, environment: 'staging', pipeline: parent) }
let_it_be(:pipeline) { create(:ci_pipeline, child_of: parent) }
let_it_be(:build) { create(:ci_build, :with_deployment, :deploy_to_production, pipeline: pipeline) }
let_it_be(:child) { create(:ci_pipeline, child_of: pipeline) }
let_it_be(:child_build) { create(:ci_build, :with_deployment, environment: 'canary', pipeline: child) }
let_it_be(:grandchild) { create(:ci_pipeline, child_of: child) }
let_it_be(:grandchild_build) { create(:ci_build, :with_deployment, environment: 'test', pipeline: grandchild) }
let_it_be(:sibling) { create(:ci_pipeline, child_of: parent) }
let_it_be(:sibling_build) { create(:ci_build, :with_deployment, environment: 'review', pipeline: sibling) }
it 'returns its own environment and from all descendants' do
expected_environments = [
build.deployment.environment,
child_build.deployment.environment,
grandchild_build.deployment.environment
]
expect(subject).to match_array(expected_environments)
end
it 'does not return parent environment' do
expect(subject).not_to include(parent_build.deployment.environment)
end
it 'does not return sibling environment' do
expect(subject).not_to include(sibling_build.deployment.environment)
end
end
context 'when each pipeline has multiple environments' do
let_it_be(:pipeline) { create(:ci_pipeline, :created) }
let_it_be(:build1) { create(:ci_build, :with_deployment, :deploy_to_production, pipeline: pipeline) }
let_it_be(:build2) { create(:ci_build, :with_deployment, environment: 'staging', pipeline: pipeline) }
let_it_be(:child) { create(:ci_pipeline, child_of: pipeline) }
let_it_be(:child_build1) { create(:ci_build, :with_deployment, environment: 'canary', pipeline: child) }
let_it_be(:child_build2) { create(:ci_build, :with_deployment, environment: 'test', pipeline: child) }
it 'returns all related environments' do
expected_environments = [
build1.deployment.environment,
build2.deployment.environment,
child_build1.deployment.environment,
child_build2.deployment.environment
]
expect(subject).to match_array(expected_environments)
end
end
context 'when pipeline has no environment' do
let_it_be(:pipeline) { create(:ci_pipeline, :created) }
it 'returns empty' do
expect(subject).to be_empty
end
end
end
describe '#root_ancestor' do
subject { pipeline.root_ancestor }
......
......@@ -245,6 +245,17 @@ RSpec.describe EnvironmentStatus do
end
end
context 'when there is a deployment in a child pipeline' do
let!(:child_pipeline) { create(:ci_pipeline, child_of: pipeline) }
let!(:child_build) { create(:ci_build, :with_deployment, :start_review_app, pipeline: child_pipeline) }
let(:child_environment) { child_build.deployment.environment }
it 'returns both parent and child entries' do
expect(subject.count).to eq(2)
expect(subject.map(&:id)).to contain_exactly(environment.id, child_environment.id)
end
end
context 'when environment is stopped' do
before do
environment.stop!
......
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