summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMatija Čupić <matteeyah@gmail.com>2018-09-07 19:57:57 +0200
committerMatija Čupić <matteeyah@gmail.com>2018-09-07 19:57:57 +0200
commitc3e33f06c2920a9f032ee8166cccf8423bd24b78 (patch)
treec04eda599e6ef1fb2206bf586e05b8b798ed4ffa /lib
parent9083fc04f1add6f7e4628cdb10fef69c6b815ef5 (diff)
downloadgitlab-ce-c3e33f06c2920a9f032ee8166cccf8423bd24b78.tar.gz
Build barebones for ExternalFiles libraries
CE mirror of 30ca00f17034f654403ec7cb5dc370d1e5db8152
Diffstat (limited to 'lib')
-rw-r--r--lib/gitlab/ci/config/entry/global.rb10
-rw-r--r--lib/gitlab/ci/config/entry/includes.rb22
-rw-r--r--lib/gitlab/ci/config/entry/validators.rb32
-rw-r--r--lib/gitlab/ci/external_files/external_file.rb38
-rw-r--r--lib/gitlab/ci/external_files/mapper.rb27
-rw-r--r--lib/gitlab/ci/external_files/processor.rb46
6 files changed, 174 insertions, 1 deletions
diff --git a/lib/gitlab/ci/config/entry/global.rb b/lib/gitlab/ci/config/entry/global.rb
index a4ec8f0ff2f..401e566de77 100644
--- a/lib/gitlab/ci/config/entry/global.rb
+++ b/lib/gitlab/ci/config/entry/global.rb
@@ -33,11 +33,15 @@ module Gitlab
entry :cache, Entry::Cache,
description: 'Configure caching between build jobs.'
+ entry :includes, Entry::Includes,
+ description: 'External GitlLab Ci files'
+
helpers :before_script, :image, :services, :after_script,
- :variables, :stages, :types, :cache, :jobs
+ :variables, :stages, :types, :cache, :jobs, :includes
def compose!(_deps = nil)
super(self) do
+ append_external_files!
compose_jobs!
compose_deprecated_entries!
end
@@ -45,6 +49,10 @@ module Gitlab
private
+ def append_external_files!
+ return if includes_value.nil?
+ end
+
def compose_jobs!
factory = Entry::Factory.new(Entry::Jobs)
.value(@config.except(*self.class.nodes.keys))
diff --git a/lib/gitlab/ci/config/entry/includes.rb b/lib/gitlab/ci/config/entry/includes.rb
new file mode 100644
index 00000000000..c7a8c7960e8
--- /dev/null
+++ b/lib/gitlab/ci/config/entry/includes.rb
@@ -0,0 +1,22 @@
+module Gitlab
+ module Ci
+ class Config
+ module Entry
+ ##
+ # Entry that represents a Docker image.
+ #
+ class Includes < Node
+ include Validatable
+
+ validations do
+ validates :config, array_or_string: true, external_file: true, allow_nil: true
+ end
+
+ def value
+ Array(@config)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/entry/validators.rb b/lib/gitlab/ci/config/entry/validators.rb
index b3c889ee92f..5b4d5d53821 100644
--- a/lib/gitlab/ci/config/entry/validators.rb
+++ b/lib/gitlab/ci/config/entry/validators.rb
@@ -60,6 +60,38 @@ module Gitlab
end
end
+ class ArrayOrStringValidator < ActiveModel::EachValidator
+ def validate_each(record, attribute, value)
+ unless value.is_a?(Array) || value.is_a?(String)
+ record.errors.add(attribute, 'should be an array or a string')
+ end
+ end
+ end
+
+ class ExternalFileValidator < ActiveModel::EachValidator
+ def validate_each(record, attribute, value)
+ if value.is_a?(Array)
+ value.each do |path|
+ validate_external_file(path, record, attribute)
+ end
+ else
+ validate_external_file(value, record, attribute)
+ end
+ end
+
+ private
+
+ def validate_external_file(value, record, attribute)
+ unless valid_url?(value)
+ record.errors.add(attribute, 'should be a valid local or remote file')
+ end
+ end
+
+ def valid_url?(value)
+ Gitlab::UrlSanitizer.valid?(value) || File.exists?("#{Rails.root}/#{value}")
+ end
+ end
+
class KeyValidator < ActiveModel::EachValidator
include LegacyValidationHelpers
diff --git a/lib/gitlab/ci/external_files/external_file.rb b/lib/gitlab/ci/external_files/external_file.rb
new file mode 100644
index 00000000000..9bad8231c42
--- /dev/null
+++ b/lib/gitlab/ci/external_files/external_file.rb
@@ -0,0 +1,38 @@
+require 'open-uri'
+
+module Gitlab
+ module Ci
+ module ExternalFiles
+ class ExternalFile
+
+ def initialize(value)
+ @value = value
+ end
+
+ def content
+ if remote_url?
+ open(value).read
+ else
+ File.read(base_path)
+ end
+ end
+
+ def valid?
+ remote_url? || File.exists?(base_path)
+ end
+
+ private
+
+ attr_reader :value
+
+ def base_path
+ "#{Rails.root}/#{value}"
+ end
+
+ def remote_url?
+ ::Gitlab::UrlSanitizer.valid?(value)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/external_files/mapper.rb b/lib/gitlab/ci/external_files/mapper.rb
new file mode 100644
index 00000000000..5deb2f5a2e5
--- /dev/null
+++ b/lib/gitlab/ci/external_files/mapper.rb
@@ -0,0 +1,27 @@
+module Gitlab
+ module Ci
+ module ExternalFiles
+ class Mapper
+
+ def self.fetch_paths(values)
+ paths = values.fetch(:includes, [])
+ normalize_paths(paths)
+ end
+
+ private
+
+ def self.normalize_paths(paths)
+ if paths.is_a?(String)
+ [build_external_file(paths)]
+ else
+ paths.map { |path| build_external_file(path) }
+ end
+ end
+
+ def self.build_external_file(path)
+ ::Gitlab::Ci::ExternalFiles::ExternalFile.new(path)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/external_files/processor.rb b/lib/gitlab/ci/external_files/processor.rb
new file mode 100644
index 00000000000..f38bc7633b5
--- /dev/null
+++ b/lib/gitlab/ci/external_files/processor.rb
@@ -0,0 +1,46 @@
+module Gitlab
+ module Ci
+ module ExternalFiles
+ class Processor
+ ExternalFileError = Class.new(StandardError)
+
+ def initialize(values)
+ @values = values
+ @external_files = ::Gitlab::Ci::ExternalFiles::Mapper.fetch_paths(values)
+ end
+
+ def perform
+ return values if external_files.empty?
+
+ external_files.each do |external_file|
+ validate_external_file(external_file)
+ append_external_content(external_file)
+ end
+
+ remove_include_keyword
+ end
+
+ private
+
+ attr_reader :values, :external_files
+
+ def validate_external_file(external_file)
+ unless external_file.valid?
+ raise ExternalFileError, 'External files should be a valid local or remote file'
+ end
+ end
+
+ def append_external_content(external_file)
+ external_values = ::Gitlab::Ci::Config::Loader.new(external_file.content).load!
+ @values.merge!(external_values)
+ end
+
+ def remove_include_keyword
+ values.delete(:includes)
+ values
+ end
+
+ end
+ end
+ end
+end