summaryrefslogtreecommitdiff
path: root/lib/gitlab/ci/pipeline/chain/build/associations.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/ci/pipeline/chain/build/associations.rb')
-rw-r--r--lib/gitlab/ci/pipeline/chain/build/associations.rb59
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