diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-07 03:06:18 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-07 03:06:18 +0300 |
commit | ee6b185429b62857a5e490526095a7699e8539f3 (patch) | |
tree | de54f53b76c5da2bf05cbd333e1910bbe655d653 /app/services/deployments | |
parent | cf85de264d049f1f8ff14b23f38f8331ae4c60fa (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/services/deployments')
-rw-r--r-- | app/services/deployments/after_create_service.rb | 9 | ||||
-rw-r--r-- | app/services/deployments/link_merge_requests_service.rb | 66 | ||||
-rw-r--r-- | app/services/deployments/update_service.rb | 17 |
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 |