summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamil Trzciński <ayufan@ayufan.eu>2018-09-03 11:20:59 +0200
committerKamil Trzciński <ayufan@ayufan.eu>2018-09-03 11:21:21 +0200
commitc8ea98739f8ebe59e55cd14ecc468d7c66929b6f (patch)
tree1a13997654391a4004abe0c0fd162e5a957257f7
parent553de354044a9abf52ff6c53bfd956cff209c960 (diff)
downloadgitlab-ce-kamil-refactor-ci-builds-v4.tar.gz
Config Value storekamil-refactor-ci-builds-v4
-rw-r--r--app/models/ci/build.rb2
-rw-r--r--app/models/ci/build_config.rb134
-rw-r--r--app/models/ci/build_config_value.rb40
-rw-r--r--db/migrate/20180831115822_create_ci_builds_config_values.rb21
4 files changed, 197 insertions, 0 deletions
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 2c182b02f36..23218aa2c22 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -35,10 +35,12 @@ module Ci
end
has_one :config, class_name: 'Ci::BuildConfig'
+ has_many :config_values, class_name: 'Ci::BuildConfigValue'
has_one :metadata, class_name: 'Ci::BuildMetadata'
has_one :runner_session, class_name: 'Ci::BuildRunnerSession', validate: true, inverse_of: :build
accepts_nested_attributes_for :runner_session
+ accepts_nested_attributes_for :config_values
delegate :timeout, to: :metadata, prefix: true, allow_nil: true
delegate :url, to: :runner_session, prefix: true, allow_nil: true
diff --git a/app/models/ci/build_config.rb b/app/models/ci/build_config.rb
index 2401b8b514b..954e8f6df43 100644
--- a/app/models/ci/build_config.rb
+++ b/app/models/ci/build_config.rb
@@ -16,5 +16,139 @@ module Ci
serialize :yaml_options # rubocop:disable Cop/ActiveRecordSerialize
serialize :yaml_variables, Gitlab::Serializer::Ci::Variables # rubocop:disable Cop/ActiveRecordSerialize
+
+ STRUCTURE = {
+ image: :image,
+ services: [:service],
+ artifacts: {
+ name: :artifacts_name,
+ untracked: :artifacts_untracked,
+ path: [:artifacts_path],
+ reports: {
+ junit: [:artifacts_report_junit]
+ },
+ when: :artifacts_when,
+ expire_in: :artifacts_expire_in,
+ },
+ cache: {
+ key: :cache_key,
+ untracked: :cache_untracked,
+ path: [:cache_paths],
+ policy: :cache_policy
+ },
+ dependencies: [:dependency],
+ before_script: [:before_script],
+ script: [:script],
+ after_script: [:after_script],
+ environment: {
+ name: :environment_name,
+ url: :environment_url,
+ action: :environment_action
+ },
+ retry: :retry
+ }
+
+ def options
+ demap_data(STRUCTURE, nil)
+ end
+
+ def options=(value)
+ build.config_values_attributes = map_data(STRUCTURE, value, nil).flatten
+ end
+
+ public
+
+ def map_data(data_def, value, index)
+ if data_def.is_a?(Symbol)
+ map_value(data_def, value, index)
+ elsif data_def.is_a?(Hash)
+ map_structure(data_def, value, index)
+ elsif data_def.is_a?(Array)
+ map_array(data_def, value, index)
+ else
+ raise "Unsupported type for: #{data_def}"
+ end
+ end
+
+ def map_structure(data_def, hash, index)
+ raise 'Invalid data' unless data_def.is_a?(Hash)
+ raise 'Value needs to be hash' unless hash.is_a?(Hash)
+
+ data_def.map do |key, data|
+ map_data(data, hash[key], index) if hash[key]
+ end.compact
+ end
+
+ def map_value(key, value, index)
+ { key: key, value_string: value, index: index }
+ end
+
+ def map_array(data_def, values, index)
+ raise 'Invalid data' unless data_def.is_a?(Array)
+ raise 'Array needs exactly one' unless data_def.one?
+ raise 'Nested arrays are not supported' if index
+ raise "Value needs to be array: #{values}" unless values.is_a?(Array)
+
+ type = data_def.first
+
+ values.map.with_index do |value, index|
+ map_data(type, value, index)
+ end
+ end
+
+ public
+
+ def demap_data(data_def, index)
+ if data_def.is_a?(Symbol)
+ demap_value(data_def, index)
+ elsif data_def.is_a?(Hash)
+ demap_structure(data_def, index)
+ elsif data_def.is_a?(Array)
+ demap_array(data_def, index)
+ else
+ raise "Unsupported type for: #{data_def}"
+ end
+ end
+
+ def demap_structure(data_def, index)
+ raise 'Invalid data' unless data_def.is_a?(Hash)
+
+ data_def = data_def.map do |key, data|
+ result = demap_data(data, index)
+ [key, result]
+ end
+
+ puts "#{data_def}"
+
+ result = data_def.to_h.compact
+ result if result.present?
+ end
+
+ def demap_array(data_def, index)
+ raise 'Invalid data' unless data_def.is_a?(Array)
+ raise 'Array needs exactly one' unless data_def.one?
+ raise 'Nested arrays are not supported' if index
+
+ type = data_def.first
+
+ results = []
+
+ 10000.times do |index|
+ result = demap_data(type, index)
+ break unless result.present?
+ results << result
+ end
+
+ results if results.present?
+ end
+
+ def demap_value(key, index)
+ value = build.config_values.find do |config|
+ config.key.to_sym == key && config.index == index
+ end
+ return unless value
+
+ value.value_string
+ end
end
end
diff --git a/app/models/ci/build_config_value.rb b/app/models/ci/build_config_value.rb
new file mode 100644
index 00000000000..fb270c0550a
--- /dev/null
+++ b/app/models/ci/build_config_value.rb
@@ -0,0 +1,40 @@
+module Ci
+ class BuildConfigValue < ActiveRecord::Base
+ extend Gitlab::Ci::Model
+
+ # The version of the schema that first introduced this model/table.
+ MINIMUM_SCHEMA_VERSION = 20180831115822
+
+ def self.available?
+ @available ||=
+ ActiveRecord::Migrator.current_version >= MINIMUM_SCHEMA_VERSION
+ end
+
+ self.table_name = 'ci_builds_config_values'
+
+ belongs_to :build
+
+ enum key: [
+ :image,
+ :service,
+ :artifacts_name,
+ :artifacts_untracked,
+ :artifacts_path,
+ :artifacts_report_junit,
+ :artifacts_when,
+ :artifacts_expire_in,
+ :cache_key,
+ :cache_untracked,
+ :cache_paths,
+ :cache_policy,
+ :dependency,
+ :before_script,
+ :script,
+ :after_script,
+ :environment_name,
+ :environment_url,
+ :environment_action,
+ :retry,
+ ]
+ end
+end
diff --git a/db/migrate/20180831115822_create_ci_builds_config_values.rb b/db/migrate/20180831115822_create_ci_builds_config_values.rb
new file mode 100644
index 00000000000..b1e75881ae1
--- /dev/null
+++ b/db/migrate/20180831115822_create_ci_builds_config_values.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class CreateCiBuildsConfigValues < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :ci_builds_config_values, id: :bigserial do |t|
+ t.integer :build_id, null: false
+ t.foreign_key :ci_builds, column: :build_id, on_delete: :cascade
+
+ t.integer :key, null: false
+ t.integer :index
+ t.text :value_string
+ end
+ end
+end