summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/ci/variables/builder_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/ci/variables/builder_spec.rb')
-rw-r--r--spec/lib/gitlab/ci/variables/builder_spec.rb362
1 files changed, 225 insertions, 137 deletions
diff --git a/spec/lib/gitlab/ci/variables/builder_spec.rb b/spec/lib/gitlab/ci/variables/builder_spec.rb
index 8552a06eab3..b9aa5f7c431 100644
--- a/spec/lib/gitlab/ci/variables/builder_spec.rb
+++ b/spec/lib/gitlab/ci/variables/builder_spec.rb
@@ -199,6 +199,20 @@ RSpec.describe Gitlab::Ci::Variables::Builder do
'O' => '15', 'P' => '15')
end
end
+
+ context 'with schedule variables' do
+ let_it_be(:schedule) { create(:ci_pipeline_schedule, project: project) }
+ let_it_be(:schedule_variable) { create(:ci_pipeline_schedule_variable, pipeline_schedule: schedule) }
+
+ before do
+ pipeline.update!(pipeline_schedule_id: schedule.id)
+ end
+
+ it 'includes schedule variables' do
+ expect(subject.to_runner_variables)
+ .to include(a_hash_including(key: schedule_variable.key, value: schedule_variable.value))
+ end
+ end
end
describe '#user_variables' do
@@ -278,6 +292,14 @@ RSpec.describe Gitlab::Ci::Variables::Builder do
end
shared_examples "secret CI variables" do
+ let(:protected_variable_item) do
+ Gitlab::Ci::Variables::Collection::Item.fabricate(protected_variable)
+ end
+
+ let(:unprotected_variable_item) do
+ Gitlab::Ci::Variables::Collection::Item.fabricate(unprotected_variable)
+ end
+
context 'when ref is branch' do
context 'when ref is protected' do
before do
@@ -338,189 +360,255 @@ RSpec.describe Gitlab::Ci::Variables::Builder do
let_it_be(:protected_variable) { create(:ci_instance_variable, protected: true) }
let_it_be(:unprotected_variable) { create(:ci_instance_variable, protected: false) }
- let(:protected_variable_item) { Gitlab::Ci::Variables::Collection::Item.fabricate(protected_variable) }
- let(:unprotected_variable_item) { Gitlab::Ci::Variables::Collection::Item.fabricate(unprotected_variable) }
-
include_examples "secret CI variables"
end
describe '#secret_group_variables' do
- subject { builder.secret_group_variables(ref: job.git_ref, environment: job.expanded_environment_name) }
+ subject { builder.secret_group_variables(environment: job.expanded_environment_name) }
let_it_be(:protected_variable) { create(:ci_group_variable, protected: true, group: group) }
let_it_be(:unprotected_variable) { create(:ci_group_variable, protected: false, group: group) }
- context 'with ci_variables_builder_memoize_secret_variables disabled' do
- before do
- stub_feature_flags(ci_variables_builder_memoize_secret_variables: false)
+ include_examples "secret CI variables"
+
+ context 'variables memoization' do
+ let_it_be(:scoped_variable) { create(:ci_group_variable, group: group, environment_scope: 'scoped') }
+
+ let(:environment) { job.expanded_environment_name }
+ let(:scoped_variable_item) { Gitlab::Ci::Variables::Collection::Item.fabricate(scoped_variable) }
+
+ context 'with protected environments' do
+ it 'memoizes the result by environment' do
+ expect(pipeline.project)
+ .to receive(:protected_for?)
+ .with(pipeline.jobs_git_ref)
+ .once.and_return(true)
+
+ expect_next_instance_of(described_class::Group) do |group_variables_builder|
+ expect(group_variables_builder)
+ .to receive(:secret_variables)
+ .with(environment: 'production', protected_ref: true)
+ .once
+ .and_call_original
+ end
+
+ 2.times do
+ expect(builder.secret_group_variables(environment: 'production'))
+ .to contain_exactly(unprotected_variable_item, protected_variable_item)
+ end
+ end
end
- let(:protected_variable_item) { protected_variable }
- let(:unprotected_variable_item) { unprotected_variable }
+ context 'with unprotected environments' do
+ it 'memoizes the result by environment' do
+ expect(pipeline.project)
+ .to receive(:protected_for?)
+ .with(pipeline.jobs_git_ref)
+ .once.and_return(false)
+
+ expect_next_instance_of(described_class::Group) do |group_variables_builder|
+ expect(group_variables_builder)
+ .to receive(:secret_variables)
+ .with(environment: nil, protected_ref: false)
+ .once
+ .and_call_original
+
+ expect(group_variables_builder)
+ .to receive(:secret_variables)
+ .with(environment: 'scoped', protected_ref: false)
+ .once
+ .and_call_original
+ end
+
+ 2.times do
+ expect(builder.secret_group_variables(environment: nil))
+ .to contain_exactly(unprotected_variable_item)
- include_examples "secret CI variables"
+ expect(builder.secret_group_variables(environment: 'scoped'))
+ .to contain_exactly(unprotected_variable_item, scoped_variable_item)
+ end
+ end
+ end
end
+ end
- context 'with ci_variables_builder_memoize_secret_variables enabled' do
- before do
- stub_feature_flags(ci_variables_builder_memoize_secret_variables: true)
- end
+ describe '#secret_project_variables' do
+ let_it_be(:protected_variable) { create(:ci_variable, protected: true, project: project) }
+ let_it_be(:unprotected_variable) { create(:ci_variable, protected: false, project: project) }
- let(:protected_variable_item) { Gitlab::Ci::Variables::Collection::Item.fabricate(protected_variable) }
- let(:unprotected_variable_item) { Gitlab::Ci::Variables::Collection::Item.fabricate(unprotected_variable) }
+ let(:environment) { job.expanded_environment_name }
- include_examples "secret CI variables"
+ subject { builder.secret_project_variables(environment: environment) }
- context 'variables memoization' do
- let_it_be(:scoped_variable) { create(:ci_group_variable, group: group, environment_scope: 'scoped') }
+ include_examples "secret CI variables"
- let(:ref) { job.git_ref }
- let(:environment) { job.expanded_environment_name }
- let(:scoped_variable_item) { Gitlab::Ci::Variables::Collection::Item.fabricate(scoped_variable) }
+ context 'variables memoization' do
+ let_it_be(:scoped_variable) { create(:ci_variable, project: project, environment_scope: 'scoped') }
- context 'with protected environments' do
- it 'memoizes the result by environment' do
- expect(pipeline.project)
- .to receive(:protected_for?)
- .with(pipeline.jobs_git_ref)
- .once.and_return(true)
+ let(:scoped_variable_item) { Gitlab::Ci::Variables::Collection::Item.fabricate(scoped_variable) }
- expect_next_instance_of(described_class::Group) do |group_variables_builder|
- expect(group_variables_builder)
- .to receive(:secret_variables)
- .with(environment: 'production', protected_ref: true)
- .once
- .and_call_original
- end
+ context 'with protected environments' do
+ it 'memoizes the result by environment' do
+ expect(pipeline.project)
+ .to receive(:protected_for?)
+ .with(pipeline.jobs_git_ref)
+ .once.and_return(true)
- 2.times do
- expect(builder.secret_group_variables(ref: ref, environment: 'production'))
- .to contain_exactly(unprotected_variable_item, protected_variable_item)
- end
+ expect_next_instance_of(described_class::Project) do |project_variables_builder|
+ expect(project_variables_builder)
+ .to receive(:secret_variables)
+ .with(environment: 'production', protected_ref: true)
+ .once
+ .and_call_original
+ end
+
+ 2.times do
+ expect(builder.secret_project_variables(environment: 'production'))
+ .to contain_exactly(unprotected_variable_item, protected_variable_item)
end
end
+ end
- context 'with unprotected environments' do
- it 'memoizes the result by environment' do
- expect(pipeline.project)
- .to receive(:protected_for?)
- .with(pipeline.jobs_git_ref)
- .once.and_return(false)
-
- expect_next_instance_of(described_class::Group) do |group_variables_builder|
- expect(group_variables_builder)
- .to receive(:secret_variables)
- .with(environment: nil, protected_ref: false)
- .once
- .and_call_original
-
- expect(group_variables_builder)
- .to receive(:secret_variables)
- .with(environment: 'scoped', protected_ref: false)
- .once
- .and_call_original
- end
-
- 2.times do
- expect(builder.secret_group_variables(ref: 'other', environment: nil))
- .to contain_exactly(unprotected_variable_item)
-
- expect(builder.secret_group_variables(ref: 'other', environment: 'scoped'))
- .to contain_exactly(unprotected_variable_item, scoped_variable_item)
- end
+ context 'with unprotected environments' do
+ it 'memoizes the result by environment' do
+ expect(pipeline.project)
+ .to receive(:protected_for?)
+ .with(pipeline.jobs_git_ref)
+ .once.and_return(false)
+
+ expect_next_instance_of(described_class::Project) do |project_variables_builder|
+ expect(project_variables_builder)
+ .to receive(:secret_variables)
+ .with(environment: nil, protected_ref: false)
+ .once
+ .and_call_original
+
+ expect(project_variables_builder)
+ .to receive(:secret_variables)
+ .with(environment: 'scoped', protected_ref: false)
+ .once
+ .and_call_original
+ end
+
+ 2.times do
+ expect(builder.secret_project_variables(environment: nil))
+ .to contain_exactly(unprotected_variable_item)
+
+ expect(builder.secret_project_variables(environment: 'scoped'))
+ .to contain_exactly(unprotected_variable_item, scoped_variable_item)
end
end
end
end
end
- describe '#secret_project_variables' do
- let_it_be(:protected_variable) { create(:ci_variable, protected: true, project: project) }
- let_it_be(:unprotected_variable) { create(:ci_variable, protected: false, project: project) }
+ describe '#config_variables' do
+ subject(:config_variables) { builder.config_variables }
- let(:ref) { job.git_ref }
- let(:environment) { job.expanded_environment_name }
+ context 'without project' do
+ before do
+ pipeline.update!(project_id: nil)
+ end
+
+ it { expect(config_variables.size).to eq(0) }
+ end
- subject { builder.secret_project_variables(ref: ref, environment: environment) }
+ context 'without repository' do
+ let(:project) { create(:project) }
+ let(:pipeline) { build(:ci_pipeline, ref: nil, sha: nil, project: project) }
- context 'with ci_variables_builder_memoize_secret_variables disabled' do
- before do
- stub_feature_flags(ci_variables_builder_memoize_secret_variables: false)
+ it { expect(config_variables['CI_COMMIT_SHA']).to be_nil }
+ end
+
+ context 'with protected variables' do
+ let_it_be(:instance_variable) do
+ create(:ci_instance_variable, :protected, key: 'instance_variable')
+ end
+
+ let_it_be(:group_variable) do
+ create(:ci_group_variable, :protected, group: group, key: 'group_variable')
end
- let(:protected_variable_item) { protected_variable }
- let(:unprotected_variable_item) { unprotected_variable }
+ let_it_be(:project_variable) do
+ create(:ci_variable, :protected, project: project, key: 'project_variable')
+ end
- include_examples "secret CI variables"
+ it 'does not include protected variables' do
+ expect(config_variables[instance_variable.key]).to be_nil
+ expect(config_variables[group_variable.key]).to be_nil
+ expect(config_variables[project_variable.key]).to be_nil
+ end
end
- context 'with ci_variables_builder_memoize_secret_variables enabled' do
- before do
- stub_feature_flags(ci_variables_builder_memoize_secret_variables: true)
+ context 'with scoped variables' do
+ let_it_be(:scoped_group_variable) do
+ create(:ci_group_variable,
+ group: group,
+ key: 'group_variable',
+ value: 'scoped',
+ environment_scope: 'scoped')
end
- let(:protected_variable_item) { Gitlab::Ci::Variables::Collection::Item.fabricate(protected_variable) }
- let(:unprotected_variable_item) { Gitlab::Ci::Variables::Collection::Item.fabricate(unprotected_variable) }
+ let_it_be(:group_variable) do
+ create(:ci_group_variable,
+ group: group,
+ key: 'group_variable',
+ value: 'unscoped')
+ end
- include_examples "secret CI variables"
+ let_it_be(:scoped_project_variable) do
+ create(:ci_variable,
+ project: project,
+ key: 'project_variable',
+ value: 'scoped',
+ environment_scope: 'scoped')
+ end
- context 'variables memoization' do
- let_it_be(:scoped_variable) { create(:ci_variable, project: project, environment_scope: 'scoped') }
+ let_it_be(:project_variable) do
+ create(:ci_variable,
+ project: project,
+ key: 'project_variable',
+ value: 'unscoped')
+ end
- let(:scoped_variable_item) { Gitlab::Ci::Variables::Collection::Item.fabricate(scoped_variable) }
+ it 'does not include scoped variables' do
+ expect(config_variables.to_hash[group_variable.key]).to eq('unscoped')
+ expect(config_variables.to_hash[project_variable.key]).to eq('unscoped')
+ end
+ end
- context 'with protected environments' do
- it 'memoizes the result by environment' do
- expect(pipeline.project)
- .to receive(:protected_for?)
- .with(pipeline.jobs_git_ref)
- .once.and_return(true)
+ context 'variables ordering' do
+ def var(name, value)
+ { key: name, value: value.to_s, public: true, masked: false }
+ end
- expect_next_instance_of(described_class::Project) do |project_variables_builder|
- expect(project_variables_builder)
- .to receive(:secret_variables)
- .with(environment: 'production', protected_ref: true)
- .once
- .and_call_original
- end
+ before do
+ allow(pipeline.project).to receive(:predefined_variables) { [var('A', 1), var('B', 1)] }
+ allow(pipeline).to receive(:predefined_variables) { [var('B', 2), var('C', 2)] }
+ allow(builder).to receive(:secret_instance_variables) { [var('C', 3), var('D', 3)] }
+ allow(builder).to receive(:secret_group_variables) { [var('D', 4), var('E', 4)] }
+ allow(builder).to receive(:secret_project_variables) { [var('E', 5), var('F', 5)] }
+ allow(pipeline).to receive(:variables) { [var('F', 6), var('G', 6)] }
+ allow(pipeline).to receive(:pipeline_schedule) { double(job_variables: [var('G', 7), var('H', 7)]) }
+ end
- 2.times do
- expect(builder.secret_project_variables(ref: ref, environment: 'production'))
- .to contain_exactly(unprotected_variable_item, protected_variable_item)
- end
- end
- end
+ it 'returns variables in order depending on resource hierarchy' do
+ expect(config_variables.to_runner_variables).to eq(
+ [var('A', 1), var('B', 1),
+ var('B', 2), var('C', 2),
+ var('C', 3), var('D', 3),
+ var('D', 4), var('E', 4),
+ var('E', 5), var('F', 5),
+ var('F', 6), var('G', 6),
+ var('G', 7), var('H', 7)])
+ end
- context 'with unprotected environments' do
- it 'memoizes the result by environment' do
- expect(pipeline.project)
- .to receive(:protected_for?)
- .with(pipeline.jobs_git_ref)
- .once.and_return(false)
-
- expect_next_instance_of(described_class::Project) do |project_variables_builder|
- expect(project_variables_builder)
- .to receive(:secret_variables)
- .with(environment: nil, protected_ref: false)
- .once
- .and_call_original
-
- expect(project_variables_builder)
- .to receive(:secret_variables)
- .with(environment: 'scoped', protected_ref: false)
- .once
- .and_call_original
- end
-
- 2.times do
- expect(builder.secret_project_variables(ref: 'other', environment: nil))
- .to contain_exactly(unprotected_variable_item)
-
- expect(builder.secret_project_variables(ref: 'other', environment: 'scoped'))
- .to contain_exactly(unprotected_variable_item, scoped_variable_item)
- end
- end
- end
+ it 'overrides duplicate keys depending on resource hierarchy' do
+ expect(config_variables.to_hash).to match(
+ 'A' => '1', 'B' => '2',
+ 'C' => '3', 'D' => '4',
+ 'E' => '5', 'F' => '6',
+ 'G' => '7', 'H' => '7')
end
end
end