diff options
author | Matija Čupić <matteeyah@gmail.com> | 2018-09-07 20:57:57 +0300 |
---|---|---|
committer | Matija Čupić <matteeyah@gmail.com> | 2018-09-07 20:57:57 +0300 |
commit | c3e33f06c2920a9f032ee8166cccf8423bd24b78 (patch) | |
tree | c04eda599e6ef1fb2206bf586e05b8b798ed4ffa /lib/gitlab | |
parent | 9083fc04f1add6f7e4628cdb10fef69c6b815ef5 (diff) |
Build barebones for ExternalFiles libraries
CE mirror of 30ca00f17034f654403ec7cb5dc370d1e5db8152
Diffstat (limited to 'lib/gitlab')
-rw-r--r-- | lib/gitlab/ci/config/entry/global.rb | 10 | ||||
-rw-r--r-- | lib/gitlab/ci/config/entry/includes.rb | 22 | ||||
-rw-r--r-- | lib/gitlab/ci/config/entry/validators.rb | 32 | ||||
-rw-r--r-- | lib/gitlab/ci/external_files/external_file.rb | 38 | ||||
-rw-r--r-- | lib/gitlab/ci/external_files/mapper.rb | 27 | ||||
-rw-r--r-- | lib/gitlab/ci/external_files/processor.rb | 46 |
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 |