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:
Diffstat (limited to 'lib/gitlab/ci/config')
-rw-r--r--lib/gitlab/ci/config/entry/artifacts.rb2
-rw-r--r--lib/gitlab/ci/config/entry/job.rb2
-rw-r--r--lib/gitlab/ci/config/external/file/base.rb6
-rw-r--r--lib/gitlab/ci/config/external/file/component.rb18
-rw-r--r--lib/gitlab/ci/config/header/input.rb8
-rw-r--r--lib/gitlab/ci/config/interpolation/block.rb2
-rw-r--r--lib/gitlab/ci/config/interpolation/context.rb23
-rw-r--r--lib/gitlab/ci/config/interpolation/functions/base.rb6
-rw-r--r--lib/gitlab/ci/config/interpolation/functions/expand_vars.rb33
-rw-r--r--lib/gitlab/ci/config/interpolation/functions_stack.rb10
-rw-r--r--lib/gitlab/ci/config/interpolation/inputs/base_input.rb10
-rw-r--r--lib/gitlab/ci/config/interpolation/inputs/string_input.rb18
-rw-r--r--lib/gitlab/ci/config/interpolation/interpolator.rb7
-rw-r--r--lib/gitlab/ci/config/yaml/loader.rb13
-rw-r--r--lib/gitlab/ci/config/yaml/result.rb4
15 files changed, 120 insertions, 42 deletions
diff --git a/lib/gitlab/ci/config/entry/artifacts.rb b/lib/gitlab/ci/config/entry/artifacts.rb
index 27206d7e3a8..3fd07811daf 100644
--- a/lib/gitlab/ci/config/entry/artifacts.rb
+++ b/lib/gitlab/ci/config/entry/artifacts.rb
@@ -14,7 +14,7 @@ module Gitlab
ALLOWED_WHEN = %w[on_success on_failure always].freeze
ALLOWED_KEYS = %i[name untracked paths reports when expire_in expose_as exclude public].freeze
- EXPOSE_AS_REGEX = /\A\w[-\w ]*\z/.freeze
+ EXPOSE_AS_REGEX = /\A\w[-\w ]*\z/
EXPOSE_AS_ERROR_MESSAGE = "can contain only letters, digits, '-', '_' and spaces"
attributes ALLOWED_KEYS
diff --git a/lib/gitlab/ci/config/entry/job.rb b/lib/gitlab/ci/config/entry/job.rb
index c40d665f320..bf8a99ef45e 100644
--- a/lib/gitlab/ci/config/entry/job.rb
+++ b/lib/gitlab/ci/config/entry/job.rb
@@ -177,7 +177,7 @@ module Gitlab
def parsed_timeout
return unless has_timeout?
- ChronicDuration.parse(timeout.to_s, use_complete_matcher: true)
+ ChronicDuration.parse(timeout.to_s)
end
def ignored?
diff --git a/lib/gitlab/ci/config/external/file/base.rb b/lib/gitlab/ci/config/external/file/base.rb
index efba81c7420..b3c802e5657 100644
--- a/lib/gitlab/ci/config/external/file/base.rb
+++ b/lib/gitlab/ci/config/external/file/base.rb
@@ -10,7 +10,7 @@ module Gitlab
attr_reader :location, :params, :context, :errors
- YAML_WHITELIST_EXTENSION = /.+\.(yml|yaml)$/i.freeze
+ YAML_WHITELIST_EXTENSION = /.+\.(yml|yaml)$/i
def initialize(params, context)
@params = params
@@ -114,7 +114,9 @@ module Gitlab
def content_result
context.logger.instrument(:config_file_fetch_content_hash) do
- ::Gitlab::Ci::Config::Yaml::Loader.new(content, inputs: content_inputs).load
+ ::Gitlab::Ci::Config::Yaml::Loader.new(
+ content, inputs: content_inputs, variables: context.variables
+ ).load
end
end
strong_memoize_attr :content_result
diff --git a/lib/gitlab/ci/config/external/file/component.rb b/lib/gitlab/ci/config/external/file/component.rb
index de6de1bb7a8..03063e76dde 100644
--- a/lib/gitlab/ci/config/external/file/component.rb
+++ b/lib/gitlab/ci/config/external/file/component.rb
@@ -20,7 +20,7 @@ module Gitlab
::Gitlab::UsageDataCounters::HLLRedisCounter.track_event('cicd_component_usage', values: context.user.id)
- component_result.payload.fetch(:content)
+ component_payload.fetch(:content)
end
strong_memoize_attr :content
@@ -65,30 +65,30 @@ module Gitlab
override :expand_context_attrs
def expand_context_attrs
{
- project: component_path.project,
- sha: component_path.sha,
+ project: component_payload.fetch(:project),
+ sha: component_payload.fetch(:sha),
user: context.user,
variables: context.variables
}
end
def masked_blob
- return unless component_path
+ return unless component_payload
context.mask_variables_from(
Gitlab::Routing.url_helpers.project_blob_url(
- component_path.project,
- ::File.join(component_path.sha, component_path.project_file_path))
+ component_payload.fetch(:project),
+ ::File.join(component_payload.fetch(:sha), component_payload.fetch(:path)))
)
end
strong_memoize_attr :masked_blob
- def component_path
+ def component_payload
return unless component_result.success?
- component_result.payload.fetch(:path)
+ component_result.payload
end
- strong_memoize_attr :component_path
+ strong_memoize_attr :component_payload
end
end
end
diff --git a/lib/gitlab/ci/config/header/input.rb b/lib/gitlab/ci/config/header/input.rb
index 76a89a3080e..dcb96006459 100644
--- a/lib/gitlab/ci/config/header/input.rb
+++ b/lib/gitlab/ci/config/header/input.rb
@@ -11,12 +11,16 @@ module Gitlab
include ::Gitlab::Config::Entry::Validatable
include ::Gitlab::Config::Entry::Attributable
- attributes :default, :type, prefix: :input
+ ALLOWED_KEYS = %i[default description regex type].freeze
+
+ attributes ALLOWED_KEYS, prefix: :input
validations do
- validates :config, type: Hash, allowed_keys: [:default, :type]
+ validates :config, type: Hash, allowed_keys: ALLOWED_KEYS
validates :key, alphanumeric: true
validates :input_default, alphanumeric: true, allow_nil: true
+ validates :input_description, alphanumeric: true, allow_nil: true
+ validates :input_regex, type: String, allow_nil: true
validates :input_type, allow_nil: true, allowed_values: Interpolation::Inputs.input_types
end
end
diff --git a/lib/gitlab/ci/config/interpolation/block.rb b/lib/gitlab/ci/config/interpolation/block.rb
index cf8420f924e..aec19299e86 100644
--- a/lib/gitlab/ci/config/interpolation/block.rb
+++ b/lib/gitlab/ci/config/interpolation/block.rb
@@ -62,7 +62,7 @@ module Gitlab
return @errors.concat(access.errors) unless access.valid?
return @errors.push('too many functions in interpolation block') if functions.count > MAX_FUNCTIONS
- result = Interpolation::FunctionsStack.new(functions).evaluate(access.value)
+ result = Interpolation::FunctionsStack.new(functions, ctx).evaluate(access.value)
if result.success?
@value = result.value
diff --git a/lib/gitlab/ci/config/interpolation/context.rb b/lib/gitlab/ci/config/interpolation/context.rb
index f5e7db03291..19ea619f7da 100644
--- a/lib/gitlab/ci/config/interpolation/context.rb
+++ b/lib/gitlab/ci/config/interpolation/context.rb
@@ -14,8 +14,11 @@ module Gitlab
MAX_DEPTH = 3
- def initialize(hash)
- @context = hash
+ attr_reader :variables
+
+ def initialize(data, variables: [])
+ @data = data
+ @variables = Ci::Variables::Collection.fabricate(variables)
raise ContextTooComplexError if depth > MAX_DEPTH
end
@@ -32,25 +35,25 @@ module Gitlab
end
def depth
- deep_depth(@context)
+ deep_depth(@data)
end
def fetch(field)
- @context.fetch(field)
+ @data.fetch(field)
end
def key?(name)
- @context.key?(name)
+ @data.key?(name)
end
def to_h
- @context.to_h
+ @data.to_h
end
private
- def deep_depth(context, depth = 0)
- values = context.values.map do |value|
+ def deep_depth(data, depth = 0)
+ values = data.values.map do |value|
if value.is_a?(Hash)
deep_depth(value, depth + 1)
else
@@ -61,10 +64,10 @@ module Gitlab
values.max.to_i
end
- def self.fabricate(context)
+ def self.fabricate(context, variables: [])
case context
when Hash
- new(context)
+ new(context, variables: variables)
when Interpolation::Context
context
else
diff --git a/lib/gitlab/ci/config/interpolation/functions/base.rb b/lib/gitlab/ci/config/interpolation/functions/base.rb
index b9ce8cdc5bc..b04152a1558 100644
--- a/lib/gitlab/ci/config/interpolation/functions/base.rb
+++ b/lib/gitlab/ci/config/interpolation/functions/base.rb
@@ -20,9 +20,10 @@ module Gitlab
function_expression_pattern.match?(function_expression)
end
- def initialize(function_expression)
+ def initialize(function_expression, ctx)
@errors = []
@function_args = parse_args(function_expression)
+ @ctx = ctx
end
def valid?
@@ -35,10 +36,11 @@ module Gitlab
private
- attr_reader :function_args
+ attr_reader :function_args, :ctx
def error(message)
errors << "error in `#{self.class.name}` function: #{message}"
+ nil
end
def parse_args(function_expression)
diff --git a/lib/gitlab/ci/config/interpolation/functions/expand_vars.rb b/lib/gitlab/ci/config/interpolation/functions/expand_vars.rb
new file mode 100644
index 00000000000..658964018b5
--- /dev/null
+++ b/lib/gitlab/ci/config/interpolation/functions/expand_vars.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ module Interpolation
+ module Functions
+ class ExpandVars < Base
+ def self.function_expression_pattern
+ /^#{name}$/
+ end
+
+ def self.name
+ 'expand_vars'
+ end
+
+ def execute(input_value)
+ unless input_value.is_a?(String)
+ error("invalid input type: #{self.class.name} can only be used with string inputs")
+ return
+ end
+
+ ExpandVariables.expand_existing(input_value, ctx.variables, fail_on_masked: true)
+ rescue ExpandVariables::VariableExpansionError => e
+ error("variable expansion error: #{e.message}")
+ nil
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/interpolation/functions_stack.rb b/lib/gitlab/ci/config/interpolation/functions_stack.rb
index 951d1121d4f..4cb3e67b3e3 100644
--- a/lib/gitlab/ci/config/interpolation/functions_stack.rb
+++ b/lib/gitlab/ci/config/interpolation/functions_stack.rb
@@ -16,12 +16,14 @@ module Gitlab
end
FUNCTIONS = [
- Functions::Truncate
+ Functions::Truncate,
+ Functions::ExpandVars
].freeze
attr_reader :errors
- def initialize(function_expressions)
+ def initialize(function_expressions, ctx)
+ @ctx = ctx
@errors = []
@functions = build_stack(function_expressions)
end
@@ -48,14 +50,14 @@ module Gitlab
private
- attr_reader :functions
+ attr_reader :functions, :ctx
def build_stack(function_expressions)
function_expressions.map do |function_expression|
matching_function = FUNCTIONS.find { |function| function.matches?(function_expression) }
if matching_function.present?
- matching_function.new(function_expression)
+ matching_function.new(function_expression, ctx)
else
message = "no function matching `#{function_expression}`: " \
'check that the function name, arguments, and types are correct'
diff --git a/lib/gitlab/ci/config/interpolation/inputs/base_input.rb b/lib/gitlab/ci/config/interpolation/inputs/base_input.rb
index 5648c4d31ea..ba519776635 100644
--- a/lib/gitlab/ci/config/interpolation/inputs/base_input.rb
+++ b/lib/gitlab/ci/config/interpolation/inputs/base_input.rb
@@ -62,7 +62,15 @@ module Gitlab
end
# validate provided value
- error("provided value is not a #{self.class.type_name}") unless valid_value?(actual_value)
+ return error("provided value is not a #{self.class.type_name}") unless valid_value?(actual_value)
+
+ validate_regex!
+ end
+
+ def validate_regex!
+ return unless spec.key?(:regex)
+
+ error('RegEx validation can only be used with string inputs')
end
def error(message)
diff --git a/lib/gitlab/ci/config/interpolation/inputs/string_input.rb b/lib/gitlab/ci/config/interpolation/inputs/string_input.rb
index 39870582d0c..3f40e851f11 100644
--- a/lib/gitlab/ci/config/interpolation/inputs/string_input.rb
+++ b/lib/gitlab/ci/config/interpolation/inputs/string_input.rb
@@ -25,6 +25,24 @@ module Gitlab
def valid_value?(value)
value.nil? || value.is_a?(String)
end
+
+ private
+
+ def validate_regex!
+ return unless spec.key?(:regex)
+
+ safe_regex = ::Gitlab::UntrustedRegexp.new(spec[:regex])
+
+ return if safe_regex.match?(actual_value)
+
+ if value.nil?
+ error('default value does not match required RegEx pattern')
+ else
+ error('provided value does not match required RegEx pattern')
+ end
+ rescue RegexpError
+ error('invalid regular expression')
+ end
end
end
end
diff --git a/lib/gitlab/ci/config/interpolation/interpolator.rb b/lib/gitlab/ci/config/interpolation/interpolator.rb
index 95c419d7427..5b21b777c1d 100644
--- a/lib/gitlab/ci/config/interpolation/interpolator.rb
+++ b/lib/gitlab/ci/config/interpolation/interpolator.rb
@@ -8,11 +8,12 @@ module Gitlab
# Performs CI config file interpolation, and surfaces all possible interpolation errors.
#
class Interpolator
- attr_reader :config, :args, :errors
+ attr_reader :config, :args, :variables, :errors
- def initialize(config, args)
+ def initialize(config, args, variables)
@config = config
@args = args.to_h
+ @variables = variables
@errors = []
@interpolated = false
end
@@ -86,7 +87,7 @@ module Gitlab
end
def context
- @context ||= Context.new({ inputs: inputs.to_hash })
+ @context ||= Context.new({ inputs: inputs.to_hash }, variables: variables)
end
def template
diff --git a/lib/gitlab/ci/config/yaml/loader.rb b/lib/gitlab/ci/config/yaml/loader.rb
index 5d56061a8bb..1e9ac2b3dd5 100644
--- a/lib/gitlab/ci/config/yaml/loader.rb
+++ b/lib/gitlab/ci/config/yaml/loader.rb
@@ -10,9 +10,10 @@ module Gitlab
AVAILABLE_TAGS = [Config::Yaml::Tags::Reference].freeze
MAX_DOCUMENTS = 2
- def initialize(content, inputs: {})
+ def initialize(content, inputs: {}, variables: [])
@content = content
@inputs = inputs
+ @variables = variables
end
def load
@@ -20,7 +21,7 @@ module Gitlab
return yaml_result unless yaml_result.valid?
- interpolator = Interpolation::Interpolator.new(yaml_result, inputs)
+ interpolator = Interpolation::Interpolator.new(yaml_result, inputs, variables)
interpolator.interpolate!
@@ -32,16 +33,16 @@ module Gitlab
end
end
- private
-
- attr_reader :content, :inputs
-
def load_uninterpolated_yaml
Yaml::Result.new(config: load_yaml!, error: nil)
rescue ::Gitlab::Config::Loader::FormatError => e
Yaml::Result.new(error: e.message, error_class: e)
end
+ private
+
+ attr_reader :content, :inputs, :variables
+
def load_yaml!
ensure_custom_tags
diff --git a/lib/gitlab/ci/config/yaml/result.rb b/lib/gitlab/ci/config/yaml/result.rb
index a68cfde6653..0e7e9230467 100644
--- a/lib/gitlab/ci/config/yaml/result.rb
+++ b/lib/gitlab/ci/config/yaml/result.rb
@@ -39,6 +39,10 @@ module Gitlab
@config.first || {}
end
+
+ def inputs
+ (has_header? && header[:spec][:inputs]) || {}
+ end
end
end
end