summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorAlessio Caiazza <acaiazza@gitlab.com>2018-10-29 11:34:41 +0000
committerNick Thomas <nick@gitlab.com>2018-10-29 11:34:41 +0000
commitdadc046d3a5c797294330bcd26acdadac069c9cc (patch)
tree3468d1ca9b320315f3d4d5e5e032e6d547cc2550 /app
parent289651e26f5b18cc68dcdd052939cd878ca66092 (diff)
downloadgitlab-ce-dadc046d3a5c797294330bcd26acdadac069c9cc.tar.gz
post merge pipeline and environments status
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment.vue15
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue95
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js2
-rw-r--r--app/controllers/projects/merge_requests_controller.rb12
-rw-r--r--app/models/deployment.rb4
-rw-r--r--app/models/environment_status.rb41
-rw-r--r--app/models/merge_request.rb6
-rw-r--r--app/serializers/environment_status_entity.rb1
-rw-r--r--app/serializers/merge_request_widget_entity.rb1
10 files changed, 151 insertions, 34 deletions
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
index 6c87287a4c4..5e7a35e9396 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
@@ -2,6 +2,7 @@
import Icon from '~/vue_shared/components/icon.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import FilteredSearchDropdown from '~/vue_shared/components/filtered_search_dropdown.vue';
+import { __ } from '~/locale';
import timeagoMixin from '../../vue_shared/mixins/timeago';
import tooltip from '../../vue_shared/directives/tooltip';
import LoadingButton from '../../vue_shared/components/loading_button.vue';
@@ -31,6 +32,11 @@ export default {
required: true,
},
},
+ deployedTextMap: {
+ running: __('Deploying to'),
+ success: __('Deployed to'),
+ failed: __('Failed to deploy to'),
+ },
data() {
const features = window.gon.features || {};
return {
@@ -54,10 +60,13 @@ export default {
hasMetrics() {
return !!this.deployment.metrics_url;
},
+ deployedText() {
+ return this.$options.deployedTextMap[this.deployment.status];
+ },
},
methods: {
stopEnvironment() {
- const msg = 'Are you sure you want to stop this environment?';
+ const msg = __('Are you sure you want to stop this environment?');
const isConfirmed = confirm(msg); // eslint-disable-line
if (isConfirmed) {
@@ -87,10 +96,10 @@ export default {
<div class="ci-widget media">
<div class="media-body">
<div class="deploy-body">
- <div class="deployment-info">
+ <div class="js-deployment-info deployment-info">
<template v-if="hasDeploymentMeta">
<span>
- Deployed to
+ {{ deployedText }}
</span>
<tooltip-on-truncate
:title="deployment.name"
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index 5d9f7cebcf2..a5c69d2bc7a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -1,4 +1,6 @@
<script>
+import _ from 'underscore';
+import { __ } from '~/locale';
import Project from '~/pages/projects/project';
import SmartInterval from '~/smart_interval';
import createFlash from '../flash';
@@ -80,6 +82,7 @@ export default {
const service = this.createService(store);
return {
mr: store,
+ state: store.state,
service,
};
},
@@ -103,6 +106,17 @@ export default {
(!this.mr.isNothingToMergeState && !this.mr.isMergedState)
);
},
+ shouldRenderMergedPipeline() {
+ return this.mr.state === 'merged' && !_.isEmpty(this.mr.mergePipeline);
+ },
+ },
+ watch: {
+ state(newVal, oldVal) {
+ if (newVal !== oldVal && this.shouldRenderMergedPipeline) {
+ // init polling
+ this.initPostMergeDeploymentsPolling();
+ }
+ }
},
created() {
this.initPolling();
@@ -112,11 +126,19 @@ export default {
mounted() {
this.setFaviconHelper();
this.initDeploymentsPolling();
+
+ if (this.shouldRenderMergedPipeline) {
+ this.initPostMergeDeploymentsPolling();
+ }
},
beforeDestroy() {
eventHub.$off('mr.discussion.updated', this.checkStatus);
this.pollingInterval.destroy();
this.deploymentsInterval.destroy();
+
+ if (this.postMergeDeploymentsInterval) {
+ this.postMergeDeploymentsInterval.destroy();
+ }
},
methods: {
createService(store) {
@@ -146,7 +168,13 @@ export default {
cb.call(null, data);
}
})
- .catch(() => createFlash('Something went wrong. Please try again.'));
+ .catch(() => createFlash(__('Something went wrong. Please try again.')));
+ },
+ setFaviconHelper() {
+ if (this.mr.ciStatusFaviconPath) {
+ return setFaviconOverlay(this.mr.ciStatusFaviconPath);
+ }
+ return Promise.resolve();
},
initPolling() {
this.pollingInterval = new SmartInterval({
@@ -158,8 +186,14 @@ export default {
});
},
initDeploymentsPolling() {
- this.deploymentsInterval = new SmartInterval({
- callback: this.fetchDeployments,
+ this.deploymentsInterval = this.deploymentsPoll(this.fetchPreMergeDeployments);
+ },
+ initPostMergeDeploymentsPolling() {
+ this.postMergeDeploymentsInterval = this.deploymentsPoll(this.fetchPostMergeDeployments);
+ },
+ deploymentsPoll(callback) {
+ return new SmartInterval({
+ callback,
startingInterval: 30000,
maxInterval: 120000,
hiddenInterval: 240000,
@@ -167,26 +201,29 @@ export default {
immediateExecution: true,
});
},
- setFaviconHelper() {
- if (this.mr.ciStatusFaviconPath) {
- return setFaviconOverlay(this.mr.ciStatusFaviconPath);
- }
- return Promise.resolve();
+ fetchDeployments(target) {
+ return this.service.fetchDeployments(target);
},
- fetchDeployments() {
- return this.service
- .fetchDeployments()
- .then(res => res.data)
- .then(data => {
+ fetchPreMergeDeployments() {
+ return this.fetchDeployments()
+ .then(({ data }) => {
if (data.length) {
this.mr.deployments = data;
}
})
- .catch(() => {
- createFlash(
- 'Something went wrong while fetching the environments for this merge request. Please try again.',
- );
- });
+ .catch(() => this.throwDeploymentsError());
+ },
+ fetchPostMergeDeployments(){
+ return this.fetchDeployments('merge_commit')
+ .then(({ data }) => {
+ if (data.length) {
+ this.mr.postMergeDeployments = data;
+ }
+ })
+ .catch(() => this.throwDeploymentsError());
+ },
+ throwDeploymentsError() {
+ createFlash(__('Something went wrong while fetching the environments for this merge request. Please try again.'));
},
fetchActionsContent() {
this.service
@@ -199,7 +236,7 @@ export default {
Project.initRefSwitcher();
}
})
- .catch(() => createFlash('Something went wrong. Please try again.'));
+ .catch(() => createFlash(__('Something went wrong. Please try again.')));
},
handleNotification(data) {
if (data.ci_status === this.mr.ciStatus) return;
@@ -267,7 +304,8 @@ export default {
/>
<deployment
v-for="deployment in mr.deployments"
- :key="deployment.id"
+ :key="`pre-merge-deploy-${deployment.id}`"
+ class="js-pre-merge-deploy"
:deployment="deployment"
/>
<div class="mr-section-container">
@@ -308,5 +346,22 @@ export default {
<mr-widget-merge-help />
</div>
</div>
+
+ <template v-if="shouldRenderMergedPipeline">
+ <mr-widget-pipeline
+ class="js-post-merge-pipeline prepend-top-default"
+ :pipeline="mr.mergePipeline"
+ :ci-status="mr.ciStatus"
+ :has-ci="mr.hasCI"
+ :source-branch="mr.targetBranch"
+ :source-branch-link="mr.targetBranch"
+ />
+ <deployment
+ v-for="postMergeDeployment in mr.postMergeDeployments"
+ :key="`post-merge-deploy-${postMergeDeployment.id}`"
+ :deployment="postMergeDeployment"
+ class="js-post-deployment"
+ />
+ </template>
</div>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js b/app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js
index fecbfec2214..bf5b85b2ae6 100644
--- a/app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js
+++ b/app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js
@@ -21,8 +21,12 @@ export default class MRWidgetService {
return axios.delete(this.endpoints.sourceBranchPath);
}
- fetchDeployments() {
- return axios.get(this.endpoints.ciEnvironmentsStatusPath);
+ fetchDeployments(targetParam) {
+ return axios.get(this.endpoints.ciEnvironmentsStatusPath, {
+ params: {
+ environment_target: targetParam
+ }
+ });
}
poll() {
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
index e6655914700..a0c008e7314 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
@@ -32,7 +32,9 @@ export default class MergeRequestStore {
this.commitsCount = data.commits_count;
this.divergedCommitsCount = data.diverged_commits_count;
this.pipeline = data.pipeline || {};
+ this.mergePipeline = data.merge_pipeline || {};
this.deployments = this.deployments || data.deployments || [];
+ this.postMergeDeployments = this.postMergeDeployments || [];
this.initRebase(data);
if (data.issues_links) {
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 757b03d0b0e..614722fd60d 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -201,9 +201,11 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
end
def ci_environments_status
- environments = @merge_request.environments_for(current_user).map do |environment|
- EnvironmentStatus.new(environment, @merge_request)
- end
+ environments = if ci_environments_status_on_merge_result?
+ EnvironmentStatus.after_merge_request(@merge_request, current_user)
+ else
+ EnvironmentStatus.for_merge_request(@merge_request, current_user)
+ end
render json: EnvironmentStatusSerializer.new(current_user: current_user).represent(environments)
end
@@ -241,6 +243,10 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
private
+ def ci_environments_status_on_merge_result?
+ params[:environment_target] == 'merge_commit'
+ end
+
def target_branch_missing?
@merge_request.has_no_commits? && !@merge_request.target_branch_exists?
end
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index 62dc0f2cbeb..ee5b96e7454 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -127,6 +127,10 @@ class Deployment < ActiveRecord::Base
metrics&.merge(deployment_time: created_at.to_i) || {}
end
+ def status
+ 'success'
+ end
+
private
def prometheus_adapter
diff --git a/app/models/environment_status.rb b/app/models/environment_status.rb
index 5ff3acc0e58..a84871f7253 100644
--- a/app/models/environment_status.rb
+++ b/app/models/environment_status.rb
@@ -3,21 +3,33 @@
class EnvironmentStatus
include Gitlab::Utils::StrongMemoize
- attr_reader :environment, :merge_request
+ attr_reader :environment, :merge_request, :sha
delegate :id, to: :environment
delegate :name, to: :environment
delegate :project, to: :environment
delegate :deployed_at, to: :deployment, allow_nil: true
+ delegate :status, to: :deployment
- def initialize(environment, merge_request)
+ def self.for_merge_request(mr, user)
+ build_environments_status(mr, user, mr.head_pipeline)
+ end
+
+ def self.after_merge_request(mr, user)
+ return [] unless mr.merged?
+
+ build_environments_status(mr, user, mr.merge_pipeline)
+ end
+
+ def initialize(environment, merge_request, sha)
@environment = environment
@merge_request = merge_request
+ @sha = sha
end
def deployment
strong_memoize(:deployment) do
- environment.first_deployment_for(merge_request.diff_head_sha)
+ environment.first_deployment_for(sha)
end
end
@@ -26,10 +38,9 @@ class EnvironmentStatus
end
def changes
- sha = merge_request.diff_head_sha
return [] if project.route_map_for(sha).nil?
- changed_files.map { |file| build_change(file, sha) }.compact
+ changed_files.map { |file| build_change(file) }.compact
end
def changed_files
@@ -41,7 +52,7 @@ class EnvironmentStatus
PAGE_EXTENSIONS = /\A\.(s?html?|php|asp|cgi|pl)\z/i.freeze
- def build_change(file, sha)
+ def build_change(file)
public_path = project.public_path_for_source_path(file.new_path, sha)
return if public_path.nil?
@@ -53,4 +64,22 @@ class EnvironmentStatus
external_url: environment.external_url_for(file.new_path, sha)
}
end
+
+ def self.build_environments_status(mr, user, pipeline)
+ return [] unless pipeline.present?
+
+ find_environments(user, pipeline).map do |environment|
+ EnvironmentStatus.new(environment, mr, pipeline.sha)
+ end
+ end
+ private_class_method :build_environments_status
+
+ def self.find_environments(user, pipeline)
+ env_ids = Deployment.where(deployable: pipeline.builds).select(:environment_id)
+
+ Environment.available.where(id: env_ids).select do |environment|
+ Ability.allowed?(user, :read_environment, environment)
+ end
+ end
+ private_class_method :find_environments
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 6559f94a696..7eef08aa6a3 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -204,6 +204,12 @@ class MergeRequest < ActiveRecord::Base
head_pipeline&.sha == diff_head_sha ? head_pipeline : nil
end
+ def merge_pipeline
+ return unless merged?
+
+ target_project.pipeline_for(target_branch, merge_commit_sha)
+ end
+
# Pattern used to extract `!123` merge request references from text
#
# This pattern supports cross-project references.
diff --git a/app/serializers/environment_status_entity.rb b/app/serializers/environment_status_entity.rb
index 3dfa4f204c9..f87cc894d2f 100644
--- a/app/serializers/environment_status_entity.rb
+++ b/app/serializers/environment_status_entity.rb
@@ -5,6 +5,7 @@ class EnvironmentStatusEntity < Grape::Entity
expose :id
expose :name
+ expose :status
expose :url do |es|
project_environment_path(es.project, es.environment)
diff --git a/app/serializers/merge_request_widget_entity.rb b/app/serializers/merge_request_widget_entity.rb
index 9ec24f799ef..f33a1654d5e 100644
--- a/app/serializers/merge_request_widget_entity.rb
+++ b/app/serializers/merge_request_widget_entity.rb
@@ -55,6 +55,7 @@ class MergeRequestWidgetEntity < IssuableEntity
expose :merge_commit_message
expose :actual_head_pipeline, with: PipelineDetailsEntity, as: :pipeline
+ expose :merge_pipeline, with: PipelineDetailsEntity, if: ->(mr, _) { mr.merged? && can?(request.current_user, :read_pipeline, mr.target_project)}
# Booleans
expose :merge_ongoing?, as: :merge_ongoing