diff options
Diffstat (limited to 'spec/tooling')
-rw-r--r-- | spec/tooling/danger/config_files_spec.rb | 30 | ||||
-rw-r--r-- | spec/tooling/danger/feature_flag_spec.rb | 70 | ||||
-rw-r--r-- | spec/tooling/danger/product_intelligence_spec.rb | 47 | ||||
-rw-r--r-- | spec/tooling/danger/project_helper_spec.rb | 10 | ||||
-rw-r--r-- | spec/tooling/danger/specs_spec.rb | 71 | ||||
-rw-r--r-- | spec/tooling/danger/stable_branch_spec.rb | 137 | ||||
-rw-r--r-- | spec/tooling/lib/tooling/helm3_client_spec.rb | 48 | ||||
-rw-r--r-- | spec/tooling/lib/tooling/kubernetes_client_spec.rb | 20 | ||||
-rw-r--r-- | spec/tooling/lib/tooling/mappings/base_spec.rb | 44 | ||||
-rw-r--r-- | spec/tooling/lib/tooling/mappings/js_to_system_specs_mappings_spec.rb | 169 | ||||
-rw-r--r-- | spec/tooling/lib/tooling/mappings/view_to_js_mappings_spec.rb (renamed from spec/tooling/lib/tooling/view_to_js_mappings_spec.rb) | 49 |
11 files changed, 518 insertions, 177 deletions
diff --git a/spec/tooling/danger/config_files_spec.rb b/spec/tooling/danger/config_files_spec.rb index 88b327df63f..65edcabb817 100644 --- a/spec/tooling/danger/config_files_spec.rb +++ b/spec/tooling/danger/config_files_spec.rb @@ -13,7 +13,6 @@ RSpec.describe Tooling::Danger::ConfigFiles do let(:fake_danger) { DangerSpecHelper.fake_danger.include(described_class) } let(:fake_project_helper) { instance_double(Tooling::Danger::ProjectHelper) } - let(:matching_line) { "+ introduced_by_url:" } subject(:config_file) { fake_danger.new(helper: fake_helper) } @@ -22,29 +21,42 @@ RSpec.describe Tooling::Danger::ConfigFiles do end describe '#add_suggestion_for_missing_introduced_by_url' do - let(:file_lines) do + let(:file_diff) do [ - "---", - "name: about_some_new_flow", - "introduced_by_url: #{url}", - "rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/355909", - "milestone: '14.10'" + "+---", + "+name: about_some_new_flow", + "+introduced_by_url: #{url}", + "+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/355909", + "+milestone: '14.10'" ] end + let(:file_lines) do + file_diff.map { |line| line.delete_prefix('+') } + end + let(:filename) { 'config/feature_flags/new_ff.yml' } + let(:mr_url) { 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1' } before do allow(config_file.project_helper).to receive(:file_lines).and_return(file_lines) allow(config_file.helper).to receive(:added_files).and_return([filename]) - allow(config_file.helper).to receive(:mr_web_url).and_return(url) + allow(config_file.helper).to receive(:changed_lines).with(filename).and_return(file_diff) + allow(config_file.helper).to receive(:mr_web_url).and_return(mr_url) end context 'when config file has an empty introduced_by_url line' do let(:url) { '' } it 'adds suggestions at the correct line' do - expected_format = format(described_class::SUGGEST_INTRODUCED_BY_COMMENT, url: url) + template = <<~SUGGEST_COMMENT + ```suggestion + introduced_by_url: %<mr_url>s + ``` + SUGGEST_COMMENT + + expected_format = format(template, mr_url: mr_url) + expect(config_file).to receive(:markdown).with(expected_format, file: filename, line: 3) config_file.add_suggestion_for_missing_introduced_by_url diff --git a/spec/tooling/danger/feature_flag_spec.rb b/spec/tooling/danger/feature_flag_spec.rb index 0e9eda54510..4575d8ca981 100644 --- a/spec/tooling/danger/feature_flag_spec.rb +++ b/spec/tooling/danger/feature_flag_spec.rb @@ -86,14 +86,20 @@ RSpec.describe Tooling::Danger::FeatureFlag do describe described_class::Found do let(:feature_flag_path) { 'config/feature_flags/development/entry.yml' } let(:group) { 'group::source code' } - let(:raw_yaml) do - YAML.dump( + let(:yaml) do + { 'group' => group, 'default_enabled' => true, - 'rollout_issue_url' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/1' - ) + 'rollout_issue_url' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/1', + 'introduced_by_url' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/2', + 'milestone' => '15.9', + 'type' => 'development', + 'name' => 'entry' + } end + let(:raw_yaml) { YAML.dump(yaml) } + subject(:found) { described_class.new(feature_flag_path) } before do @@ -101,58 +107,34 @@ RSpec.describe Tooling::Danger::FeatureFlag do expect(File).to receive(:read).with(feature_flag_path).and_return(raw_yaml) end - describe '#raw' do - it 'returns the raw YAML' do - expect(found.raw).to eq(raw_yaml) - end - end - - describe '#group' do - it 'returns the group found in the YAML' do - expect(found.group).to eq(group) - end - end - - describe '#default_enabled' do - it 'returns the default_enabled found in the YAML' do - expect(found.default_enabled).to eq(true) + described_class::ATTRIBUTES.each do |attribute| + describe "##{attribute}" do + it 'returns value from the YAML' do + expect(found.public_send(attribute)).to eq(yaml[attribute]) + end end end - describe '#rollout_issue_url' do - it 'returns the rollout_issue_url found in the YAML' do - expect(found.rollout_issue_url).to eq('https://gitlab.com/gitlab-org/gitlab/-/issues/1') + describe '#raw' do + it 'returns the raw YAML' do + expect(found.raw).to eq(raw_yaml) end end describe '#group_match_mr_label?' do - subject(:result) { found.group_match_mr_label?(mr_group_label) } - - context 'when MR labels match FF group' do - let(:mr_group_label) { 'group::source code' } - - specify { expect(result).to eq(true) } - end - - context 'when MR labels does not match FF group' do - let(:mr_group_label) { 'group::authentication and authorization' } - - specify { expect(result).to eq(false) } - end - context 'when group is nil' do let(:group) { nil } - context 'and MR has no group label' do - let(:mr_group_label) { nil } - - specify { expect(result).to eq(true) } + it 'is true only if MR has no group label' do + expect(found.group_match_mr_label?(nil)).to eq true + expect(found.group_match_mr_label?('group::source code')).to eq false end + end - context 'and MR has a group label' do - let(:mr_group_label) { 'group::source code' } - - specify { expect(result).to eq(false) } + context 'when group is not nil' do + it 'is true only if MR has the same group label' do + expect(found.group_match_mr_label?(group)).to eq true + expect(found.group_match_mr_label?('group::authentication and authorization')).to eq false end end end diff --git a/spec/tooling/danger/product_intelligence_spec.rb b/spec/tooling/danger/product_intelligence_spec.rb index fab8b0c61fa..c4cd0e5bfb6 100644 --- a/spec/tooling/danger/product_intelligence_spec.rb +++ b/spec/tooling/danger/product_intelligence_spec.rb @@ -18,7 +18,7 @@ RSpec.describe Tooling::Danger::ProductIntelligence do let(:has_product_intelligence_label) { true } before do - allow(fake_helper).to receive(:changed_lines).and_return(changed_lines) + allow(fake_helper).to receive(:changed_lines).and_return(changed_lines) if defined?(changed_lines) allow(fake_helper).to receive(:labels_to_add).and_return(labels_to_add) allow(fake_helper).to receive(:ci?).and_return(ci_env) allow(fake_helper).to receive(:mr_has_labels?).with('product intelligence').and_return(has_product_intelligence_label) @@ -175,4 +175,49 @@ RSpec.describe Tooling::Danger::ProductIntelligence do end end end + + describe '#check_usage_data_insertions!' do + context 'when usage_data.rb is modified' do + let(:modified_files) { ['lib/gitlab/usage_data.rb'] } + + before do + allow(fake_helper).to receive(:changed_lines).with("lib/gitlab/usage_data.rb").and_return(changed_lines) + end + + context 'and has insertions' do + let(:changed_lines) { ['+ ci_runners: count(::Ci::CiRunner),'] } + + it 'produces warning' do + expect(product_intelligence).to receive(:warn).with(/usage_data\.rb has been deprecated/) + + product_intelligence.check_usage_data_insertions! + end + end + + context 'and changes are not insertions' do + let(:changed_lines) { ['- ci_runners: count(::Ci::CiRunner),'] } + + it 'doesnt do anything' do + expect(product_intelligence).not_to receive(:warn) + + product_intelligence.check_usage_data_insertions! + end + end + end + + context 'when usage_data.rb is not modified' do + context 'and another file has insertions' do + let(:modified_files) { ['tooling/danger/product_intelligence.rb'] } + + it 'doesnt do anything' do + expect(fake_helper).to receive(:changed_lines).with("lib/gitlab/usage_data.rb").and_return([]) + allow(fake_helper).to receive(:changed_lines).with("tooling/danger/product_intelligence.rb").and_return(["+ Inserting"]) + + expect(product_intelligence).not_to receive(:warn) + + product_intelligence.check_usage_data_insertions! + end + end + end + end end diff --git a/spec/tooling/danger/project_helper_spec.rb b/spec/tooling/danger/project_helper_spec.rb index 669867ffb4f..48050649f54 100644 --- a/spec/tooling/danger/project_helper_spec.rb +++ b/spec/tooling/danger/project_helper_spec.rb @@ -48,8 +48,8 @@ RSpec.describe Tooling::Danger::ProjectHelper do 'PROCESS.md' | [:docs] 'README.md' | [:docs] - 'ee/doc/foo' | [:unknown] - 'ee/README' | [:unknown] + 'ee/doc/foo' | [:none] + 'ee/README' | [:none] 'app/assets/foo' | [:frontend] 'app/views/foo' | [:frontend, :backend] @@ -139,7 +139,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do 'lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml' | [:ci_template] 'lib/gitlab/ci/templates/dotNET-Core.yml' | [:ci_template] - 'ee/FOO_VERSION' | [:unknown] + 'ee/FOO_VERSION' | [:none] 'db/schema.rb' | [:database] 'db/structure.sql' | [:database] @@ -170,8 +170,8 @@ RSpec.describe Tooling::Danger::ProjectHelper do 'locale/gitlab.pot' | [:none] - 'FOO' | [:unknown] - 'foo' | [:unknown] + 'FOO' | [:none] + 'foo' | [:none] 'foo/bar.rb' | [:backend] 'foo/bar.js' | [:frontend] diff --git a/spec/tooling/danger/specs_spec.rb b/spec/tooling/danger/specs_spec.rb index 422923827a8..cdac5954f92 100644 --- a/spec/tooling/danger/specs_spec.rb +++ b/spec/tooling/danger/specs_spec.rb @@ -19,14 +19,16 @@ RSpec.describe Tooling::Danger::Specs, feature_category: :tooling do let(:file_lines) do [ " describe 'foo' do", - " expect(foo).to match(['bar'])", + " expect(foo).to match(['bar', 'baz'])", " end", - " expect(foo).to match(['bar'])", # same line as line 1 above, we expect two different suggestions + " expect(foo).to match(['bar', 'baz'])", # same line as line 1 above, we expect two different suggestions " ", - " expect(foo).to match ['bar']", - " expect(foo).to eq(['bar'])", - " expect(foo).to eq ['bar']", - " expect(foo).to(match(['bar']))", + " expect(foo).to match ['bar', 'baz']", + " expect(foo).to eq(['bar', 'baz'])", + " expect(foo).to eq ['bar', 'baz']", + " expect(foo).to(match(['bar', 'baz']))", + " expect(foo).to(eq(['bar', 'baz']))", + " expect(foo).to(eq([bar, baz]))", " expect(foo).to(eq(['bar']))", " foo.eq(['bar'])" ] @@ -35,28 +37,30 @@ RSpec.describe Tooling::Danger::Specs, feature_category: :tooling do let(:matching_lines) do [ "+ expect(foo).to match(['should not error'])", - "+ expect(foo).to match(['bar'])", - "+ expect(foo).to match(['bar'])", - "+ expect(foo).to match ['bar']", - "+ expect(foo).to eq(['bar'])", - "+ expect(foo).to eq ['bar']", - "+ expect(foo).to(match(['bar']))", - "+ expect(foo).to(eq(['bar']))" + "+ expect(foo).to match(['bar', 'baz'])", + "+ expect(foo).to match(['bar', 'baz'])", + "+ expect(foo).to match ['bar', 'baz']", + "+ expect(foo).to eq(['bar', 'baz'])", + "+ expect(foo).to eq ['bar', 'baz']", + "+ expect(foo).to(match(['bar', 'baz']))", + "+ expect(foo).to(eq(['bar', 'baz']))", + "+ expect(foo).to(eq([bar, baz]))" ] end let(:changed_lines) do [ - " expect(foo).to match(['bar'])", - " expect(foo).to match(['bar'])", - " expect(foo).to match ['bar']", - " expect(foo).to eq(['bar'])", - " expect(foo).to eq ['bar']", - "- expect(foo).to match(['bar'])", - "- expect(foo).to match(['bar'])", - "- expect(foo).to match ['bar']", - "- expect(foo).to eq(['bar'])", - "- expect(foo).to eq ['bar']", + " expect(foo).to match(['bar', 'baz'])", + " expect(foo).to match(['bar', 'baz'])", + " expect(foo).to match ['bar', 'baz']", + " expect(foo).to eq(['bar', 'baz'])", + " expect(foo).to eq ['bar', 'baz']", + "- expect(foo).to match(['bar', 'baz'])", + "- expect(foo).to match(['bar', 'baz'])", + "- expect(foo).to match ['bar', 'baz']", + "- expect(foo).to eq(['bar', 'baz'])", + "- expect(foo).to eq ['bar', 'baz']", + "- expect(foo).to eq [bar, foo]", "+ expect(foo).to eq([])" ] + matching_lines end @@ -107,7 +111,7 @@ RSpec.describe Tooling::Danger::Specs, feature_category: :tooling do describe '#add_suggestions_for_match_with_array' do let(:template) do - <<~MARKDOWN + <<~MARKDOWN.chomp ```suggestion %<suggested_line>s ``` @@ -118,13 +122,14 @@ RSpec.describe Tooling::Danger::Specs, feature_category: :tooling do it 'adds suggestions at the correct lines' do [ - { suggested_line: " expect(foo).to match_array(['bar'])", number: 2 }, - { suggested_line: " expect(foo).to match_array(['bar'])", number: 4 }, - { suggested_line: " expect(foo).to match_array ['bar']", number: 6 }, - { suggested_line: " expect(foo).to match_array(['bar'])", number: 7 }, - { suggested_line: " expect(foo).to match_array ['bar']", number: 8 }, - { suggested_line: " expect(foo).to(match_array(['bar']))", number: 9 }, - { suggested_line: " expect(foo).to(match_array(['bar']))", number: 10 } + { suggested_line: " expect(foo).to match_array(['bar', 'baz'])", number: 2 }, + { suggested_line: " expect(foo).to match_array(['bar', 'baz'])", number: 4 }, + { suggested_line: " expect(foo).to match_array ['bar', 'baz']", number: 6 }, + { suggested_line: " expect(foo).to match_array(['bar', 'baz'])", number: 7 }, + { suggested_line: " expect(foo).to match_array ['bar', 'baz']", number: 8 }, + { suggested_line: " expect(foo).to(match_array(['bar', 'baz']))", number: 9 }, + { suggested_line: " expect(foo).to(match_array(['bar', 'baz']))", number: 10 }, + { suggested_line: " expect(foo).to(match_array([bar, baz]))", number: 11 } ].each do |test_case| comment = format(template, suggested_line: test_case[:suggested_line]) expect(specs).to receive(:markdown).with(comment, file: filename, line: test_case[:number]) @@ -136,7 +141,7 @@ RSpec.describe Tooling::Danger::Specs, feature_category: :tooling do describe '#add_suggestions_for_project_factory_usage' do let(:template) do - <<~MARKDOWN + <<~MARKDOWN.chomp ```suggestion %<suggested_line>s ``` @@ -220,7 +225,7 @@ RSpec.describe Tooling::Danger::Specs, feature_category: :tooling do describe '#add_suggestions_for_feature_category' do let(:template) do - <<~SUGGESTION_MARKDOWN + <<~SUGGESTION_MARKDOWN.chomp ```suggestion %<suggested_line>s ``` diff --git a/spec/tooling/danger/stable_branch_spec.rb b/spec/tooling/danger/stable_branch_spec.rb index 08fd25b30e0..9eee077d493 100644 --- a/spec/tooling/danger/stable_branch_spec.rb +++ b/spec/tooling/danger/stable_branch_spec.rb @@ -12,6 +12,8 @@ RSpec.describe Tooling::Danger::StableBranch, feature_category: :delivery do include_context 'with dangerfile' let(:fake_danger) { DangerSpecHelper.fake_danger.include(described_class) } + let(:fake_api) { double('Api') } # rubocop:disable RSpec/VerifiedDoubles + let(:gitlab_gem_client) { double('gitlab') } # rubocop:disable RSpec/VerifiedDoubles let(:stable_branch) { fake_danger.new(helper: fake_helper) } @@ -34,6 +36,28 @@ RSpec.describe Tooling::Danger::StableBranch, feature_category: :delivery do end end + shared_examples 'with a warning' do |warning_message| + it 'warns' do + expect(stable_branch).to receive(:warn).with(warning_message) + + subject + end + end + + shared_examples 'bypassing when flaky test or docs only' do + context 'when failure::flaky-test label is present' do + let(:flaky_test_label_present) { true } + + it_behaves_like 'without a failure' + end + + context 'with only docs changes' do + let(:changes_by_category_response) { { docs: ['foo.md'] } } + + it_behaves_like 'without a failure' + end + end + context 'when not applicable' do where(:stable_branch?, :security_mr?) do true | true @@ -47,15 +71,32 @@ RSpec.describe Tooling::Danger::StableBranch, feature_category: :delivery do allow(fake_helper).to receive(:security_mr?).and_return(security_mr?) end - it_behaves_like "without a failure" + it_behaves_like 'without a failure' end end context 'when applicable' do let(:target_branch) { '15-1-stable-ee' } + let(:source_branch) { 'my_bug_branch' } let(:feature_label_present) { false } let(:bug_label_present) { true } + let(:pipeline_expedite_label_present) { false } + let(:flaky_test_label_present) { false } let(:response_success) { true } + + let(:changes_by_category_response) do + { + graphql: ['bar.rb'] + } + end + + let(:pipeline_bridges_response) do + [ + { 'name' => 'e2e:package-and-test', + 'status' => 'success' } + ] + end + let(:parsed_response) do [ { 'version' => '15.1.1' }, @@ -79,14 +120,27 @@ RSpec.describe Tooling::Danger::StableBranch, feature_category: :delivery do before do allow(fake_helper).to receive(:mr_target_branch).and_return(target_branch) + allow(fake_helper).to receive(:mr_source_branch).and_return(source_branch) allow(fake_helper).to receive(:security_mr?).and_return(false) + allow(fake_helper).to receive(:mr_target_project_id).and_return(1) allow(fake_helper).to receive(:mr_has_labels?).with('type::feature').and_return(feature_label_present) allow(fake_helper).to receive(:mr_has_labels?).with('type::bug').and_return(bug_label_present) + allow(fake_helper).to receive(:mr_has_labels?).with('pipeline:expedite') + .and_return(pipeline_expedite_label_present) + allow(fake_helper).to receive(:mr_has_labels?).with('failure::flaky-test') + .and_return(flaky_test_label_present) + allow(fake_helper).to receive(:changes_by_category).and_return(changes_by_category_response) allow(HTTParty).to receive(:get).with(/page=1/).and_return(version_response) + allow(fake_helper).to receive(:api).and_return(fake_api) + allow(stable_branch).to receive(:gitlab).and_return(gitlab_gem_client) + allow(gitlab_gem_client).to receive(:mr_json).and_return({ 'head_pipeline' => { 'id' => '1' } }) + allow(gitlab_gem_client).to receive(:api).and_return(fake_api) + allow(fake_api).to receive(:pipeline_bridges).with(1, '1') + .and_return(pipeline_bridges_response) end # the stubbed behavior above is the success path - it_behaves_like "without a failure" + it_behaves_like 'without a failure' context 'with a feature label' do let(:feature_label_present) { true } @@ -100,20 +154,65 @@ RSpec.describe Tooling::Danger::StableBranch, feature_category: :delivery do it_behaves_like 'with a failure', described_class::BUG_ERROR_MESSAGE end + context 'with a pipeline:expedite label' do + let(:pipeline_expedite_label_present) { true } + + it_behaves_like 'with a failure', described_class::PIPELINE_EXPEDITE_ERROR_MESSAGE + it_behaves_like 'bypassing when flaky test or docs only' + end + + context 'when no package-and-test job is found' do + let(:pipeline_bridges_response) { nil } + + it_behaves_like 'with a failure', described_class::NEEDS_PACKAGE_AND_TEST_MESSAGE + it_behaves_like 'bypassing when flaky test or docs only' + end + + context 'when package-and-test job is in manual state' do + described_class::FAILING_PACKAGE_AND_TEST_STATUSES.each do |status| + let(:pipeline_bridges_response) do + [ + { 'name' => 'e2e:package-and-test', + 'status' => status } + ] + end + + it_behaves_like 'with a failure', described_class::NEEDS_PACKAGE_AND_TEST_MESSAGE + it_behaves_like 'bypassing when flaky test or docs only' + end + end + + context 'when package-and-test job is in a non-successful state' do + let(:pipeline_bridges_response) do + [ + { 'name' => 'e2e:package-and-test', + 'status' => 'running' } + ] + end + + it_behaves_like 'with a warning', described_class::WARN_PACKAGE_AND_TEST_MESSAGE + it_behaves_like 'bypassing when flaky test or docs only' + end + + context 'when no pipeline is found' do + before do + allow(gitlab_gem_client).to receive(:mr_json).and_return({}) + end + + it_behaves_like 'with a failure', described_class::NEEDS_PACKAGE_AND_TEST_MESSAGE + it_behaves_like 'bypassing when flaky test or docs only' + end + context 'when not an applicable version' do let(:target_branch) { '14-9-stable-ee' } - it_behaves_like 'with a failure', described_class::VERSION_ERROR_MESSAGE + it_behaves_like 'with a warning', described_class::VERSION_WARNING_MESSAGE end context 'when the version API request fails' do let(:response_success) { false } - it 'adds a warning' do - expect(stable_branch).to receive(:warn).with(described_class::FAILED_VERSION_REQUEST_MESSAGE) - - subject - end + it_behaves_like 'with a warning', described_class::FAILED_VERSION_REQUEST_MESSAGE end context 'when more than one page of versions is needed' do @@ -151,7 +250,7 @@ RSpec.describe Tooling::Danger::StableBranch, feature_category: :delivery do allow(HTTParty).to receive(:get).with(/page=2/).and_return(second_version_response) end - it_behaves_like "without a failure" + it_behaves_like 'without a failure' end context 'when too many version API requests are made' do @@ -166,4 +265,24 @@ RSpec.describe Tooling::Danger::StableBranch, feature_category: :delivery do end end end + + describe '#non_security_stable_branch?' do + subject { stable_branch.non_security_stable_branch? } + + where(:stable_branch?, :security_mr?, :expected_result) do + true | true | false + false | true | false + true | false | true + false | false | false + end + + with_them do + before do + allow(fake_helper).to receive(:mr_target_branch).and_return(stable_branch? ? '15-1-stable-ee' : 'main') + allow(fake_helper).to receive(:security_mr?).and_return(security_mr?) + end + + it { is_expected.to eq(expected_result) } + end + end end diff --git a/spec/tooling/lib/tooling/helm3_client_spec.rb b/spec/tooling/lib/tooling/helm3_client_spec.rb index 52d1b5a1567..5a015ddfa7c 100644 --- a/spec/tooling/lib/tooling/helm3_client_spec.rb +++ b/spec/tooling/lib/tooling/helm3_client_spec.rb @@ -3,15 +3,14 @@ require_relative '../../../../tooling/lib/tooling/helm3_client' RSpec.describe Tooling::Helm3Client do - let(:namespace) { 'review-apps' } let(:release_name) { 'my-release' } let(:raw_helm_list_page1) do <<~OUTPUT [ - {"name":"review-qa-60-reor-1mugd1","namespace":"#{namespace}","revision":1,"updated":"2020-04-03 17:27:10.245952 +0800 +08","status":"failed","chart":"gitlab-1.1.3","app_version":"12.9.2"}, - {"name":"review-7846-fix-s-261vd6","namespace":"#{namespace}","revision":2,"updated":"2020-04-02 17:27:12.245952 +0800 +08","status":"deployed","chart":"gitlab-1.1.3","app_version":"12.9.2"}, - {"name":"review-7867-snowp-lzo3iy","namespace":"#{namespace}","revision":1,"updated":"2020-04-02 15:27:12.245952 +0800 +08","status":"deployed","chart":"gitlab-1.1.3","app_version":"12.9.1"}, - {"name":"review-6709-group-2pzeec","namespace":"#{namespace}","revision":2,"updated":"2020-04-01 21:27:12.245952 +0800 +08","status":"failed","chart":"gitlab-1.1.3","app_version":"12.9.1"} + {"name":"review-qa-60-reor-1mugd1","namespace":"review-qa-60-reor-1mugd1","revision":1,"updated":"2020-04-03 17:27:10.245952 +0800 +08","status":"failed","chart":"gitlab-1.1.3","app_version":"12.9.2"}, + {"name":"review-7846-fix-s-261vd6","namespace":"review-7846-fix-s-261vd6","revision":2,"updated":"2020-04-02 17:27:12.245952 +0800 +08","status":"deployed","chart":"gitlab-1.1.3","app_version":"12.9.2"}, + {"name":"review-7867-snowp-lzo3iy","namespace":"review-7867-snowp-lzo3iy","revision":1,"updated":"2020-04-02 15:27:12.245952 +0800 +08","status":"deployed","chart":"gitlab-1.1.3","app_version":"12.9.1"}, + {"name":"review-6709-group-2pzeec","namespace":"review-6709-group-2pzeec","revision":2,"updated":"2020-04-01 21:27:12.245952 +0800 +08","status":"failed","chart":"gitlab-1.1.3","app_version":"12.9.1"} ] OUTPUT end @@ -19,7 +18,7 @@ RSpec.describe Tooling::Helm3Client do let(:raw_helm_list_page2) do <<~OUTPUT [ - {"name":"review-6709-group-t40qbv","namespace":"#{namespace}","revision":2,"updated":"2020-04-01 11:27:12.245952 +0800 +08","status":"deployed","chart":"gitlab-1.1.3","app_version":"12.9.1"} + {"name":"review-6709-group-t40qbv","namespace":"review-6709-group-t40qbv","revision":2,"updated":"2020-04-01 11:27:12.245952 +0800 +08","status":"deployed","chart":"gitlab-1.1.3","app_version":"12.9.1"} ] OUTPUT end @@ -30,7 +29,7 @@ RSpec.describe Tooling::Helm3Client do OUTPUT end - subject { described_class.new(namespace: namespace) } + subject { described_class.new } describe '#releases' do it 'raises an error if the Helm command fails' do @@ -74,7 +73,7 @@ RSpec.describe Tooling::Helm3Client do status: 'deployed', chart: 'gitlab-1.1.3', app_version: '12.9.1', - namespace: namespace + namespace: 'review-6709-group-t40qbv' ) end @@ -98,18 +97,19 @@ RSpec.describe Tooling::Helm3Client do describe '#delete' do it 'raises an error if the Helm command fails' do expect(Gitlab::Popen).to receive(:popen_with_detail) - .with([%(helm uninstall #{release_name})]) + .with([%(helm uninstall --namespace #{release_name} #{release_name})]) .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: false))) - expect { subject.delete(release_name: release_name) }.to raise_error(described_class::CommandFailedError) + expect { subject.delete(release_name: release_name, namespace: release_name) } + .to raise_error(described_class::CommandFailedError) end it 'calls helm uninstall with default arguments' do expect(Gitlab::Popen).to receive(:popen_with_detail) - .with([%(helm uninstall #{release_name})]) + .with([%(helm uninstall --namespace #{release_name} #{release_name})]) .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true))) - expect(subject.delete(release_name: release_name)).to eq('') + subject.delete(release_name: release_name, namespace: release_name) end context 'with multiple release names' do @@ -117,18 +117,30 @@ RSpec.describe Tooling::Helm3Client do it 'raises an error if the Helm command fails' do expect(Gitlab::Popen).to receive(:popen_with_detail) - .with([%(helm uninstall #{release_name.join(' ')})]) + .with([%(helm uninstall --namespace #{release_name[0]} #{release_name[0]})]) .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: false))) expect { subject.delete(release_name: release_name) }.to raise_error(described_class::CommandFailedError) end - it 'calls helm uninstall with multiple release names' do - expect(Gitlab::Popen).to receive(:popen_with_detail) - .with([%(helm uninstall #{release_name.join(' ')})]) - .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true))) + it 'calls helm uninstall with multiple release names and a namespace' do + release_name.each do |release| + expect(Gitlab::Popen).to receive(:popen_with_detail) + .with([%(helm uninstall --namespace namespace #{release})]) + .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true))) + end + + subject.delete(release_name: release_name, namespace: 'namespace') + end + + it 'calls helm uninstall with multiple release names and no namespace' do + release_name.each do |release| + expect(Gitlab::Popen).to receive(:popen_with_detail) + .with([%(helm uninstall --namespace #{release} #{release})]) + .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true))) + end - expect(subject.delete(release_name: release_name)).to eq('') + subject.delete(release_name: release_name) end end end diff --git a/spec/tooling/lib/tooling/kubernetes_client_spec.rb b/spec/tooling/lib/tooling/kubernetes_client_spec.rb index a7f50b0bb50..50d33182a42 100644 --- a/spec/tooling/lib/tooling/kubernetes_client_spec.rb +++ b/spec/tooling/lib/tooling/kubernetes_client_spec.rb @@ -250,7 +250,7 @@ RSpec.describe Tooling::KubernetesClient do describe '#review_app_namespaces_created_before' do let(:three_days_ago) { Time.now - 3600 * 24 * 3 } let(:two_days_ago) { Time.now - 3600 * 24 * 2 } - let(:namespace_created_three_days_ago) { 'namespace-created-three-days-ago' } + let(:namespace_created_three_days_ago) { 'review-ns-created-three-days-ago' } let(:resource_type) { 'namespace' } let(:raw_resources) do { @@ -260,10 +260,7 @@ RSpec.describe Tooling::KubernetesClient do kind: "Namespace", metadata: { creationTimestamp: three_days_ago, - name: namespace_created_three_days_ago, - labels: { - tls: 'review-apps-tls' - } + name: namespace_created_three_days_ago } }, { @@ -271,10 +268,7 @@ RSpec.describe Tooling::KubernetesClient do kind: "Namespace", metadata: { creationTimestamp: Time.now, - name: 'another-pvc', - labels: { - tls: 'review-apps-tls' - } + name: 'another-namespace' } } ] @@ -283,12 +277,10 @@ RSpec.describe Tooling::KubernetesClient do specify do expect(Gitlab::Popen).to receive(:popen_with_detail) - .with(["kubectl get namespace " \ - "-l tls=review-apps-tls " \ - "--sort-by='{.metadata.creationTimestamp}' -o json"]) - .and_return(Gitlab::Popen::Result.new([], raw_resources, '', double(success?: true))) + .with(["kubectl get namespace --sort-by='{.metadata.creationTimestamp}' -o json"]) + .and_return(Gitlab::Popen::Result.new([], raw_resources, '', double(success?: true))) - expect(subject.__send__(:review_app_namespaces_created_before, created_before: two_days_ago)).to contain_exactly(namespace_created_three_days_ago) + expect(subject.__send__(:review_app_namespaces_created_before, created_before: two_days_ago)).to eq([namespace_created_three_days_ago]) end end end diff --git a/spec/tooling/lib/tooling/mappings/base_spec.rb b/spec/tooling/lib/tooling/mappings/base_spec.rb new file mode 100644 index 00000000000..935f833fa8b --- /dev/null +++ b/spec/tooling/lib/tooling/mappings/base_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require_relative '../../../../../tooling/lib/tooling/mappings/view_to_js_mappings' + +RSpec.describe Tooling::Mappings::Base, feature_category: :tooling do + describe '#folders_for_available_editions' do + let(:base_folder_path) { 'app/views' } + + subject { described_class.new.folders_for_available_editions(base_folder_path) } + + context 'when FOSS' do + before do + allow(GitlabEdition).to receive(:ee?).and_return(false) + allow(GitlabEdition).to receive(:jh?).and_return(false) + end + + it 'returns the correct paths' do + expect(subject).to match_array([base_folder_path]) + end + end + + context 'when EE' do + before do + allow(GitlabEdition).to receive(:ee?).and_return(true) + allow(GitlabEdition).to receive(:jh?).and_return(false) + end + + it 'returns the correct paths' do + expect(subject).to match_array([base_folder_path, "ee/#{base_folder_path}"]) + end + end + + context 'when JiHu' do + before do + allow(GitlabEdition).to receive(:ee?).and_return(true) + allow(GitlabEdition).to receive(:jh?).and_return(true) + end + + it 'returns the correct paths' do + expect(subject).to match_array([base_folder_path, "ee/#{base_folder_path}", "jh/#{base_folder_path}"]) + end + end + end +end diff --git a/spec/tooling/lib/tooling/mappings/js_to_system_specs_mappings_spec.rb b/spec/tooling/lib/tooling/mappings/js_to_system_specs_mappings_spec.rb new file mode 100644 index 00000000000..72e02547938 --- /dev/null +++ b/spec/tooling/lib/tooling/mappings/js_to_system_specs_mappings_spec.rb @@ -0,0 +1,169 @@ +# frozen_string_literal: true + +require 'tempfile' +require_relative '../../../../../tooling/lib/tooling/mappings/js_to_system_specs_mappings' + +RSpec.describe Tooling::Mappings::JsToSystemSpecsMappings, feature_category: :tooling do + # We set temporary folders, and those readers give access to those folder paths + attr_accessor :js_base_folder, :system_specs_base_folder + + around do |example| + Dir.mktmpdir do |tmp_js_base_folder| + Dir.mktmpdir do |tmp_system_specs_base_folder| + self.system_specs_base_folder = tmp_system_specs_base_folder + self.js_base_folder = tmp_js_base_folder + + example.run + end + end + end + + describe '#execute' do + let(:instance) do + described_class.new( + system_specs_base_folder: system_specs_base_folder, + js_base_folder: js_base_folder + ) + end + + subject { instance.execute(changed_files) } + + context 'when no JS files were changed' do + let(:changed_files) { [] } + + it 'returns nothing' do + expect(subject).to match_array([]) + end + end + + context 'when some JS files were changed' do + let(:changed_files) { ["#{js_base_folder}/issues/secret_values.js"] } + + context 'when the JS files are not present on disk' do + it 'returns nothing' do + expect(subject).to match_array([]) + end + end + + context 'when the JS files are present on disk' do + before do + FileUtils.mkdir_p("#{js_base_folder}/issues") + File.write("#{js_base_folder}/issues/secret_values.js", "hello") + end + + context 'when no system specs match the JS keyword' do + it 'returns nothing' do + expect(subject).to match_array([]) + end + end + + context 'when a system spec matches the JS keyword' do + before do + FileUtils.mkdir_p("#{system_specs_base_folder}/confidential_issues") + File.write("#{system_specs_base_folder}/confidential_issues/issues_spec.rb", "a test") + end + + it 'returns something' do + expect(subject).to match_array(["#{system_specs_base_folder}/confidential_issues/issues_spec.rb"]) + end + end + end + end + end + + describe '#filter_files' do + subject { described_class.new(js_base_folder: js_base_folder).filter_files(changed_files) } + + before do + File.write("#{js_base_folder}/index.js", "index.js") + File.write("#{js_base_folder}/index-with-ee-in-it.js", "index-with-ee-in-it.js") + File.write("#{js_base_folder}/index-with-jh-in-it.js", "index-with-jh-in-it.js") + end + + context 'when no files were changed' do + let(:changed_files) { [] } + + it 'returns an empty array' do + expect(subject).to match_array([]) + end + end + + context 'when JS files were changed' do + let(:changed_files) do + [ + "#{js_base_folder}/index.js", + "#{js_base_folder}/index-with-ee-in-it.js", + "#{js_base_folder}/index-with-jh-in-it.js" + ] + end + + it 'returns the path to the JS files' do + # "nil" group represents FOSS JS files in app/assets/javascripts + expect(subject).to match(nil => [ + "#{js_base_folder}/index.js", + "#{js_base_folder}/index-with-ee-in-it.js", + "#{js_base_folder}/index-with-jh-in-it.js" + ]) + end + end + + context 'when JS files are deleted' do + let(:changed_files) { ["#{system_specs_base_folder}/deleted.html"] } + + it 'returns an empty array' do + expect(subject).to match_array([]) + end + end + end + + describe '#construct_js_keywords' do + subject { described_class.new.construct_js_keywords(js_files) } + + let(:js_files) do + %w[ + app/assets/javascripts/boards/issue_board_filters.js + ee/app/assets/javascripts/queries/epic_due_date.query.graphql + ] + end + + it 'returns a singularized keyword based on the first folder the file is in' do + expect(subject).to eq(%w[board query]) + end + end + + describe '#system_specs_for_edition' do + subject do + described_class.new(system_specs_base_folder: system_specs_base_folder).system_specs_for_edition(edition) + end + + context 'when FOSS' do + let(:edition) { nil } + + it 'checks the correct folder' do + expect(Dir).to receive(:[]).with("#{system_specs_base_folder}/**/*").and_call_original + + subject + end + end + + context 'when EE' do + let(:edition) { 'ee' } + + it 'checks the correct folder' do + expect(Dir).to receive(:[]).with("ee#{system_specs_base_folder}/**/*").and_call_original + + subject + end + end + + context 'when JiHu' do + let(:edition) { 'jh' } + + it 'checks the correct folder' do + expect(Dir).to receive(:[]).with("jh#{system_specs_base_folder}/**/*").and_call_original + + subject + end + end + end +end diff --git a/spec/tooling/lib/tooling/view_to_js_mappings_spec.rb b/spec/tooling/lib/tooling/mappings/view_to_js_mappings_spec.rb index b09df2a9200..eaa0124370d 100644 --- a/spec/tooling/lib/tooling/view_to_js_mappings_spec.rb +++ b/spec/tooling/lib/tooling/mappings/view_to_js_mappings_spec.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true require 'tempfile' -require_relative '../../../../tooling/lib/tooling/view_to_js_mappings' +require_relative '../../../../../tooling/lib/tooling/mappings/view_to_js_mappings' -RSpec.describe Tooling::ViewToJsMappings, feature_category: :tooling do +RSpec.describe Tooling::Mappings::ViewToJsMappings, feature_category: :tooling do # We set temporary folders, and those readers give access to those folder paths attr_accessor :view_base_folder, :js_base_folder @@ -32,7 +32,7 @@ RSpec.describe Tooling::ViewToJsMappings, feature_category: :tooling do context 'when no view files have been changed' do before do - allow(instance).to receive(:view_files).and_return([]) + allow(instance).to receive(:filter_files).and_return([]) end it 'returns nothing' do @@ -140,8 +140,8 @@ RSpec.describe Tooling::ViewToJsMappings, feature_category: :tooling do end end - describe '#view_files' do - subject { described_class.new(view_base_folder: view_base_folder).view_files(changed_files) } + describe '#filter_files' do + subject { described_class.new(view_base_folder: view_base_folder).filter_files(changed_files) } before do File.write("#{js_base_folder}/index.js", "index.js") @@ -181,45 +181,6 @@ RSpec.describe Tooling::ViewToJsMappings, feature_category: :tooling do end end - describe '#folders_for_available_editions' do - let(:base_folder_path) { 'app/views' } - - subject { described_class.new.folders_for_available_editions(base_folder_path) } - - context 'when FOSS' do - before do - allow(GitlabEdition).to receive(:ee?).and_return(false) - allow(GitlabEdition).to receive(:jh?).and_return(false) - end - - it 'returns the correct paths' do - expect(subject).to match_array([base_folder_path]) - end - end - - context 'when EE' do - before do - allow(GitlabEdition).to receive(:ee?).and_return(true) - allow(GitlabEdition).to receive(:jh?).and_return(false) - end - - it 'returns the correct paths' do - expect(subject).to eq([base_folder_path, "ee/#{base_folder_path}"]) - end - end - - context 'when JiHu' do - before do - allow(GitlabEdition).to receive(:ee?).and_return(true) - allow(GitlabEdition).to receive(:jh?).and_return(true) - end - - it 'returns the correct paths' do - expect(subject).to eq([base_folder_path, "ee/#{base_folder_path}", "jh/#{base_folder_path}"]) - end - end - end - describe '#find_partials' do subject { described_class.new(view_base_folder: view_base_folder).find_partials(file_path) } |