Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-11-07 03:06:18 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2019-11-07 03:06:18 +0300
commitee6b185429b62857a5e490526095a7699e8539f3 (patch)
treede54f53b76c5da2bf05cbd333e1910bbe655d653 /app/services/deployments
parentcf85de264d049f1f8ff14b23f38f8331ae4c60fa (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/services/deployments')
-rw-r--r--app/services/deployments/after_create_service.rb9
-rw-r--r--app/services/deployments/link_merge_requests_service.rb66
-rw-r--r--app/services/deployments/update_service.rb17
3 files changed, 91 insertions, 1 deletions
diff --git a/app/services/deployments/after_create_service.rb b/app/services/deployments/after_create_service.rb
index 2572802e6a1..e0a4e5419cc 100644
--- a/app/services/deployments/after_create_service.rb
+++ b/app/services/deployments/after_create_service.rb
@@ -33,12 +33,21 @@ module Deployments
if environment.save && !environment.stopped?
deployment.update_merge_request_metrics!
+ link_merge_requests(deployment)
end
end
end
private
+ def link_merge_requests(deployment)
+ unless Feature.enabled?(:deployment_merge_requests, deployment.project)
+ return
+ end
+
+ LinkMergeRequestsService.new(deployment).execute
+ end
+
def environment_options
options&.dig(:environment) || {}
end
diff --git a/app/services/deployments/link_merge_requests_service.rb b/app/services/deployments/link_merge_requests_service.rb
new file mode 100644
index 00000000000..71186659290
--- /dev/null
+++ b/app/services/deployments/link_merge_requests_service.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+module Deployments
+ # Service class for linking merge requests to deployments.
+ class LinkMergeRequestsService
+ attr_reader :deployment
+
+ # The number of commits per query for which to find merge requests.
+ COMMITS_PER_QUERY = 5_000
+
+ def initialize(deployment)
+ @deployment = deployment
+ end
+
+ def execute
+ return unless deployment.success?
+
+ if (prev = deployment.previous_environment_deployment)
+ link_merge_requests_for_range(prev.sha, deployment.sha)
+ else
+ # When no previous deployment is found we fall back to linking all merge
+ # requests merged into the deployed branch. This will not always be
+ # accurate, but it's better than having no data.
+ #
+ # We can't use the first commit in the repository as a base to compare
+ # to, as this will not scale to large repositories. For example, GitLab
+ # itself has over 150 000 commits.
+ link_all_merged_merge_requests
+ end
+ end
+
+ def link_merge_requests_for_range(from, to)
+ commits = project
+ .repository
+ .commits_between(from, to)
+ .map(&:id)
+
+ # For some projects the list of commits to deploy may be very large. To
+ # ensure we do not end up running SQL queries with thousands of WHERE IN
+ # values, we run one query per a certain number of commits.
+ #
+ # In most cases this translates to only a single query. For very large
+ # deployment we may end up running a handful of queries to get and insert
+ # the data.
+ commits.each_slice(COMMITS_PER_QUERY) do |slice|
+ merge_requests =
+ project.merge_requests.merged.by_merge_commit_sha(slice)
+
+ deployment.link_merge_requests(merge_requests)
+ end
+ end
+
+ def link_all_merged_merge_requests
+ merge_requests =
+ project.merge_requests.merged.by_target_branch(deployment.ref)
+
+ deployment.link_merge_requests(merge_requests)
+ end
+
+ private
+
+ def project
+ deployment.project
+ end
+ end
+end
diff --git a/app/services/deployments/update_service.rb b/app/services/deployments/update_service.rb
index 7c8215d28f2..97b233f16a7 100644
--- a/app/services/deployments/update_service.rb
+++ b/app/services/deployments/update_service.rb
@@ -10,7 +10,22 @@ module Deployments
end
def execute
- deployment.update(status: params[:status])
+ # A regular update() does not trigger the state machine transitions, which
+ # we need to ensure merge requests are linked when changing the status to
+ # success. To work around this we use this case statment, using the right
+ # event methods to trigger the transition hooks.
+ case params[:status]
+ when 'running'
+ deployment.run
+ when 'success'
+ deployment.succeed
+ when 'failed'
+ deployment.drop
+ when 'canceled'
+ deployment.cancel
+ else
+ false
+ end
end
end
end