Commit b95ac654 authored by Grzegorz Bizon's avatar Grzegorz Bizon

Merge branch 'allow-to-disable-defaults' into 'master'

Allow to disable defaults

See merge request gitlab-org/gitlab!25690
parents 8ead1a0c d62e0687
---
title: Allow to disable inheritance of default job settings
merge_request: 25690
author:
type: added
...@@ -158,6 +158,42 @@ rspec 2.6: ...@@ -158,6 +158,42 @@ rspec 2.6:
script: bundle exec rspec script: bundle exec rspec
``` ```
### `inherit`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/207484) in GitLab 12.9.
You can disable inheritance of globally defined defaults
and variables with the `inherit:` parameter.
In the example below:
- `rubocop` **will** inherit both the `before_script` and the variable `DOMAIN`.
- `rspec` **will not** inherit the `before_script` or the variable `DOMAIN`.
- `capybara` **will** inherit the `before_script`, but **will not** inherit the variable `DOMAIN`.
```yaml
default:
before_script:
- echo Hello World
variables:
DOMAIN: example.com
rubocop:
script: bundle exec rubocop
rspec:
inherit:
default: false
variables: false
script: bundle exec rspec
capybara:
inherit:
variables: false
script: bundle exec capybara
```
## Parameter details ## Parameter details
The following are detailed explanations for parameters used to configure CI/CD pipelines. The following are detailed explanations for parameters used to configure CI/CD pipelines.
......
...@@ -47,6 +47,7 @@ describe Gitlab::Ci::Config::Entry::Bridge do ...@@ -47,6 +47,7 @@ describe Gitlab::Ci::Config::Entry::Bridge do
ignore: false, ignore: false,
stage: 'test', stage: 'test',
only: { refs: %w[branches tags] }, only: { refs: %w[branches tags] },
variables: {},
scheduling_type: :stage) scheduling_type: :stage)
end end
end end
...@@ -67,6 +68,7 @@ describe Gitlab::Ci::Config::Entry::Bridge do ...@@ -67,6 +68,7 @@ describe Gitlab::Ci::Config::Entry::Bridge do
ignore: false, ignore: false,
stage: 'test', stage: 'test',
only: { refs: %w[branches tags] }, only: { refs: %w[branches tags] },
variables: {},
scheduling_type: :dag) scheduling_type: :dag)
end end
end end
......
...@@ -11,7 +11,7 @@ module Gitlab ...@@ -11,7 +11,7 @@ module Gitlab
class Bridge < ::Gitlab::Config::Entry::Node class Bridge < ::Gitlab::Config::Entry::Node
include ::Gitlab::Ci::Config::Entry::Processable include ::Gitlab::Ci::Config::Entry::Processable
ALLOWED_KEYS = %i[trigger allow_failure when variables needs].freeze ALLOWED_KEYS = %i[trigger allow_failure when needs].freeze
validations do validations do
validates :config, allowed_keys: ALLOWED_KEYS + PROCESSABLE_ALLOWED_KEYS validates :config, allowed_keys: ALLOWED_KEYS + PROCESSABLE_ALLOWED_KEYS
...@@ -45,10 +45,6 @@ module Gitlab ...@@ -45,10 +45,6 @@ module Gitlab
inherit: false, inherit: false,
metadata: { allowed_needs: %i[job bridge] } metadata: { allowed_needs: %i[job bridge] }
entry :variables, ::Gitlab::Ci::Config::Entry::Variables,
description: 'Environment variables available for this job.',
inherit: false
attributes :when, :allow_failure attributes :when, :allow_failure
def self.matching?(name, config) def self.matching?(name, config)
...@@ -67,7 +63,6 @@ module Gitlab ...@@ -67,7 +63,6 @@ module Gitlab
needs: (needs_value if needs_defined?), needs: (needs_value if needs_defined?),
ignore: !!allow_failure, ignore: !!allow_failure,
when: self.when, when: self.when,
variables: (variables_value if variables_defined?),
scheduling_type: needs_defined? && !bridge_needs ? :dag : :stage scheduling_type: needs_defined? && !bridge_needs ? :dag : :stage
).compact ).compact
end end
......
# frozen_string_literal: true
module Gitlab
module Ci
class Config
module Entry
##
# This class represents a inherit entry
#
class Inherit < ::Gitlab::Config::Entry::Node
include ::Gitlab::Config::Entry::Configurable
ALLOWED_KEYS = %i[default variables].freeze
validations do
validates :config, allowed_keys: ALLOWED_KEYS
end
entry :default, ::Gitlab::Config::Entry::Boolean,
description: 'Indicates whether to inherit `default:`.',
default: true
entry :variables, ::Gitlab::Config::Entry::Boolean,
description: 'Indicates whether to inherit `variables:`.',
default: true
end
end
end
end
end
...@@ -13,7 +13,7 @@ module Gitlab ...@@ -13,7 +13,7 @@ module Gitlab
ALLOWED_WHEN = %w[on_success on_failure always manual delayed].freeze ALLOWED_WHEN = %w[on_success on_failure always manual delayed].freeze
ALLOWED_KEYS = %i[tags script type image services ALLOWED_KEYS = %i[tags script type image services
allow_failure type when start_in artifacts cache allow_failure type when start_in artifacts cache
dependencies before_script needs after_script variables dependencies before_script needs after_script
environment coverage retry parallel interruptible timeout environment coverage retry parallel interruptible timeout
resource_group release].freeze resource_group release].freeze
...@@ -112,10 +112,6 @@ module Gitlab ...@@ -112,10 +112,6 @@ module Gitlab
metadata: { allowed_needs: %i[job cross_dependency] }, metadata: { allowed_needs: %i[job cross_dependency] },
inherit: false inherit: false
entry :variables, Entry::Variables,
description: 'Environment variables available for this job.',
inherit: false
entry :environment, Entry::Environment, entry :environment, Entry::Environment,
description: 'Environment configuration for this job.', description: 'Environment configuration for this job.',
inherit: false inherit: false
...@@ -174,7 +170,6 @@ module Gitlab ...@@ -174,7 +170,6 @@ module Gitlab
when: self.when, when: self.when,
start_in: self.start_in, start_in: self.start_in,
dependencies: dependencies, dependencies: dependencies,
variables: variables_defined? ? variables_value : {},
environment: environment_defined? ? environment_value : nil, environment: environment_defined? ? environment_value : nil,
environment_name: environment_defined? ? environment_value[:name] : nil, environment_name: environment_defined? ? environment_value[:name] : nil,
coverage: coverage_defined? ? coverage_value : nil, coverage: coverage_defined? ? coverage_value : nil,
......
...@@ -14,7 +14,7 @@ module Gitlab ...@@ -14,7 +14,7 @@ module Gitlab
include ::Gitlab::Config::Entry::Attributable include ::Gitlab::Config::Entry::Attributable
include ::Gitlab::Config::Entry::Inheritable include ::Gitlab::Config::Entry::Inheritable
PROCESSABLE_ALLOWED_KEYS = %i[extends stage only except rules].freeze PROCESSABLE_ALLOWED_KEYS = %i[extends stage only except rules variables inherit].freeze
included do included do
validations do validations do
...@@ -54,12 +54,21 @@ module Gitlab ...@@ -54,12 +54,21 @@ module Gitlab
allowed_when: %w[on_success on_failure always never manual delayed].freeze allowed_when: %w[on_success on_failure always never manual delayed].freeze
} }
entry :variables, ::Gitlab::Ci::Config::Entry::Variables,
description: 'Environment variables available for this job.',
inherit: false
entry :inherit, ::Gitlab::Ci::Config::Entry::Inherit,
description: 'Indicates whether to inherit defaults or not.',
inherit: false,
default: {}
attributes :extends, :rules attributes :extends, :rules
end end
def compose!(deps = nil) def compose!(deps = nil)
super do super do
has_workflow_rules = deps&.workflow&.has_rules? has_workflow_rules = deps&.workflow_entry&.has_rules?
# If workflow:rules: or rules: are used # If workflow:rules: or rules: are used
# they are considered not compatible # they are considered not compatible
...@@ -73,6 +82,9 @@ module Gitlab ...@@ -73,6 +82,9 @@ module Gitlab
@entries.delete(:except) unless except_defined? # rubocop:disable Gitlab/ModuleWithInstanceVariables @entries.delete(:except) unless except_defined? # rubocop:disable Gitlab/ModuleWithInstanceVariables
end end
# inherit root variables
@root_variables_value = deps&.variables_value # rubocop:disable Gitlab/ModuleWithInstanceVariables
yield if block_given? yield if block_given?
end end
end end
...@@ -82,7 +94,10 @@ module Gitlab ...@@ -82,7 +94,10 @@ module Gitlab
end end
def overwrite_entry(deps, key, current_entry) def overwrite_entry(deps, key, current_entry)
deps.default[key] unless current_entry.specified? return unless inherit_entry&.default_value
return unless deps.default_entry
deps.default_entry[key] unless current_entry.specified?
end end
def value def value
...@@ -90,9 +105,18 @@ module Gitlab ...@@ -90,9 +105,18 @@ module Gitlab
stage: stage_value, stage: stage_value,
extends: extends, extends: extends,
rules: rules_value, rules: rules_value,
variables: root_and_job_variables_value,
only: only_value, only: only_value,
except: except_value }.compact except: except_value }.compact
end end
def root_and_job_variables_value
if inherit_entry&.variables_value
@root_variables_value.to_h.merge(variables_value.to_h) # rubocop:disable Gitlab/ModuleWithInstanceVariables
else
variables_value.to_h
end
end
end end
end end
end end
......
...@@ -65,7 +65,8 @@ module Gitlab ...@@ -65,7 +65,8 @@ module Gitlab
reserved: true reserved: true
entry :workflow, Entry::Workflow, entry :workflow, Entry::Workflow,
description: 'List of evaluable rules to determine Pipeline status' description: 'List of evaluable rules to determine Pipeline status',
default: {}
dynamic_helpers :jobs dynamic_helpers :jobs
...@@ -73,7 +74,7 @@ module Gitlab ...@@ -73,7 +74,7 @@ module Gitlab
:image_value, :image_value,
:services_value, :services_value,
:after_script_value, :after_script_value,
:cache_value, to: :default :cache_value, to: :default_entry
attr_reader :jobs_config attr_reader :jobs_config
...@@ -102,14 +103,6 @@ module Gitlab ...@@ -102,14 +103,6 @@ module Gitlab
end end
end end
def default
self[:default]
end
def workflow
self[:workflow] if workflow_defined?
end
private private
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
......
...@@ -12,7 +12,6 @@ module Gitlab ...@@ -12,7 +12,6 @@ module Gitlab
validations do validations do
validates :config, type: Hash validates :config, type: Hash
validates :config, allowed_keys: ALLOWED_KEYS validates :config, allowed_keys: ALLOWED_KEYS
validates :config, presence: true
end end
entry :rules, Entry::Rules, entry :rules, Entry::Rules,
......
...@@ -57,7 +57,7 @@ module Gitlab ...@@ -57,7 +57,7 @@ module Gitlab
when: job[:when] || 'on_success', when: job[:when] || 'on_success',
environment: job[:environment_name], environment: job[:environment_name],
coverage_regex: job[:coverage], coverage_regex: job[:coverage],
yaml_variables: transform_to_yaml_variables(job_variables(name)), yaml_variables: transform_to_yaml_variables(job[:variables]),
needs_attributes: job.dig(:needs, :job), needs_attributes: job.dig(:needs, :job),
interruptible: job[:interruptible], interruptible: job[:interruptible],
only: job[:only], only: job[:only],
...@@ -146,13 +146,6 @@ module Gitlab ...@@ -146,13 +146,6 @@ module Gitlab
end end
end end
def job_variables(name)
job_variables = @jobs.dig(name.to_sym, :variables)
@variables.to_h
.merge(job_variables.to_h)
end
def transform_to_yaml_variables(variables) def transform_to_yaml_variables(variables)
variables.to_h.map do |key, value| variables.to_h.map do |key, value|
{ key: key.to_s, value: value, public: true } { key: key.to_s, value: value, public: true }
......
...@@ -10,7 +10,7 @@ module Gitlab ...@@ -10,7 +10,7 @@ module Gitlab
def attributes(*attributes) def attributes(*attributes)
attributes.flatten.each do |attribute| attributes.flatten.each do |attribute|
if method_defined?(attribute) if method_defined?(attribute)
raise ArgumentError, "Method already defined: #{attribute}" raise ArgumentError, "Method '#{attribute}' already defined in '#{name}'"
end end
define_method(attribute) do define_method(attribute) do
......
...@@ -76,7 +76,7 @@ module Gitlab ...@@ -76,7 +76,7 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def entry(key, entry, description: nil, default: nil, inherit: nil, reserved: nil, metadata: {}) def entry(key, entry, description: nil, default: nil, inherit: nil, reserved: nil, metadata: {})
entry_name = key.to_sym entry_name = key.to_sym
raise ArgumentError, "Entry #{key} already defined" if @nodes.to_h[entry_name] raise ArgumentError, "Entry '#{key}' already defined in '#{name}'" if @nodes.to_h[entry_name]
factory = ::Gitlab::Config::Entry::Factory.new(entry) factory = ::Gitlab::Config::Entry::Factory.new(entry)
.with(description: description) .with(description: description)
...@@ -98,8 +98,8 @@ module Gitlab ...@@ -98,8 +98,8 @@ module Gitlab
def helpers(*nodes, dynamic: false) def helpers(*nodes, dynamic: false)
nodes.each do |symbol| nodes.each do |symbol|
if method_defined?("#{symbol}_defined?") || method_defined?("#{symbol}_value") if method_defined?("#{symbol}_defined?") || method_defined?("#{symbol}_entry") || method_defined?("#{symbol}_value")
raise ArgumentError, "Method #{symbol}_defined? or #{symbol}_value already defined" raise ArgumentError, "Method '#{symbol}_defined?', '#{symbol}_entry' or '#{symbol}_value' already defined in '#{name}'"
end end
unless @nodes.to_h[symbol] unless @nodes.to_h[symbol]
...@@ -110,10 +110,13 @@ module Gitlab ...@@ -110,10 +110,13 @@ module Gitlab
entries[symbol]&.specified? entries[symbol]&.specified?
end end
define_method("#{symbol}_value") do define_method("#{symbol}_entry") do
return unless entries[symbol] && entries[symbol].valid? entries[symbol]
end
entries[symbol].value define_method("#{symbol}_value") do
entry = entries[symbol]
entry.value if entry&.valid?
end end
end end
end end
......
...@@ -106,6 +106,7 @@ describe Gitlab::Ci::Config::Entry::Bridge do ...@@ -106,6 +106,7 @@ describe Gitlab::Ci::Config::Entry::Bridge do
ignore: false, ignore: false,
stage: 'test', stage: 'test',
only: { refs: %w[branches tags] }, only: { refs: %w[branches tags] },
variables: {},
scheduling_type: :stage) scheduling_type: :stage)
end end
end end
...@@ -128,6 +129,7 @@ describe Gitlab::Ci::Config::Entry::Bridge do ...@@ -128,6 +129,7 @@ describe Gitlab::Ci::Config::Entry::Bridge do
ignore: false, ignore: false,
stage: 'test', stage: 'test',
only: { refs: %w[branches tags] }, only: { refs: %w[branches tags] },
variables: {},
scheduling_type: :stage) scheduling_type: :stage)
end end
end end
......
...@@ -6,6 +6,7 @@ describe Gitlab::Ci::Config::Entry::Job do ...@@ -6,6 +6,7 @@ describe Gitlab::Ci::Config::Entry::Job do
let(:entry) { described_class.new(config, name: :rspec) } let(:entry) { described_class.new(config, name: :rspec) }
it_behaves_like 'with inheritable CI config' do it_behaves_like 'with inheritable CI config' do
let(:config) { { script: 'echo' } }
let(:inheritable_key) { 'default' } let(:inheritable_key) { 'default' }
let(:inheritable_class) { Gitlab::Ci::Config::Entry::Default } let(:inheritable_class) { Gitlab::Ci::Config::Entry::Default }
...@@ -15,6 +16,10 @@ describe Gitlab::Ci::Config::Entry::Job do ...@@ -15,6 +16,10 @@ describe Gitlab::Ci::Config::Entry::Job do
let(:ignored_inheritable_columns) do let(:ignored_inheritable_columns) do
%i[] %i[]
end end
before do
allow(entry).to receive_message_chain(:inherit_entry, :default_value).and_return(true)
end
end end
describe '.nodes' do describe '.nodes' do
...@@ -24,7 +29,8 @@ describe Gitlab::Ci::Config::Entry::Job do ...@@ -24,7 +29,8 @@ describe Gitlab::Ci::Config::Entry::Job do
let(:result) do let(:result) do
%i[before_script script stage type after_script cache %i[before_script script stage type after_script cache
image services only except rules needs variables artifacts image services only except rules needs variables artifacts
environment coverage retry interruptible timeout release tags] environment coverage retry interruptible timeout release tags
inherit]
end end
it { is_expected.to match_array result } it { is_expected.to match_array result }
...@@ -500,7 +506,13 @@ describe Gitlab::Ci::Config::Entry::Job do ...@@ -500,7 +506,13 @@ describe Gitlab::Ci::Config::Entry::Job do
let(:unspecified) { double('unspecified', 'specified?' => false) } let(:unspecified) { double('unspecified', 'specified?' => false) }
let(:default) { double('default', '[]' => unspecified) } let(:default) { double('default', '[]' => unspecified) }
let(:workflow) { double('workflow', 'has_rules?' => false) } let(:workflow) { double('workflow', 'has_rules?' => false) }
let(:deps) { double('deps', 'default' => default, '[]' => unspecified, 'workflow' => workflow) }
let(:deps) do
double('deps',
'default_entry' => default,
'workflow_entry' => workflow,
'variables_value' => nil)
end
context 'when job config overrides default config' do context 'when job config overrides default config' do
before do before do
......
...@@ -99,6 +99,7 @@ describe Gitlab::Ci::Config::Entry::Jobs do ...@@ -99,6 +99,7 @@ describe Gitlab::Ci::Config::Entry::Jobs do
only: { refs: %w[branches tags] }, only: { refs: %w[branches tags] },
stage: 'test', stage: 'test',
trigger: { project: 'my/project' }, trigger: { project: 'my/project' },
variables: {},
scheduling_type: :stage scheduling_type: :stage
}, },
regular_job: { regular_job: {
......
...@@ -7,6 +7,10 @@ describe Gitlab::Ci::Config::Entry::Processable do ...@@ -7,6 +7,10 @@ describe Gitlab::Ci::Config::Entry::Processable do
Class.new(::Gitlab::Config::Entry::Node) do Class.new(::Gitlab::Config::Entry::Node) do
include Gitlab::Ci::Config::Entry::Processable include Gitlab::Ci::Config::Entry::Processable
entry :tags, ::Gitlab::Config::Entry::ArrayOfStrings,
description: 'Set the default tags.',
inherit: true
def self.name def self.name
'job' 'job'
end end
...@@ -189,14 +193,17 @@ describe Gitlab::Ci::Config::Entry::Processable do ...@@ -189,14 +193,17 @@ describe Gitlab::Ci::Config::Entry::Processable do
end end
describe '#compose!' do describe '#compose!' do
let(:specified) do
double('specified', 'specified?' => true, value: 'specified')
end
let(:unspecified) { double('unspecified', 'specified?' => false) } let(:unspecified) { double('unspecified', 'specified?' => false) }
let(:default) { double('default', '[]' => unspecified) } let(:default) { double('default', '[]' => unspecified) }
let(:workflow) { double('workflow', 'has_rules?' => false) } let(:workflow) { double('workflow', 'has_rules?' => false) }
let(:deps) { double('deps', 'default' => default, '[]' => unspecified, 'workflow' => workflow) } let(:variables) { }
let(:deps) do
double('deps',
default_entry: default,
workflow_entry: workflow,
variables_value: variables)
end
context 'with workflow rules' do context 'with workflow rules' do
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
...@@ -240,6 +247,84 @@ describe Gitlab::Ci::Config::Entry::Processable do ...@@ -240,6 +247,84 @@ describe Gitlab::Ci::Config::Entry::Processable do
end end
end end
end end
context 'with inheritance' do
context 'of variables' do
let(:config) do
{ variables: { A: 'job', B: 'job' } }
end
before do
entry.compose!(deps)
end
context 'with only job variables' do
it 'does return defined variables' do
expect(entry.value).to include(
variables: { 'A' => 'job', 'B' => 'job' }
)
end
end
context 'when root yaml variables are used' do
let(:variables) do
Gitlab::Ci::Config::Entry::Variables.new(
A: 'root', C: 'root'
).value
end
it 'does return all variables and overwrite them' do
expect(entry.value).to include(
variables: { 'A' => 'job', 'B' => 'job', 'C' => 'root' }
)
end
context 'when inherit of defaults is disabled' do
let(:config) do
{
variables: { A: 'job', B: 'job' },
inherit: { variables: false }
}
end
it 'does return only job variables' do
expect(entry.value).to include(
variables: { 'A' => 'job', 'B' => 'job' }
)
end
end
end
end
context 'of default:tags' do
using RSpec::Parameterized::TableSyntax
where(:default_tags, :tags, :inherit_default, :result) do
nil | %w[a b] | nil | %w[a b]
nil | %w[a b] | true | %w[a b]
nil | %w[a b] | false | %w[a b]
%w[b c] | %w[a b] | nil | %w[a b]
%w[b c] | %w[a b] | true | %w[a b]
%w[b c] | %w[a b] | false | %w[a b]
%w[b c] | nil | nil | %w[b c]
%w[b c] | nil | true | %w[b c]
%w[b c] | nil | false | nil
end
with_them do
let(:config) { { tags: tags, inherit: { default: inherit_default } } }
let(:default_specified_tags) { double('tags', 'specified?' => true, 'valid?' => true, 'value' => default_tags) }
before do
allow(default).to receive('[]').with(:tags).and_return(default_specified_tags)
entry.compose!(deps)
end
it { expect(entry.tags_value).to eq(result) }
end
end
end
end end
context 'when composed' do context 'when composed' do
...@@ -254,10 +339,12 @@ describe Gitlab::Ci::Config::Entry::Processable do ...@@ -254,10 +339,12 @@ describe Gitlab::Ci::Config::Entry::Processable do
end end
it 'returns correct value' do it 'returns correct value' do
expect(entry.value) expect(entry.value).to eq(
.to eq(name: :rspec, name: :rspec,
stage: 'test', stage: 'test',
only: { refs: %w[branches tags] }) only: { refs: %w[branches tags] },
variables: {}
)
end end
end end
end end
......
...@@ -32,7 +32,7 @@ describe Gitlab::Ci::Config::Entry::Root do ...@@ -32,7 +32,7 @@ describe Gitlab::Ci::Config::Entry::Root do
image: 'ruby:2.2', image: 'ruby:2.2',
default: {}, default: {},
services: ['postgres:9.1', 'mysql:5.5'], services: ['postgres:9.1', 'mysql:5.5'],
variables: { VAR: 'value' }, variables: { VAR: 'root' },
after_script: ['make clean'], after_script: ['make clean'],
stages: %w(build pages release), stages: %w(build pages release),
cache: { key: 'k', untracked: true, paths: ['public/'] }, cache: { key: 'k', untracked: true, paths: ['public/'] },
...@@ -42,6 +42,7 @@ describe Gitlab::Ci::Config::Entry::Root do ...@@ -42,6 +42,7 @@ describe Gitlab::Ci::Config::Entry::Root do
stage: 'release', stage: 'release',
before_script: [], before_script: [],
after_script: [], after_script: [],
variables: { 'VAR' => 'job' },
script: ["make changelog | tee release_changelog.txt"], script: ["make changelog | tee release_changelog.txt"],
release: { release: {
tag_name: 'v0.06', tag_name: 'v0.06',
...@@ -127,7 +128,7 @@ describe Gitlab::Ci::Config::Entry::Root do ...@@ -127,7 +128,7 @@ describe Gitlab::Ci::Config::Entry::Root do
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }], services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test', stage: 'test',
cache: { key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push' }, cache: { key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push' },
variables: {}, variables: { 'VAR' => 'root' },
ignore: false, ignore: false,
after_script: ['make clean'], after_script: ['make clean'],
only: { refs: %w[branches tags] }, only: { refs: %w[branches tags] },
...@@ -141,7 +142,7 @@ describe Gitlab::Ci::Config::Entry::Root do ...@@ -141,7 +142,7 @@ describe Gitlab::Ci::Config::Entry::Root do
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }], services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test', stage: 'test',
cache: { key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push' }, cache: { key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push' },
variables: {}, variables: { 'VAR' => 'root' },
ignore: false, ignore: false,
after_script: ['make clean'], after_script: ['make clean'],
only: { refs: %w[branches tags] }, only: { refs: %w[branches tags] },
...@@ -157,7 +158,7 @@ describe Gitlab::Ci::Config::Entry::Root do ...@@ -157,7 +158,7 @@ describe Gitlab::Ci::Config::Entry::Root do
services: [{ name: "postgres:9.1" }, { name: "mysql:5.5" }], services: [{ name: "postgres:9.1" }, { name: "mysql:5.5" }],
cache: { key: "k", untracked: true, paths: ["public/"], policy: "pull-push" }, cache: { key: "k", untracked: true, paths: ["public/"], policy: "pull-push" },
only: { refs: %w(branches tags) }, only: { refs: %w(branches tags) },
variables: {}, variables: { 'VAR' => 'job' },
after_script: [], after_script: [],
ignore: false, ignore: false,
scheduling_type: :stage } scheduling_type: :stage }
...@@ -175,11 +176,11 @@ describe Gitlab::Ci::Config::Entry::Root do ...@@ -175,11 +176,11 @@ describe Gitlab::Ci::Config::Entry::Root do
image: 'ruby:2.1', image: 'ruby:2.1',
services: ['postgres:9.1', 'mysql:5.5'] services: ['postgres:9.1', 'mysql:5.5']
}, },
variables: { VAR: 'value' }, variables: { VAR: 'root' },
stages: %w(build pages), stages: %w(build pages),
cache: { key: 'k', untracked: true, paths: ['public/'] }, cache: { key: 'k', untracked: true, paths: ['public/'] },
rspec: { script: %w[rspec ls] }, rspec: { script: %w[rspec ls] },
spinach: { before_script: [], variables: { VAR: 'AA' }, script: 'spinach' } } spinach: { before_script: [], variables: { VAR: 'job' }, script: 'spinach' } }
end end
context 'when composed' do context 'when composed' do
...@@ -203,7 +204,7 @@ describe Gitlab::Ci::Config::Entry::Root do ...@@ -203,7 +204,7 @@ describe Gitlab::Ci::Config::Entry::Root do
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }], services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test', stage: 'test',
cache: { key: 'k', untracked: true, paths: ['public/'], policy: "pull-push" }, cache: { key: 'k', untracked: true, paths: ['public/'], policy: "pull-push" },
variables: {}, variables: { 'VAR' => 'root' },
ignore: false, ignore: false,
after_script: ['make clean'], after_script: ['make clean'],
only: { refs: %w[branches tags] }, only: { refs: %w[branches tags] },
...@@ -215,7 +216,7 @@ describe Gitlab::Ci::Config::Entry::Root do ...@@ -215,7 +216,7 @@ describe Gitlab::Ci::Config::Entry::Root do
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }], services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test', stage: 'test',
cache: { key: 'k', untracked: true, paths: ['public/'], policy: "pull-push" }, cache: { key: 'k', untracked: true, paths: ['public/'], policy: "pull-push" },
variables: { 'VAR' => 'AA' }, variables: { 'VAR' => 'job' },
ignore: false, ignore: false,
after_script: ['make clean'], after_script: ['make clean'],
only: { refs: %w[branches tags] }, only: { refs: %w[branches tags] },
......
...@@ -509,28 +509,44 @@ module Gitlab ...@@ -509,28 +509,44 @@ module Gitlab
describe "before_script" do describe "before_script" do
context "in global context" do context "in global context" do
using RSpec::Parameterized::TableSyntax
where(:inherit, :result) do
nil | ["global script"]
{ default: false } | nil
{ default: true } | ["global script"]
end
with_them do
let(:config) do let(:config) do
{ {
before_script: ["global script"], before_script: ["global script"],
test: { script: ["script"] } test: { script: ["script"], inherit: inherit }
} }
end end
it "return commands with scripts concatenated" do it { expect(subject[:options][:before_script]).to eq(result) }
expect(subject[:options][:before_script]).to eq(["global script"])
end end
end end
context "in default context" do context "in default context" do
using RSpec::Parameterized::TableSyntax
where(:inherit, :result) do
nil | ["global script"]
{ default: false } | nil
{ default: true } | ["global script"]
end
with_them do
let(:config) do let(:config) do
{ {
default: { before_script: ["global script"] }, default: { before_script: ["global script"] },
test: { script: ["script"] } test: { script: ["script"], inherit: inherit }
} }
end end
it "return commands with scripts concatenated" do it { expect(subject[:options][:before_script]).to eq(result) }
expect(subject[:options][:before_script]).to eq(["global script"])
end end
end end
...@@ -793,7 +809,7 @@ module Gitlab ...@@ -793,7 +809,7 @@ module Gitlab
context 'when job and global variables are defined' do context 'when job and global variables are defined' do
let(:global_variables) do let(:global_variables) do
{ 'VAR1' => 'global1', 'VAR3' => 'global3' } { 'VAR1' => 'global1', 'VAR3' => 'global3', 'VAR4' => 'global4' }
end end
let(:job_variables) do let(:job_variables) do
{ 'VAR1' => 'value1', 'VAR2' => 'value2' } { 'VAR1' => 'value1', 'VAR2' => 'value2' }
...@@ -802,12 +818,16 @@ module Gitlab ...@@ -802,12 +818,16 @@ module Gitlab
{ {
before_script: ['pwd'], before_script: ['pwd'],
variables: global_variables, variables: global_variables,
rspec: { script: 'rspec', variables: job_variables } rspec: { script: 'rspec', variables: job_variables, inherit: inherit }
} }
end end
context 'when no inheritance is specified' do
let(:inherit) { }
it 'returns all unique variables' do it 'returns all unique variables' do
expect(subject).to contain_exactly( expect(subject).to contain_exactly(
{ key: 'VAR4', value: 'global4', public: true },
{ key: 'VAR3', value: 'global3', public: true }, { key: 'VAR3', value: 'global3', public: true },
{ key: 'VAR1', value: 'value1', public: true }, { key: 'VAR1', value: 'value1', public: true },
{ key: 'VAR2', value: 'value2', public: true } { key: 'VAR2', value: 'value2', public: true }
...@@ -815,6 +835,18 @@ module Gitlab ...@@ -815,6 +835,18 @@ module Gitlab
end end
end end
context 'when inheritance is disabled' do
let(:inherit) { { variables: false } }
it 'does not inherit variables' do
expect(subject).to contain_exactly(
{ key: 'VAR1', value: 'value1', public: true },
{ key: 'VAR2', value: 'value2', public: true }
)
end
end
end
context 'when job variables are defined' do context 'when job variables are defined' do
let(:config) do let(:config) do
{ {
......
...@@ -59,7 +59,7 @@ describe Gitlab::Config::Entry::Attributable do ...@@ -59,7 +59,7 @@ describe Gitlab::Config::Entry::Attributable do
end end
end end
expectation.to raise_error(ArgumentError, 'Method already defined: length') expectation.to raise_error(ArgumentError, /Method 'length' already defined in/)
end end
end end
end end
...@@ -53,7 +53,7 @@ RSpec.shared_examples 'with inheritable CI config' do ...@@ -53,7 +53,7 @@ RSpec.shared_examples 'with inheritable CI config' do
let(:deps) do let(:deps) do
if inheritable_key if inheritable_key
double('deps', inheritable_key => inheritable, '[]' => unspecified) double('deps', "#{inheritable_key}_entry" => inheritable, '[]' => unspecified)
else else
inheritable inheritable
end end
...@@ -68,7 +68,7 @@ RSpec.shared_examples 'with inheritable CI config' do ...@@ -68,7 +68,7 @@ RSpec.shared_examples 'with inheritable CI config' do
it 'does inherit value' do it 'does inherit value' do
expect(inheritable).to receive('[]').with(entry_key).and_return(specified) expect(inheritable).to receive('[]').with(entry_key).and_return(specified)
entry.compose!(deps) entry.send(:inherit!, deps)
expect(entry[entry_key]).to eq(specified) expect(entry[entry_key]).to eq(specified)
end end
...@@ -86,7 +86,7 @@ RSpec.shared_examples 'with inheritable CI config' do ...@@ -86,7 +86,7 @@ RSpec.shared_examples 'with inheritable CI config' do
expect do expect do
# we ignore exceptions as `#overwrite_entry` # we ignore exceptions as `#overwrite_entry`
# can raise exception on duplicates # can raise exception on duplicates
entry.compose!(deps) rescue described_class::InheritError entry.send(:inherit!, deps) rescue described_class::InheritError
end.not_to change { entry[entry_key] } end.not_to change { entry[entry_key] }
end end
end end
...@@ -94,7 +94,7 @@ RSpec.shared_examples 'with inheritable CI config' do ...@@ -94,7 +94,7 @@ RSpec.shared_examples 'with inheritable CI config' do
context 'when inheritable does not specify' do context 'when inheritable does not specify' do
it 'does not inherit value' do it 'does not inherit value' do
entry.compose!(deps) entry.send(:inherit!, deps)
expect(entry[entry_key]).to be_a( expect(entry[entry_key]).to be_a(
Gitlab::Config::Entry::Undefined) Gitlab::Config::Entry::Undefined)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment