Class: Deployments::LinkMergeRequestsService

Inherits:
Object
  • Object
show all
Defined in:
app/services/deployments/link_merge_requests_service.rb

Overview

Service class for linking merge requests to deployments.

Constant Summary collapse

COMMITS_PER_QUERY =

The number of commits per query for which to find merge requests.

5_000

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(deployment) ⇒ LinkMergeRequestsService

Returns a new instance of LinkMergeRequestsService.


11
12
13
# File 'app/services/deployments/link_merge_requests_service.rb', line 11

def initialize(deployment)
  @deployment = deployment
end

Instance Attribute Details

#deploymentObject (readonly)

Returns the value of attribute deployment


6
7
8
# File 'app/services/deployments/link_merge_requests_service.rb', line 6

def deployment
  @deployment
end

Instance Method Details

#executeObject


15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'app/services/deployments/link_merge_requests_service.rb', line 15

def execute
  # Review apps have the environment type set (e.g. to `review`, though the
  # exact value may differ). We don't want to link merge requests to review
  # app deployments, as this is not useful.
  return if deployment.environment.environment_type

  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

61
62
63
64
65
66
# File 'app/services/deployments/link_merge_requests_service.rb', line 61

def link_all_merged_merge_requests
  merge_requests =
    project.merge_requests.merged.by_target_branch(deployment.ref)

  deployment.link_merge_requests(merge_requests)
end

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'app/services/deployments/link_merge_requests_service.rb', line 35

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)

    picked_merge_requests =
      project.merge_requests.by_cherry_pick_sha(slice)

    deployment.link_merge_requests(picked_merge_requests)
  end
end