summaryrefslogtreecommitdiff
path: root/lib/gitlab/ci/config
diff options
context:
space:
mode:
authorGrzegorz Bizon <grzegorz@gitlab.com>2018-11-07 10:38:05 +0000
committerGrzegorz Bizon <grzegorz@gitlab.com>2018-11-07 10:38:05 +0000
commit6f6cd4f43dfdab19c8cb1ac7a03cae268f12b206 (patch)
tree514d15ed2eeb38a45ac7ceb820264d7e6392e58c /lib/gitlab/ci/config
parentb1fae097bdb54232ca56f11447ec895ea067c56c (diff)
parent7366c319df12900e40dbed679feab146d1092d89 (diff)
downloadgitlab-ce-6f6cd4f43dfdab19c8cb1ac7a03cae268f12b206.tar.gz
Merge branch '21480-parallel-job-keyword-mvc' into 'master'
Resolve "`parallel` job keyword MVC" Closes #21480 See merge request gitlab-org/gitlab-ce!22631
Diffstat (limited to 'lib/gitlab/ci/config')
-rw-r--r--lib/gitlab/ci/config/entry/job.rb14
-rw-r--r--lib/gitlab/ci/config/normalizer.rb63
2 files changed, 72 insertions, 5 deletions
diff --git a/lib/gitlab/ci/config/entry/job.rb b/lib/gitlab/ci/config/entry/job.rb
index e4610faa327..362014b1a09 100644
--- a/lib/gitlab/ci/config/entry/job.rb
+++ b/lib/gitlab/ci/config/entry/job.rb
@@ -14,7 +14,7 @@ module Gitlab
ALLOWED_KEYS = %i[tags script only except type image services
allow_failure type stage when start_in artifacts cache
dependencies before_script after_script variables
- environment coverage retry extends].freeze
+ environment coverage retry parallel extends].freeze
validations do
validates :config, allowed_keys: ALLOWED_KEYS
@@ -29,6 +29,8 @@ module Gitlab
validates :retry, numericality: { only_integer: true,
greater_than_or_equal_to: 0,
less_than_or_equal_to: 2 }
+ validates :parallel, numericality: { only_integer: true,
+ greater_than_or_equal_to: 2 }
validates :when,
inclusion: { in: %w[on_success on_failure always manual delayed],
message: 'should be on_success, on_failure, ' \
@@ -79,17 +81,18 @@ module Gitlab
description: 'Artifacts configuration for this job.'
entry :environment, Entry::Environment,
- description: 'Environment configuration for this job.'
+ description: 'Environment configuration for this job.'
entry :coverage, Entry::Coverage,
- description: 'Coverage configuration for this job.'
+ description: 'Coverage configuration for this job.'
helpers :before_script, :script, :stage, :type, :after_script,
:cache, :image, :services, :only, :except, :variables,
- :artifacts, :commands, :environment, :coverage, :retry
+ :artifacts, :commands, :environment, :coverage, :retry,
+ :parallel
attributes :script, :tags, :allow_failure, :when, :dependencies,
- :retry, :extends, :start_in
+ :retry, :parallel, :extends, :start_in
def compose!(deps = nil)
super do
@@ -158,6 +161,7 @@ module Gitlab
environment_name: environment_defined? ? environment_value[:name] : nil,
coverage: coverage_defined? ? coverage_value : nil,
retry: retry_defined? ? retry_value.to_i : nil,
+ parallel: parallel_defined? ? parallel_value.to_i : nil,
artifacts: artifacts_value,
after_script: after_script_value,
ignore: ignored? }
diff --git a/lib/gitlab/ci/config/normalizer.rb b/lib/gitlab/ci/config/normalizer.rb
new file mode 100644
index 00000000000..969ae093e8b
--- /dev/null
+++ b/lib/gitlab/ci/config/normalizer.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ class Normalizer
+ def initialize(jobs_config)
+ @jobs_config = jobs_config
+ end
+
+ def normalize_jobs
+ extract_parallelized_jobs
+ parallelized_config = parallelize_jobs
+ parallelize_dependencies(parallelized_config)
+ end
+
+ private
+
+ def extract_parallelized_jobs
+ @parallelized_jobs = {}
+
+ @jobs_config.each do |job_name, config|
+ if config[:parallel]
+ @parallelized_jobs[job_name] = self.class.parallelize_job_names(job_name, config[:parallel])
+ end
+ end
+
+ @parallelized_jobs
+ end
+
+ def parallelize_jobs
+ @jobs_config.each_with_object({}) do |(job_name, config), hash|
+ if @parallelized_jobs.key?(job_name)
+ @parallelized_jobs[job_name].each { |name, index| hash[name.to_sym] = config.merge(name: name, instance: index) }
+ else
+ hash[job_name] = config
+ end
+
+ hash
+ end
+ end
+
+ def parallelize_dependencies(parallelized_config)
+ parallelized_config.each_with_object({}) do |(job_name, config), hash|
+ parallelized_job_names = @parallelized_jobs.keys.map(&:to_s)
+ if config[:dependencies] && (intersection = config[:dependencies] & parallelized_job_names).any?
+ deps = intersection.map { |dep| @parallelized_jobs[dep.to_sym].map(&:first) }.flatten
+ hash[job_name] = config.merge(dependencies: deps)
+ else
+ hash[job_name] = config
+ end
+
+ hash
+ end
+ end
+
+ def self.parallelize_job_names(name, total)
+ Array.new(total) { |index| ["#{name} #{index + 1}/#{total}", index + 1] }
+ end
+ end
+ end
+ end
+end