diff --git a/app/helpers/environment_helper.rb b/app/helpers/environment_helper.rb index 1e2a8c7ddbd..ea34bce9367 100644 --- a/app/helpers/environment_helper.rb +++ b/app/helpers/environment_helper.rb @@ -2,20 +2,28 @@ module EnvironmentHelper def environment_for_build(project, build) return unless build.environment - environment_name = ExpandVariables.expand(build.environment, build.variables) - project.environments.find_by(name: environment_name) + project.environments.find_by(name: build.expanded_environment_name) end def environment_link_for_build(project, build) environment = environment_for_build(project, build) - return unless environment - - link_to environment.name, namespace_project_environment_path(project.namespace, project, environment) + if environment + link_to environment.name, namespace_project_environment_path(project.namespace, project, environment) + else + content_tag :span, build.expanded_environment_name + end end - def deployment_link(project, deployment) + def deployment_link(deployment) return unless deployment link_to "##{deployment.id}", [deployment.project.namespace.becomes(Namespace), deployment.project, deployment.deployable] end + + def last_deployment_link_for_environment_build(project, build) + environment = environment_for_build(project, build) + return unless environment + + deployment_link(environment.last_deployment) + end end diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 09bbea1c653..e0e7a8caeea 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -127,8 +127,24 @@ module Ci !self.pipeline.statuses.latest.include?(self) end - def deployable? - self.environment.present? + def expanded_environment_name + ExpandVariables.expand(environment, variables) if environment + end + + def starts_environment? + self.environment.present? && self.environment_action == 'start' + end + + def stops_environment? + self.environment.present? && self.environment_action == 'stop' + end + + def environment_action + self.options.fetch(:environment, {}).fetch(:action, 'start') + end + + def outdated_deployment? + success? && !last_deployment.try(:last?) end def last_deployment diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index 488688a7d59..d799671058d 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -26,26 +26,29 @@ = link_to namespace_project_runners_path(@build.project.namespace, @build.project) do Runners page - - if @build.deployable? + - if @build.environment.present? && @build.starts_environment? .prepend-top-default .environment-information - - if @build.status == 'success' && (!@build.last_deployment.try(:last?)) + - if @build.outdated_deployment? = ci_icon_for_status('success_with_warnings') - else = ci_icon_for_status(@build.status) - - last_deployment = @build.last_deployment - - if @build.complete? - - if @build.success? - - if last_deployment.try(:last?) - This build is the most recent deployment to #{environment_link_for_build(@build.project, @build)}. - - else - This build is an out-of-date deployment to #{environment_link_for_build(@build.project, @build)}. View the most recent deployment #{deployment_link(@project, last_deployment)}. + - environment = environment_for_build(@build.project, @build) + - if @build.success? && @build.last_deployment.present? + - if @build.last_deployment.last? + This build is the most recent deployment to #{environment_link_for_build(@build.project, @build)}. - else - The deployment of this build to #{environment_link_for_build(@build.project, @build)} did not complete. + This build is an out-of-date deployment to #{environment_link_for_build(@build.project, @build)}. + - if environment.last_deployment + View the most recent deployment #{deployment_link(environment.last_deployment)}. + - elsif @build.complete? && !@build.success? + The deployment of this build to #{environment_link_for_build(@build.project, @build)} did not complete. - else - This build is creating a deployment to #{environment_link_for_build(@build.project, @build)} and will overwrite the | - = link_to "latest deployment.", deployment_link(@project, last_deployment) | + This build is creating a deployment to #{environment_link_for_build(@build.project, @build)} + - if environment.last_deployment + and will overwrite the + = link_to 'latest deployment', deployment_link(environment.last_deployment) .prepend-top-default - if @build.erased? diff --git a/app/workers/build_success_worker.rb b/app/workers/build_success_worker.rb index 1bc9745ecbc..450ba871c4c 100644 --- a/app/workers/build_success_worker.rb +++ b/app/workers/build_success_worker.rb @@ -4,7 +4,7 @@ class BuildSuccessWorker def perform(build_id) Ci::Build.find_by(id: build_id).try do |build| - create_deployment(build) if build.deployable? + create_deployment(build) if build.environment.present? end end diff --git a/spec/models/build_spec.rb b/spec/models/build_spec.rb index ae185de9ca3..731a2274d9e 100644 --- a/spec/models/build_spec.rb +++ b/spec/models/build_spec.rb @@ -1052,4 +1052,100 @@ describe Ci::Build, models: true do end end end + + describe '#starts_environment?' do + subject { build.starts_environment? } + + context 'when environment is defined' do + before do + build.update(environment: 'review') + end + + it { is_expected.to be_truthy } + end + + context 'when environment is not defined' do + before do + build.update(environment: nil) + end + + it { is_expected.to be_falsey } + end + end + + describe '#stops_environment?' do + subject { build.stops_environment? } + + context 'when environment is defined' do + before do + build.update(environment: 'review') + end + + context 'no action is defined' do + it { is_expected.to be_falsey } + end + + context 'and stop action is defined' do + before do + build.update(options: { environment: { action: 'stop' } } ) + end + + it { is_expected.to be_truthy } + end + end + + context 'when environment is not defined' do + before do + build.update(environment: nil) + end + + it { is_expected.to be_falsey } + end + end + + describe '#last_deployment' do + subject { build.last_deployment } + + context 'when multiple deployments is created returns latest one' do + let!(:deployment1) { create(:deployment, deployable: build) } + let!(:deployment2) { create(:deployment, deployable: build) } + + it { is_expected.to eq(deployment2) } + end + end + + describe '#outdated_deployment?' do + subject { build.outdated_deployment? } + + context 'when build succeeded' do + let(:build) { create(:ci_build, :success) } + let!(:deployment) { create(:deployment, deployable: build) } + + context 'current deployment is latest' do + it { is_expected.to be_falsey } + end + + context 'current deployment is not latest on environment' do + let!(:deployment2) { create(:deployment, environment: deployment.environment) } + + it { is_expected.to be_truthy } + end + end + + context 'when build failed' do + let(:build) { create(:ci_build, :failed) } + + it { is_expected.to be_falsey } + end + end + + describe '#expanded_environment_name' do + subject { build.expanded_environment_name } + + context 'when environment uses variables' do + let(:build) { create(:ci_build, ref: 'master', environment: 'review/$CI_BUILD_REF_NAME') } + + it { is_expected.to eq('review/master') } + end + end end diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index a37a00f461a..2efe69d7adc 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -4,6 +4,14 @@ describe Ci::Build, models: true do let(:build) { create(:ci_build) } let(:test_trace) { 'This is a test' } + describe 'ss' do + it { is_expected.to belong_to(:runner) } + it { is_expected.to belong_to(:trigger_request) } + it { is_expected.to belong_to(:erased_by) } + + it { is_expected.to have_many(:deployments) } + end + describe '#trace' do it 'obfuscates project runners token' do allow(build).to receive(:raw_trace).and_return("Test: #{build.project.runners_token}") diff --git a/spec/views/projects/builds/show.html.haml_spec.rb b/spec/views/projects/builds/show.html.haml_spec.rb index fa4d66bb6cb..3b9a9c95daa 100644 --- a/spec/views/projects/builds/show.html.haml_spec.rb +++ b/spec/views/projects/builds/show.html.haml_spec.rb @@ -54,7 +54,7 @@ describe 'projects/builds/show', :view do it 'shows deployment message' do expected_text = 'This build is an out-of-date deployment ' \ - "to staging. View the most recent deployment ##{first_deployment.id}" + "to staging.\nView the most recent deployment ##{second_deployment.id}." render expect(rendered).to have_css('.environment-information', text: expected_text)