Welcome to mirror list, hosted at ThFree Co, Russian Federation.

determine-qa-tests « scripts - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: b1e9d8e93126b5c25506797eaf1db534526d18fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#!/usr/bin/env ruby
# frozen_string_literal: true

require 'optparse'

# This script returns end-to-end tests or test directories. The returned value is stored in QA_TESTS
# variable for executing only those tests.

class DetermineQATests # rubocop:disable Gitlab/NamespacedClass
  def initialize(options)
    @changed_files = options.delete(:changed_files)
    @mr_labels = options.delete(:mr_labels) || []
  end

  def execute
    # If only e2e test files have changed, run only those tests
    qa_tests = if has_qa_spec_only_changes?
                 changed_files

                 # If only non qa files have changed, use the devops MR label to run the files in the related directory
                 # However, if a feature flag file has changed, do not return any specific test/test directory
               elsif has_non_qa_only_changes? && mr_labels.any? && !has_dev_ops_feature_flag_changes?
                 devops_stage = devops_stage_from_mr_labels

                 qa_spec_directories_for_devops_stage(devops_stage) if devops_stage
               end

    trim_path(qa_tests).join(' ') if qa_tests
  end

  private

  attr_reader :changed_files, :mr_labels

  # Are the changed files only qa specs?
  #
  # @return [Boolean] whether the changes files are only qa specs
  def has_qa_spec_only_changes?
    changed_files.all? { |file_path| file_path =~ %r{^qa/qa/specs/features/} }
  end

  # Are the changed files only outside the qa directory?
  #
  # @return [Boolean] whether the changes files are outside of qa directory
  def has_non_qa_only_changes?
    changed_files.none? { |file_path| file_path =~ %r{^qa/} }
  end

  # Are the changed files for development and ops feature flags?
  #
  # @return [Boolean] whether the changes files are for development and ops feature flags
  def has_dev_ops_feature_flag_changes?
    changed_files.any? { |file_path| file_path =~ %r{/feature_flags/(development|ops)/.*\.yml} }
  end

  # Remove the leading `qa/` from the file or directory paths
  #
  # @param [Array] paths Array of file or directory paths
  # @return [Array] Array of files or directories with the first occurance of `qa/` removed
  def trim_path(paths)
    paths.map { |path| path.delete_prefix("qa/") }
  end

  # Extract devops stage from MR labels
  #
  # @return [String] a devops stage
  def devops_stage_from_mr_labels
    mr_labels.find { |label| label =~ /^devops::/ }&.delete_prefix('devops::')
  end

  # Get qa spec directories for devops stage
  #
  # @param [String] devops_stage a devops stage
  # @return [Array] qa spec directories
  def qa_spec_directories_for_devops_stage(devops_stage)
    Dir.glob("qa/qa/specs/**/*/").select { |dir| dir =~ %r{\d+_#{devops_stage}/$} }
  end
end

if $0 == __FILE__
  options = {}

  OptionParser.new do |opts|
    opts.on("-f", "--files CHANGED_FILES_PATH", String,
      "A path to a file containing a list of changed files") do |value|
      changed_files_path = value
      abort("ERROR: The specified changed files path does not exist") unless File.exist?(changed_files_path)

      changed_files = File.read(changed_files_path).split(' ')
      abort("ERROR: There are no changed files") if changed_files.empty?

      options[:changed_files] = changed_files
    end

    opts.on("-l", "--labels MR_LABELS", String, "A comma separated list of MR labels") do |value|
      options[:mr_labels] = Array(value&.split(',')).compact
    end

    opts.on("-h", "--help", "Prints this help") do
      puts opts
      exit
    end
  end.parse!

  puts DetermineQATests.new(options).execute
end