diff options
Diffstat (limited to 'qa/qa/tools/ci')
-rw-r--r-- | qa/qa/tools/ci/non_empty_suites.rb | 81 | ||||
-rw-r--r-- | qa/qa/tools/ci/qa_changes.rb | 51 |
2 files changed, 81 insertions, 51 deletions
diff --git a/qa/qa/tools/ci/non_empty_suites.rb b/qa/qa/tools/ci/non_empty_suites.rb index 687c11a3e62..2319237fa25 100644 --- a/qa/qa/tools/ci/non_empty_suites.rb +++ b/qa/qa/tools/ci/non_empty_suites.rb @@ -10,42 +10,11 @@ module QA class NonEmptySuites include Helpers - # rubocop:disable Layout/LineLength - SCENARIOS = [ - { klass: "Test::Instance::All" }, - { klass: "Test::Instance::Smoke" }, - { klass: "Test::Instance::Reliable" }, - { klass: "Test::Instance::ReviewBlocking" }, - { klass: "Test::Instance::ReviewNonBlocking" }, - { klass: "Test::Instance::CloudActivation" }, - { klass: "Test::Instance::Integrations" }, - { klass: "Test::Instance::Jira" }, - { klass: "Test::Instance::LargeSetup" }, - { klass: "Test::Instance::Metrics" }, - { klass: "Test::Instance::ObjectStorage" }, - { klass: "Test::Instance::Packages" }, - { klass: "Test::Instance::RepositoryStorage" }, - { klass: "Test::Integration::ServicePingDisabled" }, - { klass: "Test::Integration::LDAPNoTLS" }, - { klass: "Test::Integration::LDAPTLS" }, - { klass: "Test::Integration::LDAPNoServer" }, - { klass: "Test::Integration::InstanceSAML" }, - { klass: "Test::Integration::RegistryWithCDN" }, - { klass: "Test::Integration::RegistryTLS" }, - { klass: "Test::Integration::Registry" }, - { klass: "Test::Integration::SMTP" }, - { klass: "QA::EE::Scenario::Test::Integration::Elasticsearch" }, - { klass: "QA::EE::Scenario::Test::Integration::GroupSAML" }, - { - klass: "QA::EE::Scenario::Test::Geo", - args: "--primary-address http://dummy1.test --primary-name gitlab-primary --secondary-address http://dummy2.test --secondary-name gitlab-secondary --without-setup" - }, - { - klass: "Test::Integration::Mattermost", - args: "--mattermost-address http://mattermost.test" - } + # @return [Array] scenarios that never run in package-and-test pipeline + IGNORED_SCENARIOS = [ + "QA::EE::Scenario::Test::Geo", + "QA::Scenario::Test::Instance::Airgapped" ].freeze - # rubocop:enable Layout/LineLength def initialize(qa_tests) @qa_tests = qa_tests @@ -56,38 +25,58 @@ module QA # @return [String] def fetch logger.info("Checking for runnable suites") - scenarios = SCENARIOS.each_with_object([]) do |scenario, runnable_scenarios| - logger.info(" fetching runnable specs for '#{scenario[:klass]}'") + scenarios.each_with_object([]) do |scenario, runnable_scenarios| + logger.info(" fetching runnable specs for '#{scenario}'") + next logger.info(" scenario is in ignore list, skipping") if IGNORED_SCENARIOS.include?(scenario) - out, err, status = run_command(**scenario) + out, err, status = run_command(scenario) unless status.success? - logger.error(" example count failed!\n#{err}") + logger.error(" example count failed!\n#{err}") next end count = out.split("\n").last.to_i logger.info(" found #{count} examples to run") - runnable_scenarios << scenario[:klass] if count > 0 - end - - scenarios.join(",") + runnable_scenarios << scenario if count > 0 + end.join(",") end private attr_reader :qa_tests + # Get all defined scenarios + # + # @return [Array<String>] + def scenarios + foss_scenarios = scenario_classes(QA::Scenario::Test) + return foss_scenarios unless QA.const_defined?("QA::EE") + + foss_scenarios + scenario_classes(QA::EE::Scenario::Test) + end + + # Fetch scenario classes recursively + # + # @param [Module] mod + # @return [Array<String>] + def scenario_classes(mod) + mod.constants.map do |const| + c = mod.const_get(const, false) + next c.to_s if c.is_a?(Class) + + scenario_classes(c) + end.flatten + end + # Run scenario count command # # @param [String] klass - # @param [String] args # @return [String] - def run_command(klass:, args: nil) + def run_command(klass) cmd = ["bundle exec bin/qa"] cmd << klass cmd << "--count-examples-only --address http://dummy1.test" - cmd << args if args cmd << "-- #{qa_tests}" unless qa_tests.blank? Open3.capture3(cmd.join(" ")) diff --git a/qa/qa/tools/ci/qa_changes.rb b/qa/qa/tools/ci/qa_changes.rb index 75274961efe..784923714d6 100644 --- a/qa/qa/tools/ci/qa_changes.rb +++ b/qa/qa/tools/ci/qa_changes.rb @@ -11,17 +11,25 @@ module QA QA_PATTERN = %r{^qa/}.freeze SPEC_PATTERN = %r{^qa/qa/specs/features/}.freeze - - def initialize(mr_diff, mr_labels) + DEPENDENCY_PATTERN = Regexp.union( + /_VERSION/, + /Gemfile\.lock/, + /yarn\.lock/, + /Dockerfile\.assets/ + ) + + def initialize(mr_diff, mr_labels, additional_group_spec_list) @mr_diff = mr_diff @mr_labels = mr_labels + @additional_group_spec_list = additional_group_spec_list end # Specific specs to run # # @return [String] def qa_tests - return if mr_diff.empty? + return if mr_diff.empty? || dependency_changes + # make paths relative to qa directory return changed_files&.map { |path| path.delete_prefix("qa/") }&.join(" ") if only_spec_changes? return qa_spec_directories_for_devops_stage&.join(" ") if non_qa_changes? && mr_labels.any? @@ -73,6 +81,9 @@ module QA # @return [Array] attr_reader :mr_labels + # @return [Hash<String, Array<String>>] + attr_reader :additional_group_spec_list + # Are the changed files only qa specs? # # @return [Boolean] whether the changes files are only qa specs @@ -94,6 +105,13 @@ module QA mr_labels.find { |label| label =~ /^devops::/ }&.delete_prefix('devops::') end + # Extract group name from MR labels + # + # @return [String] a group name + def group_name_from_mr_labels + mr_labels.find { |label| label =~ /^group::/ }&.delete_prefix('group::') + end + # Get qa spec directories for devops stage # # @return [Array] qa spec directories @@ -101,14 +119,37 @@ module QA devops_stage = devops_stage_from_mr_labels return unless devops_stage - Dir.glob("qa/specs/**/*/").select { |dir| dir =~ %r{\d+_#{devops_stage}/$} } + spec_dirs = stage_specs(devops_stage) + + grp_name = group_name_from_mr_labels + return spec_dirs if grp_name.nil? + + additional_grp_specs = additional_group_spec_list[grp_name] + return spec_dirs if additional_grp_specs.nil? + + spec_dirs + stage_specs(*additional_grp_specs) + end + + # Changes to gitlab dependencies + # + # @return [Boolean] + def dependency_changes + changed_files.any? { |file| file.match?(DEPENDENCY_PATTERN) } end # Change files in merge request # # @return [Array<String>] def changed_files - @changed_files ||= mr_diff.map { |change| change[:path] } # rubocop:disable Rails/Pluck + @changed_files ||= mr_diff.map { |change| change[:path] } + end + + # Devops stage specs + # + # @param [Array<String>] devops_stages + # @return [Array] + def stage_specs(*devops_stages) + Dir.glob("qa/specs/**/*/").select { |dir| dir =~ %r{\d+_(#{devops_stages.join('|')})/$} } end end end |