summaryrefslogtreecommitdiff
path: root/app/presenters/ci/build_runner_presenter.rb
blob: ffa33dc9f15522fd6838746742204c4a9a12ae98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# frozen_string_literal: true

module Ci
  class BuildRunnerPresenter < SimpleDelegator
    include Gitlab::Utils::StrongMemoize

    RUNNER_REMOTE_TAG_PREFIX = 'refs/tags/'
    RUNNER_REMOTE_BRANCH_PREFIX = 'refs/remotes/origin/'

    def artifacts
      return unless options[:artifacts]

      list = []
      list << create_archive(options[:artifacts])
      list << create_reports(options[:artifacts][:reports], expire_in: options[:artifacts][:expire_in])
      list.flatten.compact
    end

    def ref_type
      if tag
        'tag'
      else
        'branch'
      end
    end

    def git_depth
      if git_depth_variable
        git_depth_variable[:value]
      else
        project.ci_default_git_depth
      end.to_i
    end

    def refspecs
      specs = []
      specs << refspec_for_persistent_ref if persistent_ref_exist?

      if git_depth > 0
        specs << refspec_for_branch(ref) if branch? || legacy_detached_merge_request_pipeline?
        specs << refspec_for_tag(ref) if tag?
      else
        specs << refspec_for_branch
        specs << refspec_for_tag
      end

      specs
    end

    private

    def create_archive(artifacts)
      return unless artifacts[:untracked] || artifacts[:paths]

      archive = {
        artifact_type: :archive,
        artifact_format: :zip,
        name: artifacts[:name],
        untracked: artifacts[:untracked],
        paths: artifacts[:paths],
        when: artifacts[:when],
        expire_in: artifacts[:expire_in]
      }

      if artifacts.dig(:exclude).present? && ::Gitlab::Ci::Features.artifacts_exclude_enabled?
        archive.merge(exclude: artifacts[:exclude])
      else
        archive
      end
    end

    def create_reports(reports, expire_in:)
      return unless reports&.any?

      reports.map do |report_type, report_paths|
        {
          artifact_type: report_type.to_sym,
          artifact_format: ::Ci::JobArtifact::TYPE_AND_FORMAT_PAIRS.fetch(report_type.to_sym),
          name: ::Ci::JobArtifact::DEFAULT_FILE_NAMES.fetch(report_type.to_sym),
          paths: report_paths,
          when: 'always',
          expire_in: expire_in
        }
      end
    end

    def refspec_for_branch(ref = '*')
      "+#{Gitlab::Git::BRANCH_REF_PREFIX}#{ref}:#{RUNNER_REMOTE_BRANCH_PREFIX}#{ref}"
    end

    def refspec_for_tag(ref = '*')
      "+#{Gitlab::Git::TAG_REF_PREFIX}#{ref}:#{RUNNER_REMOTE_TAG_PREFIX}#{ref}"
    end

    def refspec_for_persistent_ref
      #
      # End-to-end test coverage for CI fetching seems to not be strong, so we
      # are using a feature flag here to close the confidence gap. My (JV)
      # confidence about the change is very high but if something is wrong
      # with it after all, this would cause all CI jobs on gitlab.com to fail.
      #
      # The roll-out will be tracked in
      # https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/746.
      #
      if Feature.enabled?(:scalability_ci_fetch_sha, type: :ops)
        # Use persistent_ref.sha because it causes 'git fetch' to do less work.
        # See https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/746.
        "+#{pipeline.persistent_ref.sha}:#{pipeline.persistent_ref.path}"
      else
        "+#{pipeline.persistent_ref.path}:#{pipeline.persistent_ref.path}"
      end
    end

    def persistent_ref_exist?
      ##
      # Persistent refs for pipelines definitely exist from GitLab 12.4,
      # hence, we don't need to check the ref existence before passing it to runners.
      # Checking refs pressurizes gitaly node and should be avoided.
      # Issue: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/2143
      return true if Feature.enabled?(:ci_skip_persistent_ref_existence_check)

      pipeline.persistent_ref.exist?
    end

    def git_depth_variable
      strong_memoize(:git_depth_variable) do
        variables&.find { |variable| variable[:key] == 'GIT_DEPTH' }
      end
    end
  end
end

Ci::BuildRunnerPresenter.prepend_if_ee('EE::Ci::BuildRunnerPresenter')