diff --git a/app/graphql/types/ci/config_variable_type.rb b/app/graphql/types/ci/config_variable_type.rb
index 87ae026c2c1dafd4004646e6e062def7024f3b3b..5b5890fd5a56c806618c3ec8a632aaf260d77011 100644
--- a/app/graphql/types/ci/config_variable_type.rb
+++ b/app/graphql/types/ci/config_variable_type.rb
@@ -17,6 +17,10 @@ class ConfigVariableType < BaseObject # rubocop:disable Graphql/AuthorizeTypes
field :value, GraphQL::Types::String,
null: true,
description: 'Value of the variable.'
+
+ field :value_options, [GraphQL::Types::String],
+ null: true,
+ description: 'Value options for the variable.'
end
end
end
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index bd9905ca652a0293fdb60fc95207a12d8184f522..f547326d8189478cfcdd486beda6360d07e4e2bc 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -10405,6 +10405,7 @@ CI/CD config variables.
| `description` | [`String`](#string) | Description for the CI/CD config variable. |
| `key` | [`String`](#string) | Name of the variable. |
| `value` | [`String`](#string) | Value of the variable. |
+| `valueOptions` | [`[String!]`](#string) | Value options for the variable. |
### `CiGroup`
diff --git a/lib/gitlab/ci/config/entry/root.rb b/lib/gitlab/ci/config/entry/root.rb
index b1b42cad74c34f080fba1973d8c433a04ed96a3b..1d7d8617c747806f69f7f720636d2dbbcea9df02 100644
--- a/lib/gitlab/ci/config/entry/root.rb
+++ b/lib/gitlab/ci/config/entry/root.rb
@@ -50,7 +50,7 @@ class Root < ::Gitlab::Config::Entry::Node
entry :variables, Entry::Variables,
description: 'Environment variables that will be used.',
- metadata: { allowed_value_data: %i[value description] },
+ metadata: { allowed_value_data: %i[value description], allow_array_value: true },
reserved: true
entry :stages, Entry::Stages,
diff --git a/lib/gitlab/ci/config/entry/variable.rb b/lib/gitlab/ci/config/entry/variable.rb
index 253888aadebeb3319680d90bb3fb45ba2bac8dd0..54c153c8b07dfbd26189ff8cc2d2b5203a4ed73c 100644
--- a/lib/gitlab/ci/config/entry/variable.rb
+++ b/lib/gitlab/ci/config/entry/variable.rb
@@ -10,6 +10,7 @@ module Entry
class Variable < ::Gitlab::Config::Entry::Simplifiable
strategy :SimpleVariable, if: -> (config) { SimpleVariable.applies_to?(config) }
strategy :ComplexVariable, if: -> (config) { ComplexVariable.applies_to?(config) }
+ strategy :ComplexArrayVariable, if: -> (config) { ComplexArrayVariable.applies_to?(config) }
class SimpleVariable < ::Gitlab::Config::Entry::Node
include ::Gitlab::Config::Entry::Validatable
@@ -39,7 +40,7 @@ class ComplexVariable < ::Gitlab::Config::Entry::Node
class << self
def applies_to?(config)
- config.is_a?(Hash)
+ config.is_a?(Hash) && !config[:value].is_a?(Array)
end
end
@@ -86,6 +87,34 @@ def config_description_defined?
end
end
+ class ComplexArrayVariable < ComplexVariable
+ include ::Gitlab::Config::Entry::Validatable
+
+ class << self
+ def applies_to?(config)
+ config.is_a?(Hash) && config[:value].is_a?(Array)
+ end
+ end
+
+ validations do
+ validates :config_value, array_of_strings: true, allow_nil: false, if: :config_value_defined?
+
+ validate do
+ next if opt(:allow_array_value)
+
+ errors.add(:config, 'value must be an alphanumeric string')
+ end
+ end
+
+ def value
+ config_value.first
+ end
+
+ def value_with_data
+ super.merge(value_options: config_value).compact
+ end
+ end
+
class UnknownStrategy < ::Gitlab::Config::Entry::Node
def errors
["variable definition must be either a string or a hash"]
diff --git a/lib/gitlab/ci/config/entry/variables.rb b/lib/gitlab/ci/config/entry/variables.rb
index 7fa0ee000667143a1a614119fe01a5ed75fb504a..4430a11dda73bd8b7b550f9ebed141871a67e756 100644
--- a/lib/gitlab/ci/config/entry/variables.rb
+++ b/lib/gitlab/ci/config/entry/variables.rb
@@ -36,7 +36,7 @@ def composable_class(_name, _config)
end
def composable_metadata
- { allowed_value_data: opt(:allowed_value_data) }
+ { allowed_value_data: opt(:allowed_value_data), allow_array_value: opt(:allow_array_value) }
end
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/root_spec.rb b/spec/lib/gitlab/ci/config/entry/root_spec.rb
index 64438a1594a46e66b9541dbf8747bf547f43bb79..a55e13e7c2d9eb70139cf25d2c011212c7708876 100644
--- a/spec/lib/gitlab/ci/config/entry/root_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/root_spec.rb
@@ -34,7 +34,11 @@
image: 'image:1.0',
default: {},
services: ['postgres:9.1', 'mysql:5.5'],
- variables: { VAR: 'root', VAR2: { value: 'val 2', description: 'this is var 2' } },
+ variables: {
+ VAR: 'root',
+ VAR2: { value: 'val 2', description: 'this is var 2' },
+ VAR3: { value: %w[val3 val3b], description: 'this is var 3' }
+ },
after_script: ['make clean'],
stages: %w(build pages release),
cache: { key: 'k', untracked: true, paths: ['public/'] },
@@ -83,7 +87,7 @@
end
it 'sets correct variables value' do
- expect(root.variables_value).to eq('VAR' => 'root', 'VAR2' => 'val 2')
+ expect(root.variables_value).to eq('VAR' => 'root', 'VAR2' => 'val 2', 'VAR3' => 'val3')
end
describe '#leaf?' do
diff --git a/spec/lib/gitlab/ci/config/entry/variable_spec.rb b/spec/lib/gitlab/ci/config/entry/variable_spec.rb
index 744a89d45095103be9489d9e7f145c18db59ab8e..076a5b32e92ba6ef004a201738c10164eae81e0f 100644
--- a/spec/lib/gitlab/ci/config/entry/variable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/variable_spec.rb
@@ -127,20 +127,6 @@
end
end
- context 'when config value is an array' do
- let(:config) { { value: ['value'], description: 'description' } }
-
- describe '#valid?' do
- it { is_expected.not_to be_valid }
- end
-
- describe '#errors' do
- subject(:errors) { entry.errors }
-
- it { is_expected.to include 'var1 config value must be an alphanumeric string' }
- end
- end
-
context 'when config description is a symbol' do
let(:config) { { value: 'value', description: :description } }
@@ -209,4 +195,42 @@
end
end
end
+
+ describe 'ComplexArrayVariable' do
+ context 'when allow_array_value metadata is false' do
+ let(:config) { { value: %w[value value2], description: 'description' } }
+ let(:metadata) { { allow_array_value: false } }
+
+ describe '#valid?' do
+ it { is_expected.not_to be_valid }
+ end
+
+ describe '#errors' do
+ subject(:errors) { entry.errors }
+
+ it { is_expected.to include 'var1 config value must be an alphanumeric string' }
+ end
+ end
+
+ context 'when allow_array_value metadata is true' do
+ let(:config) { { value: %w[value value2], description: 'description' } }
+ let(:metadata) { { allowed_value_data: %i[value description], allow_array_value: true } }
+
+ describe '#valid?' do
+ it { is_expected.to be_valid }
+ end
+
+ describe '#value' do
+ subject(:value) { entry.value }
+
+ it { is_expected.to eq('value') }
+ end
+
+ describe '#value_with_data' do
+ subject(:value_with_data) { entry.value_with_data }
+
+ it { is_expected.to eq(value: 'value', description: 'description', value_options: %w[value value2]) }
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/config/entry/variables_spec.rb b/spec/lib/gitlab/ci/config/entry/variables_spec.rb
index ad7290d058960f2c7f29e6bd5d6d8ba20216c4ea..085f304094e4f1553b84ca43a458a4626768056e 100644
--- a/spec/lib/gitlab/ci/config/entry/variables_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/variables_spec.rb
@@ -98,6 +98,62 @@
it_behaves_like 'invalid config', /must be either a string or a hash/
end
+ context 'when entry config value has unallowed value key-value pair and value is a string' do
+ let(:config) do
+ { 'VARIABLE_1' => { value: 'value', description: 'variable 1' } }
+ end
+
+ context 'when there is no allowed_value_data metadata' do
+ it_behaves_like 'invalid config', /variable_1 config must be a string/
+ end
+
+ context 'when metadata has allow_array_value and allowed_value_data' do
+ let(:metadata) { { allowed_value_data: %i[value description], allow_array_value: true } }
+
+ let(:result) do
+ { 'VARIABLE_1' => 'value' }
+ end
+
+ it_behaves_like 'valid config'
+
+ describe '#value_with_data' do
+ it 'returns variable with data' do
+ expect(entry.value_with_data).to eq(
+ 'VARIABLE_1' => { value: 'value', description: 'variable 1' }
+ )
+ end
+ end
+ end
+ end
+
+ context 'when entry config value has key-value pair and value is an array' do
+ let(:config) do
+ { 'VARIABLE_1' => { value: %w[value1 value2], description: 'variable 1' } }
+ end
+
+ context 'when there is no allowed_value_data metadata' do
+ it_behaves_like 'invalid config', /variable_1 config value must be an alphanumeric string/
+ end
+
+ context 'when metadata has allow_array_value and allowed_value_data' do
+ let(:metadata) { { allowed_value_data: %i[value description], allow_array_value: true } }
+
+ let(:result) do
+ { 'VARIABLE_1' => 'value1' }
+ end
+
+ it_behaves_like 'valid config'
+
+ describe '#value_with_data' do
+ it 'returns variable with data' do
+ expect(entry.value_with_data).to eq(
+ 'VARIABLE_1' => { value: 'value1', value_options: %w[value1 value2], description: 'variable 1' }
+ )
+ end
+ end
+ end
+ end
+
context 'when entry config value has key-value pair and hash' do
let(:config) do
{ 'VARIABLE_1' => { value: 'value 1', description: 'variable 1' },
diff --git a/spec/requests/api/graphql/ci/config_variables_spec.rb b/spec/requests/api/graphql/ci/config_variables_spec.rb
index 2b5a5d0dc931c9b0b1ed534c70a37923b9df542c..17133d7ea6605ae8a5e03e3921b64c2e6b74250d 100644
--- a/spec/requests/api/graphql/ci/config_variables_spec.rb
+++ b/spec/requests/api/graphql/ci/config_variables_spec.rb
@@ -23,6 +23,7 @@
ciConfigVariables(sha: "#{sha}") {
key
value
+ valueOptions
description
}
}
@@ -52,14 +53,22 @@
post_graphql(query, current_user: user)
expect(graphql_data.dig('project', 'ciConfigVariables')).to contain_exactly(
+ {
+ 'key' => 'KEY_VALUE_VAR',
+ 'value' => 'value x',
+ 'valueOptions' => nil,
+ 'description' => 'value of KEY_VALUE_VAR'
+ },
{
'key' => 'DB_NAME',
'value' => 'postgres',
+ 'valueOptions' => nil,
'description' => nil
},
{
'key' => 'ENVIRONMENT_VAR',
'value' => 'env var value',
+ 'valueOptions' => ['env var value', 'env var value2'],
'description' => 'env var description'
}
)
diff --git a/spec/support/gitlab_stubs/gitlab_ci.yml b/spec/support/gitlab_stubs/gitlab_ci.yml
index b6a66cfa2c62f1cf118d1fde7093d49b19e82abe..945235917654b3d1276e743318e78db054eef723 100644
--- a/spec/support/gitlab_stubs/gitlab_ci.yml
+++ b/spec/support/gitlab_stubs/gitlab_ci.yml
@@ -7,9 +7,12 @@ before_script:
- bundle exec rake db:create
variables:
+ KEY_VALUE_VAR:
+ value: 'value x'
+ description: 'value of KEY_VALUE_VAR'
DB_NAME: postgres
ENVIRONMENT_VAR:
- value: 'env var value'
+ value: ['env var value', 'env var value2']
description: 'env var description'
stages: