diff options
Diffstat (limited to 'lib/gitlab/ci/pipeline/chain/build/associations.rb')
-rw-r--r-- | lib/gitlab/ci/pipeline/chain/build/associations.rb | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/lib/gitlab/ci/pipeline/chain/build/associations.rb b/lib/gitlab/ci/pipeline/chain/build/associations.rb index eb49c56bcd7..b5d63691849 100644 --- a/lib/gitlab/ci/pipeline/chain/build/associations.rb +++ b/lib/gitlab/ci/pipeline/chain/build/associations.rb @@ -6,7 +6,25 @@ module Gitlab module Chain class Build class Associations < Chain::Base + include Gitlab::Allowable + include Chain::Helpers + def perform! + assign_pipeline_variables + assign_source_pipeline + end + + def break? + @pipeline.errors.any? + end + + private + + def assign_pipeline_variables + @pipeline.variables_attributes = variables_attributes + end + + def assign_source_pipeline return unless @command.bridge @pipeline.build_source_pipeline( @@ -17,8 +35,45 @@ module Gitlab ) end - def break? - false + def variables_attributes + variables = Array(@command.variables_attributes) + variables = apply_permissions(variables) + validate_uniqueness(variables) + end + + def apply_permissions(variables) + # We allow parent pipelines to pass variables to child pipelines since + # these variables are coming from internal configurations. We will check + # permissions to :set_pipeline_variables when those are injected upstream, + # to the parent pipeline. + # In other scenarios (e.g. multi-project pipelines or run pipeline via UI) + # the variables are provided from the outside and those should be guarded. + return variables if @command.creates_child_pipeline? + + if variables.present? && !can?(@command.current_user, :set_pipeline_variables, @command.project) + error("Insufficient permissions to set pipeline variables") + variables = [] + end + + variables + end + + def validate_uniqueness(variables) + duplicated_keys = variables + .map { |var| var[:key] } + .tally + .filter_map { |key, count| key if count > 1 } + + if duplicated_keys.empty? + variables + else + error(duplicate_variables_message(duplicated_keys), config_error: true) + [] + end + end + + def duplicate_variables_message(keys) + "Duplicate variable #{'name'.pluralize(keys.size)}: #{keys.join(', ')}" end end end |