Class: Gitlab::Ci::Config::External::File::Base

Inherits:
Object
  • Object
show all
Includes:
Utils::StrongMemoize
Defined in:
lib/gitlab/ci/config/external/file/base.rb

Direct Known Subclasses

Artifact, Component, Local, Project, Remote, Template

Constant Summary collapse

YAML_ALLOWLIST_EXTENSION =
/.+\.(yml|yaml)$/i

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(params, context) ⇒ Base

Returns a new instance of Base.



15
16
17
18
19
20
# File 'lib/gitlab/ci/config/external/file/base.rb', line 15

def initialize(params, context)
  @params = params
  @context = context
  @errors = []
  @inputs_only = false
end

Instance Attribute Details

#contextObject (readonly)

Returns the value of attribute context.



11
12
13
# File 'lib/gitlab/ci/config/external/file/base.rb', line 11

def context
  @context
end

#errorsObject (readonly)

Returns the value of attribute errors.



11
12
13
# File 'lib/gitlab/ci/config/external/file/base.rb', line 11

def errors
  @errors
end

#locationObject (readonly)

Returns the value of attribute location.



11
12
13
# File 'lib/gitlab/ci/config/external/file/base.rb', line 11

def location
  @location
end

#paramsObject (readonly)

Returns the value of attribute params.



11
12
13
# File 'lib/gitlab/ci/config/external/file/base.rb', line 11

def params
  @params
end

Instance Method Details

#contentObject

Raises:

  • (NotImplementedError)


51
52
53
# File 'lib/gitlab/ci/config/external/file/base.rb', line 51

def content
  raise NotImplementedError, 'subclass must implement fetching raw content'
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


66
67
68
# File 'lib/gitlab/ci/config/external/file/base.rb', line 66

def eql?(other)
  other.hash == hash
end

#error_messageObject



47
48
49
# File 'lib/gitlab/ci/config/external/file/base.rb', line 47

def error_message
  errors.first
end

#hashObject



70
71
72
# File 'lib/gitlab/ci/config/external/file/base.rb', line 70

def hash
  [params, context.project&.full_path, context.sha].hash
end

#inputs_only!Object



22
23
24
25
# File 'lib/gitlab/ci/config/external/file/base.rb', line 22

def inputs_only!
  @inputs_only = true
  self
end

#inputs_only?Boolean

Returns:

  • (Boolean)


27
28
29
# File 'lib/gitlab/ci/config/external/file/base.rb', line 27

def inputs_only?
  @inputs_only
end

#invalid_extension?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/gitlab/ci/config/external/file/base.rb', line 39

def invalid_extension?
  location.nil? || !::File.basename(location).match?(YAML_ALLOWLIST_EXTENSION)
end

#invalid_location_type?Boolean

Returns:

  • (Boolean)


35
36
37
# File 'lib/gitlab/ci/config/external/file/base.rb', line 35

def invalid_location_type?
  !location.is_a?(String)
end

#load_and_validate_expanded_hash!Object



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/gitlab/ci/config/external/file/base.rb', line 102

def load_and_validate_expanded_hash!
  return errors.push("`#{masked_location}`: #{content_result.error}") unless content_result.valid?

  if content_result.interpolated? && context.user.present?
    ::Gitlab::UsageDataCounters::HLLRedisCounter
      .track_event('ci_interpolation_users', values: context.user.id)
  end

  context.logger.instrument(:config_file_expand_content_includes) do
    expanded_content_hash # calling the method expands then memoizes the result
  end

  validate_hash!
  validate_content_keys! if inputs_only?
end

#load_uninterpolated_yamlObject



129
130
131
# File 'lib/gitlab/ci/config/external/file/base.rb', line 129

def load_uninterpolated_yaml
  ::Gitlab::Ci::Config::Yaml::Loader.new(content).load_uninterpolated_yaml
end

#matching?Boolean

Returns:

  • (Boolean)


31
32
33
# File 'lib/gitlab/ci/config/external/file/base.rb', line 31

def matching?
  location.present?
end

#metadataObject



59
60
61
62
63
64
# File 'lib/gitlab/ci/config/external/file/base.rb', line 59

def 
  {
    context_project: context.project&.full_path,
    context_sha: context.sha
  }
end

#preload_contentObject



80
81
82
83
84
# File 'lib/gitlab/ci/config/external/file/base.rb', line 80

def preload_content
  # calling the `content` method either loads content into the memoized result
  # or lazily loads it via BatchLoader
  content
end

#preload_contextObject

This method is overridden to load context into the memoized result or to lazily load context via BatchLoader



76
77
78
# File 'lib/gitlab/ci/config/external/file/base.rb', line 76

def preload_context
  # no-op
end

#to_hashObject



55
56
57
# File 'lib/gitlab/ci/config/external/file/base.rb', line 55

def to_hash
  expanded_content_hash
end

#valid?Boolean

Returns:

  • (Boolean)


43
44
45
# File 'lib/gitlab/ci/config/external/file/base.rb', line 43

def valid?
  errors.none?
end

#validate_content_keys!Object



118
119
120
121
122
123
124
125
126
127
# File 'lib/gitlab/ci/config/external/file/base.rb', line 118

def validate_content_keys!
  return unless expanded_content_hash

  allowed_keys = i[inputs]
  unknown_keys = expanded_content_hash.keys - allowed_keys

  return unless unknown_keys.any?

  errors.push("Header include file `#{masked_location}` contains unknown keys: #{unknown_keys}")
end

#validate_content_presence!Object



98
99
100
# File 'lib/gitlab/ci/config/external/file/base.rb', line 98

def validate_content_presence!
  errors.push("Included file `#{masked_location}` is empty or does not exist!") if content.blank?
end

#validate_context!Object

Raises:

  • (NotImplementedError)


94
95
96
# File 'lib/gitlab/ci/config/external/file/base.rb', line 94

def validate_context!
  raise NotImplementedError, 'subclass must implement `validate_context!`'
end

#validate_location!Object



86
87
88
89
90
91
92
# File 'lib/gitlab/ci/config/external/file/base.rb', line 86

def validate_location!
  if invalid_location_type?
    errors.push("Included file `#{masked_location}` needs to be a string")
  elsif invalid_extension?
    errors.push("Included file `#{masked_location}` does not have YAML extension!")
  end
end