From 9fe1b32f9773fc6bd041e80be290f3bd1ce1bfb8 Mon Sep 17 00:00:00 2001 From: Allen Cook <acook@gitlab.com> Date: Fri, 20 May 2022 14:48:16 +0000 Subject: [PATCH] Resolve "Environments View - Deploy button tied to wrong job" --- app/models/ci/build.rb | 8 ++++ app/models/deployment.rb | 20 ++++++++- app/models/environment.rb | 6 +-- app/serializers/environment_serializer.rb | 4 +- .../deployment_environment_manual_actions.yml | 8 ++++ .../environments/environments_spec.rb | 2 +- .../user_sees_deployment_widget_spec.rb | 5 ++- .../projects/environments/environment_spec.rb | 5 ++- spec/lib/gitlab/slash_commands/deploy_spec.rb | 2 +- spec/models/deployment_spec.rb | 44 ++++++++++++++----- spec/serializers/deployment_entity_spec.rb | 12 +++-- .../environment_serializer_spec.rb | 7 ++- 12 files changed, 94 insertions(+), 29 deletions(-) create mode 100644 config/feature_flags/development/deployment_environment_manual_actions.yml diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index fd264b71b9251..261230189474e 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -425,10 +425,18 @@ def other_manual_actions pipeline.manual_actions.reject { |action| action.name == self.name } end + def environment_manual_actions + pipeline.manual_actions.filter { |action| action.expanded_environment_name == self.expanded_environment_name } + end + def other_scheduled_actions pipeline.scheduled_actions.reject { |action| action.name == self.name } end + def environment_scheduled_actions + pipeline.scheduled_actions.filter { |action| action.expanded_environment_name == self.expanded_environment_name } + end + def pages_generator? Gitlab.config.pages.enabled && self.name == 'pages' diff --git a/app/models/deployment.rb b/app/models/deployment.rb index 3a96f4e386771..863e8bcfaa8e4 100644 --- a/app/models/deployment.rb +++ b/app/models/deployment.rb @@ -256,11 +256,27 @@ def invalidate_cache end def manual_actions - @manual_actions ||= deployable.try(:other_manual_actions) + Feature.enabled?(:deployment_environment_manual_actions) ? environment_manual_actions : other_manual_actions + end + + def other_manual_actions + @other_manual_actions ||= deployable.try(:other_manual_actions) + end + + def environment_manual_actions + @environment_manual_actions ||= deployable.try(:environment_manual_actions) end def scheduled_actions - @scheduled_actions ||= deployable.try(:other_scheduled_actions) + Feature.enabled?(:deployment_environment_manual_actions) ? environment_scheduled_actions : other_scheduled_actions + end + + def environment_scheduled_actions + @environment_scheduled_actions ||= deployable.try(:environment_scheduled_actions) + end + + def other_scheduled_actions + @other_scheduled_actions ||= deployable.try(:other_scheduled_actions) end def playable_build diff --git a/app/models/environment.rb b/app/models/environment.rb index 865f5c68af172..919998abaf229 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -59,7 +59,7 @@ class Environment < ApplicationRecord allow_nil: true, addressable_url: true - delegate :manual_actions, to: :last_deployment, allow_nil: true + delegate :manual_actions, :other_manual_actions, to: :last_deployment, allow_nil: true delegate :auto_rollback_enabled?, to: :project scope :available, -> { with_state(:available) } @@ -325,9 +325,9 @@ def reset_auto_stop end def actions_for(environment) - return [] unless manual_actions + return [] unless other_manual_actions - manual_actions.select do |action| + other_manual_actions.select do |action| action.expanded_environment_name == environment end end diff --git a/app/serializers/environment_serializer.rb b/app/serializers/environment_serializer.rb index b13140efea730..3cb60a59f513b 100644 --- a/app/serializers/environment_serializer.rb +++ b/app/serializers/environment_serializer.rb @@ -89,8 +89,8 @@ def deployment_associations user: [], metadata: [], pipeline: { - manual_actions: [], - scheduled_actions: [] + manual_actions: [:metadata], + scheduled_actions: [:metadata] }, project: project_associations } diff --git a/config/feature_flags/development/deployment_environment_manual_actions.yml b/config/feature_flags/development/deployment_environment_manual_actions.yml new file mode 100644 index 0000000000000..47ab1b257f984 --- /dev/null +++ b/config/feature_flags/development/deployment_environment_manual_actions.yml @@ -0,0 +1,8 @@ +--- +name: deployment_environment_manual_actions +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87138 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/362824 +milestone: '15.1' +type: development +group: group::release +default_enabled: false diff --git a/ee/spec/features/projects/environments/environments_spec.rb b/ee/spec/features/projects/environments/environments_spec.rb index 2296a645fa81a..5e267bae09035 100644 --- a/ee/spec/features/projects/environments/environments_spec.rb +++ b/ee/spec/features/projects/environments/environments_spec.rb @@ -33,7 +33,7 @@ def actions_button_selector context 'when environment has manual actions' do let!(:pipeline) { create(:ci_pipeline, project: project) } - let!(:build) { create(:ci_build, pipeline: pipeline) } + let!(:build) { create(:ci_build, pipeline: pipeline, environment: 'production') } let!(:deployment) do create(:deployment, diff --git a/spec/features/merge_request/user_sees_deployment_widget_spec.rb b/spec/features/merge_request/user_sees_deployment_widget_spec.rb index 01cc58777ba75..9f1f0d97b0954 100644 --- a/spec/features/merge_request/user_sees_deployment_widget_spec.rb +++ b/spec/features/merge_request/user_sees_deployment_widget_spec.rb @@ -109,7 +109,10 @@ end context 'with stop action' do - let(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') } + let(:manual) do + create(:ci_build, :manual, pipeline: pipeline, + name: 'close_app', environment: environment.name) + end before do stub_feature_flags(bootstrap_confirmation_modals: false) diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb index bfd54b9c6daea..124fc1e20866d 100644 --- a/spec/features/projects/environments/environment_spec.rb +++ b/spec/features/projects/environments/environment_spec.rb @@ -157,7 +157,7 @@ def auto_stop_button_selector context 'with related deployable present' do let(:pipeline) { create(:ci_pipeline, project: project) } - let(:build) { create(:ci_build, pipeline: pipeline) } + let(:build) { create(:ci_build, pipeline: pipeline, environment: environment.name) } let(:deployment) do create(:deployment, :success, environment: environment, deployable: build) @@ -263,7 +263,8 @@ def auto_stop_button_selector context 'with stop action' do let(:action) do create(:ci_build, :manual, pipeline: pipeline, - name: 'close_app') + name: 'close_app', + environment: environment.name) end let(:deployment) do diff --git a/spec/lib/gitlab/slash_commands/deploy_spec.rb b/spec/lib/gitlab/slash_commands/deploy_spec.rb index 71fca1e1fc80b..5167523ff58e4 100644 --- a/spec/lib/gitlab/slash_commands/deploy_spec.rb +++ b/spec/lib/gitlab/slash_commands/deploy_spec.rb @@ -32,7 +32,7 @@ context 'with environment' do let!(:staging) { create(:environment, name: 'staging', project: project) } let!(:pipeline) { create(:ci_pipeline, project: project) } - let!(:build) { create(:ci_build, pipeline: pipeline) } + let!(:build) { create(:ci_build, pipeline: pipeline, environment: 'production') } let!(:deployment) { create(:deployment, :success, environment: staging, deployable: build) } context 'without actions' do diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb index 8096604b96585..ce6b59a5f957a 100644 --- a/spec/models/deployment_spec.rb +++ b/spec/models/deployment_spec.rb @@ -17,7 +17,6 @@ it { is_expected.to delegate_method(:name).to(:environment).with_prefix } it { is_expected.to delegate_method(:commit).to(:project) } it { is_expected.to delegate_method(:commit_title).to(:commit).as(:try) } - it { is_expected.to delegate_method(:manual_actions).to(:deployable).as(:try) } it { is_expected.to delegate_method(:kubernetes_namespace).to(:deployment_cluster).as(:kubernetes_namespace) } it { is_expected.to validate_presence_of(:ref) } @@ -25,20 +24,43 @@ it_behaves_like 'having unique enum values' + describe '#manual_actions' do + let(:deployment) { create(:deployment) } + + it 'delegates to environment_manual_actions when deployment_environment_manual_actions ff is enabled' do + stub_feature_flags(deployment_environment_manual_actions: true) + + expect(deployment.deployable).to receive(:environment_manual_actions).and_call_original + + deployment.manual_actions + end + + it 'delegates to other_manual_actions when deployment_environment_manual_actions ff is disabled' do + stub_feature_flags(deployment_environment_manual_actions: false) + + expect(deployment.deployable).to receive(:other_manual_actions).and_call_original + + deployment.manual_actions + end + end + describe '#scheduled_actions' do - subject { deployment.scheduled_actions } + let(:deployment) { create(:deployment) } - let(:project) { create(:project, :repository) } - let(:pipeline) { create(:ci_pipeline, project: project) } - let(:build) { create(:ci_build, :success, pipeline: pipeline) } - let(:deployment) { create(:deployment, deployable: build) } + it 'delegates to environment_scheduled_actions when deployment_environment_manual_actions ff is enabled' do + stub_feature_flags(deployment_environment_manual_actions: true) - it 'delegates to other_scheduled_actions' do - expect_next_instance_of(Ci::Build) do |instance| - expect(instance).to receive(:other_scheduled_actions) - end + expect(deployment.deployable).to receive(:environment_scheduled_actions).and_call_original - subject + deployment.scheduled_actions + end + + it 'delegates to other_scheduled_actions when deployment_environment_manual_actions ff is disabled' do + stub_feature_flags(deployment_environment_manual_actions: false) + + expect(deployment.deployable).to receive(:other_scheduled_actions).and_call_original + + deployment.scheduled_actions end end diff --git a/spec/serializers/deployment_entity_spec.rb b/spec/serializers/deployment_entity_spec.rb index 500d5718bf195..4452ccbcf07f3 100644 --- a/spec/serializers/deployment_entity_spec.rb +++ b/spec/serializers/deployment_entity_spec.rb @@ -60,12 +60,16 @@ end context 'when the pipeline has another manual action' do - let(:other_build) { create(:ci_build, :manual, name: 'another deploy', pipeline: pipeline) } - let!(:other_deployment) { create(:deployment, deployable: other_build) } + let!(:other_build) do + create(:ci_build, :manual, name: 'another deploy', + pipeline: pipeline, environment: build.environment) + end + + let!(:other_deployment) { create(:deployment, deployable: build) } it 'returns another manual action' do - expect(subject[:manual_actions].count).to eq(1) - expect(subject[:manual_actions].first[:name]).to eq('another deploy') + expect(subject[:manual_actions].count).to eq(2) + expect(subject[:manual_actions].second[:name]).to eq('another deploy') end context 'when user is a reporter' do diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb index fe6278084f93c..47d2c8b379479 100644 --- a/spec/serializers/environment_serializer_spec.rb +++ b/spec/serializers/environment_serializer_spec.rb @@ -227,8 +227,11 @@ def create_environment_with_associations(project) create(:environment, project: project).tap do |environment| - create(:deployment, :success, environment: environment, project: project) - create(:deployment, :running, environment: environment, project: project) + pipeline = create(:ci_pipeline, project: project) + manual_build = create(:ci_build, :manual, project: project, pipeline: pipeline, environment: environment.name) + scheduled_build = create(:ci_build, :scheduled, project: project, pipeline: pipeline, environment: environment.name) + create(:deployment, :success, environment: environment, project: project, deployable: manual_build) + create(:deployment, :running, environment: environment, project: project, deployable: scheduled_build) end end end -- GitLab