gitlab-triage 1.6.1 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.gitignore +0 -1
 - data/.gitlab-ci.yml +75 -40
 - data/.gitlab/merge_request_templates/Release.md +35 -0
 - data/.rubocop.yml +3 -0
 - data/Gemfile +1 -1
 - data/README.md +95 -4
 - data/gitlab-triage.gemspec +1 -1
 - data/lib/gitlab/triage/action/comment.rb +14 -1
 - data/lib/gitlab/triage/api_query_builders/date_query_param_builder.rb +78 -0
 - data/lib/gitlab/triage/command_builders/move_command_builder.rb +19 -0
 - data/lib/gitlab/triage/command_builders/text_content_builder.rb +17 -1
 - data/lib/gitlab/triage/engine.rb +41 -16
 - data/lib/gitlab/triage/errors.rb +1 -1
 - data/lib/gitlab/triage/filters/merge_request_date_conditions_filter.rb +51 -5
 - data/lib/gitlab/triage/network.rb +2 -1
 - data/lib/gitlab/triage/network_adapters/httparty_adapter.rb +13 -1
 - data/lib/gitlab/triage/option_parser.rb +10 -0
 - data/lib/gitlab/triage/options.rb +2 -0
 - data/lib/gitlab/triage/policies/rule_policy.rb +1 -1
 - data/lib/gitlab/triage/policies/summary_policy.rb +1 -1
 - data/lib/gitlab/triage/policies_resources/rule_resources.rb +5 -6
 - data/lib/gitlab/triage/policies_resources/summary_resources.rb +5 -6
 - data/lib/gitlab/triage/resource/base.rb +5 -0
 - data/lib/gitlab/triage/resource/issue.rb +4 -0
 - data/lib/gitlab/triage/resource/merge_request.rb +13 -0
 - data/lib/gitlab/triage/resource/shared/issuable.rb +26 -0
 - data/lib/gitlab/triage/url_builders/url_builder.rb +10 -9
 - data/lib/gitlab/triage/validators/limiter_validator.rb +3 -1
 - data/lib/gitlab/triage/validators/params_validator.rb +5 -3
 - data/lib/gitlab/triage/version.rb +3 -1
 - data/support/.triage-policies.example.yml +2 -2
 - metadata +6 -4
 - data/lib/gitlab/triage/filters/issuable_date_conditions_filter.rb +0 -65
 
| 
         @@ -0,0 +1,78 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative '../validators/params_validator'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Gitlab
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Triage
         
     | 
| 
      
 5 
     | 
    
         
            +
                module APIQueryBuilders
         
     | 
| 
      
 6 
     | 
    
         
            +
                  class DateQueryParamBuilder
         
     | 
| 
      
 7 
     | 
    
         
            +
                    ATTRIBUTES = %w[updated_at created_at].freeze
         
     | 
| 
      
 8 
     | 
    
         
            +
                    CONDITIONS = %w[older_than newer_than].freeze
         
     | 
| 
      
 9 
     | 
    
         
            +
                    INTERVAL_TYPES = %w[days weeks months years].freeze
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                    def self.filter_parameters
         
     | 
| 
      
 12 
     | 
    
         
            +
                      [
         
     | 
| 
      
 13 
     | 
    
         
            +
                        {
         
     | 
| 
      
 14 
     | 
    
         
            +
                          name: :attribute,
         
     | 
| 
      
 15 
     | 
    
         
            +
                          type: String,
         
     | 
| 
      
 16 
     | 
    
         
            +
                          values: ATTRIBUTES
         
     | 
| 
      
 17 
     | 
    
         
            +
                        },
         
     | 
| 
      
 18 
     | 
    
         
            +
                        {
         
     | 
| 
      
 19 
     | 
    
         
            +
                          name: :condition,
         
     | 
| 
      
 20 
     | 
    
         
            +
                          type: String,
         
     | 
| 
      
 21 
     | 
    
         
            +
                          values: CONDITIONS
         
     | 
| 
      
 22 
     | 
    
         
            +
                        },
         
     | 
| 
      
 23 
     | 
    
         
            +
                        {
         
     | 
| 
      
 24 
     | 
    
         
            +
                          name: :interval_type,
         
     | 
| 
      
 25 
     | 
    
         
            +
                          type: String,
         
     | 
| 
      
 26 
     | 
    
         
            +
                          values: INTERVAL_TYPES
         
     | 
| 
      
 27 
     | 
    
         
            +
                        },
         
     | 
| 
      
 28 
     | 
    
         
            +
                        {
         
     | 
| 
      
 29 
     | 
    
         
            +
                          name: :interval,
         
     | 
| 
      
 30 
     | 
    
         
            +
                          type: Numeric
         
     | 
| 
      
 31 
     | 
    
         
            +
                        }
         
     | 
| 
      
 32 
     | 
    
         
            +
                      ]
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    def self.applicable?(condition)
         
     | 
| 
      
 36 
     | 
    
         
            +
                      ATTRIBUTES.include?(condition[:attribute].to_s)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    def initialize(condition_hash)
         
     | 
| 
      
 40 
     | 
    
         
            +
                      @attribute = condition_hash[:attribute].to_s
         
     | 
| 
      
 41 
     | 
    
         
            +
                      @interval_condition = condition_hash[:condition].to_sym
         
     | 
| 
      
 42 
     | 
    
         
            +
                      @interval_type = condition_hash[:interval_type]
         
     | 
| 
      
 43 
     | 
    
         
            +
                      @interval = condition_hash[:interval]
         
     | 
| 
      
 44 
     | 
    
         
            +
                      validate_condition(condition_hash)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    def validate_condition(condition)
         
     | 
| 
      
 48 
     | 
    
         
            +
                      ParamsValidator.new(self.class.filter_parameters, condition).validate!
         
     | 
| 
      
 49 
     | 
    
         
            +
                    end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    def param_name
         
     | 
| 
      
 52 
     | 
    
         
            +
                      prefix = attribute.delete_suffix('_at')
         
     | 
| 
      
 53 
     | 
    
         
            +
                      suffix =
         
     | 
| 
      
 54 
     | 
    
         
            +
                        case interval_condition
         
     | 
| 
      
 55 
     | 
    
         
            +
                        when :older_than
         
     | 
| 
      
 56 
     | 
    
         
            +
                          'before'
         
     | 
| 
      
 57 
     | 
    
         
            +
                        when :newer_than
         
     | 
| 
      
 58 
     | 
    
         
            +
                          'after'
         
     | 
| 
      
 59 
     | 
    
         
            +
                        end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                      "#{prefix}_#{suffix}"
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                    def param_content
         
     | 
| 
      
 65 
     | 
    
         
            +
                      interval.public_send(interval_type).ago.to_date # rubocop:disable GitlabSecurity/PublicSend
         
     | 
| 
      
 66 
     | 
    
         
            +
                    end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                    def build_param
         
     | 
| 
      
 69 
     | 
    
         
            +
                      "&#{param_name}=#{param_content.strip}"
         
     | 
| 
      
 70 
     | 
    
         
            +
                    end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                    private
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                    attr_reader :condition_hash, :attribute, :interval_condition, :interval_type, :interval
         
     | 
| 
      
 75 
     | 
    
         
            +
                  end
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
              end
         
     | 
| 
      
 78 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'base_command_builder'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Gitlab
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Triage
         
     | 
| 
      
 5 
     | 
    
         
            +
                module CommandBuilders
         
     | 
| 
      
 6 
     | 
    
         
            +
                  class MoveCommandBuilder < BaseCommandBuilder
         
     | 
| 
      
 7 
     | 
    
         
            +
                    private
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                    def slash_command_string
         
     | 
| 
      
 10 
     | 
    
         
            +
                      "/move"
         
     | 
| 
      
 11 
     | 
    
         
            +
                    end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    def format_item(item)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      item
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,6 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require 'active_support/core_ext/array/wrap'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'cgi'
         
     | 
| 
       4 
5 
     | 
    
         | 
| 
       5 
6 
     | 
    
         
             
            require_relative 'base_command_builder'
         
     | 
| 
       6 
7 
     | 
    
         
             
            require_relative '../resource/context'
         
     | 
| 
         @@ -76,7 +77,22 @@ module Gitlab 
     | 
|
| 
       76 
77 
     | 
    
         
             
                          template.sub(PLACEHOLDER_REGEX, attribute.to_s)
         
     | 
| 
       77 
78 
     | 
    
         
             
                        end.join(', ')
         
     | 
| 
       78 
79 
     | 
    
         | 
| 
       79 
     | 
    
         
            -
                         
     | 
| 
      
 80 
     | 
    
         
            +
                        escaped_text =
         
     | 
| 
      
 81 
     | 
    
         
            +
                          case placeholder
         
     | 
| 
      
 82 
     | 
    
         
            +
                          when :items
         
     | 
| 
      
 83 
     | 
    
         
            +
                            # We don't need to escape it because it's recursive,
         
     | 
| 
      
 84 
     | 
    
         
            +
                            # which the contents should all be escaped already.
         
     | 
| 
      
 85 
     | 
    
         
            +
                            # Or put it another way, items isn't an attribute
         
     | 
| 
      
 86 
     | 
    
         
            +
                            # retrieved externally. It's a generated value which
         
     | 
| 
      
 87 
     | 
    
         
            +
                            # should be safe to begin with. At some point we
         
     | 
| 
      
 88 
     | 
    
         
            +
                            # may want to make this more distinguishable,
         
     | 
| 
      
 89 
     | 
    
         
            +
                            # separating values from API and values generated.
         
     | 
| 
      
 90 
     | 
    
         
            +
                            formatted_text
         
     | 
| 
      
 91 
     | 
    
         
            +
                          else
         
     | 
| 
      
 92 
     | 
    
         
            +
                            CGI.escape_html(formatted_text)
         
     | 
| 
      
 93 
     | 
    
         
            +
                          end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                        comment.gsub("{{#{placeholder}}}", escaped_text)
         
     | 
| 
       80 
96 
     | 
    
         
             
                      end
         
     | 
| 
       81 
97 
     | 
    
         
             
                    end
         
     | 
| 
       82 
98 
     | 
    
         | 
    
        data/lib/gitlab/triage/engine.rb
    CHANGED
    
    | 
         @@ -2,7 +2,6 @@ require 'active_support/all' 
     | 
|
| 
       2 
2 
     | 
    
         
             
            require 'active_support/inflector'
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            require_relative 'expand_condition'
         
     | 
| 
       5 
     | 
    
         
            -
            require_relative 'filters/issuable_date_conditions_filter'
         
     | 
| 
       6 
5 
     | 
    
         
             
            require_relative 'filters/merge_request_date_conditions_filter'
         
     | 
| 
       7 
6 
     | 
    
         
             
            require_relative 'filters/votes_conditions_filter'
         
     | 
| 
       8 
7 
     | 
    
         
             
            require_relative 'filters/forbidden_labels_conditions_filter'
         
     | 
| 
         @@ -16,6 +15,7 @@ require_relative 'policies/rule_policy' 
     | 
|
| 
       16 
15 
     | 
    
         
             
            require_relative 'policies/summary_policy'
         
     | 
| 
       17 
16 
     | 
    
         
             
            require_relative 'policies_resources/rule_resources'
         
     | 
| 
       18 
17 
     | 
    
         
             
            require_relative 'policies_resources/summary_resources'
         
     | 
| 
      
 18 
     | 
    
         
            +
            require_relative 'api_query_builders/date_query_param_builder'
         
     | 
| 
       19 
19 
     | 
    
         
             
            require_relative 'api_query_builders/single_query_param_builder'
         
     | 
| 
       20 
20 
     | 
    
         
             
            require_relative 'api_query_builders/multi_query_param_builder'
         
     | 
| 
       21 
21 
     | 
    
         
             
            require_relative 'url_builders/url_builder'
         
     | 
| 
         @@ -38,6 +38,7 @@ module Gitlab 
     | 
|
| 
       38 
38 
     | 
    
         
             
                    @options = options
         
     | 
| 
       39 
39 
     | 
    
         
             
                    @network_adapter_class = network_adapter_class
         
     | 
| 
       40 
40 
     | 
    
         | 
| 
      
 41 
     | 
    
         
            +
                    assert_all!
         
     | 
| 
       41 
42 
     | 
    
         
             
                    assert_project_id!
         
     | 
| 
       42 
43 
     | 
    
         
             
                    assert_token!
         
     | 
| 
       43 
44 
     | 
    
         
             
                    require_ruby_files
         
     | 
| 
         @@ -66,6 +67,7 @@ module Gitlab 
     | 
|
| 
       66 
67 
     | 
    
         | 
| 
       67 
68 
     | 
    
         
             
                  def assert_project_id!
         
     | 
| 
       68 
69 
     | 
    
         
             
                    return if options.source_id
         
     | 
| 
      
 70 
     | 
    
         
            +
                    return if options.all
         
     | 
| 
       69 
71 
     | 
    
         | 
| 
       70 
72 
     | 
    
         
             
                    raise ArgumentError, 'A project_id is needed (pass it with the `--source-id` option)!'
         
     | 
| 
       71 
73 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -76,6 +78,11 @@ module Gitlab 
     | 
|
| 
       76 
78 
     | 
    
         
             
                    raise ArgumentError, 'A token is needed (pass it with the `--token` option)!'
         
     | 
| 
       77 
79 
     | 
    
         
             
                  end
         
     | 
| 
       78 
80 
     | 
    
         | 
| 
      
 81 
     | 
    
         
            +
                  def assert_all!
         
     | 
| 
      
 82 
     | 
    
         
            +
                    raise ArgumentError, '--all-projects option cannot be used in conjunction with --source and --source-id option!' if
         
     | 
| 
      
 83 
     | 
    
         
            +
                      options.all && (options.source || options.source_id)
         
     | 
| 
      
 84 
     | 
    
         
            +
                  end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
       79 
86 
     | 
    
         
             
                  def require_ruby_files
         
     | 
| 
       80 
87 
     | 
    
         
             
                    options.require_files.each(&method(:require))
         
     | 
| 
       81 
88 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -146,7 +153,7 @@ module Gitlab 
     | 
|
| 
       146 
153 
     | 
    
         
             
                  end
         
     | 
| 
       147 
154 
     | 
    
         | 
| 
       148 
155 
     | 
    
         
             
                  def resources_for_rule(resource_type, rule)
         
     | 
| 
       149 
     | 
    
         
            -
                    puts Gitlab::Triage::UI.header(" 
     | 
| 
      
 156 
     | 
    
         
            +
                    puts Gitlab::Triage::UI.header("Gathering resources for rule: **#{rule[:name]}**", char: '-')
         
     | 
| 
       150 
157 
     | 
    
         | 
| 
       151 
158 
     | 
    
         
             
                    ExpandCondition.perform(rule_conditions(rule)) do |conditions|
         
     | 
| 
       152 
159 
     | 
    
         
             
                      # retrieving the resources for every rule is inefficient
         
     | 
| 
         @@ -186,22 +193,35 @@ module Gitlab 
     | 
|
| 
       186 
193 
     | 
    
         
             
                    resources.select do |resource|
         
     | 
| 
       187 
194 
     | 
    
         
             
                      results = []
         
     | 
| 
       188 
195 
     | 
    
         | 
| 
      
 196 
     | 
    
         
            +
                      # rubocop:disable Style/IfUnlessModifier
         
     | 
| 
       189 
197 
     | 
    
         
             
                      if conditions[:date]
         
     | 
| 
       190 
     | 
    
         
            -
                        results <<  
     | 
| 
       191 
     | 
    
         
            -
             
     | 
| 
       192 
     | 
    
         
            -
             
     | 
| 
       193 
     | 
    
         
            -
             
     | 
| 
       194 
     | 
    
         
            -
             
     | 
| 
       195 
     | 
    
         
            -
             
     | 
| 
       196 
     | 
    
         
            -
             
     | 
| 
       197 
     | 
    
         
            -
             
     | 
| 
      
 198 
     | 
    
         
            +
                        results << Filters::MergeRequestDateConditionsFilter.new(resource, conditions[:date]).calculate
         
     | 
| 
      
 199 
     | 
    
         
            +
                      end
         
     | 
| 
      
 200 
     | 
    
         
            +
             
     | 
| 
      
 201 
     | 
    
         
            +
                      if conditions[:upvotes]
         
     | 
| 
      
 202 
     | 
    
         
            +
                        results << Filters::VotesConditionsFilter.new(resource, conditions[:upvotes]).calculate
         
     | 
| 
      
 203 
     | 
    
         
            +
                      end
         
     | 
| 
      
 204 
     | 
    
         
            +
             
     | 
| 
      
 205 
     | 
    
         
            +
                      if conditions[:forbidden_labels]
         
     | 
| 
      
 206 
     | 
    
         
            +
                        results << Filters::ForbiddenLabelsConditionsFilter.new(resource, conditions[:forbidden_labels]).calculate
         
     | 
| 
      
 207 
     | 
    
         
            +
                      end
         
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
      
 209 
     | 
    
         
            +
                      if conditions[:no_additional_labels]
         
     | 
| 
      
 210 
     | 
    
         
            +
                        results << Filters::NoAdditionalLabelsConditionsFilter.new(resource, conditions.fetch(:labels) { [] }).calculate
         
     | 
| 
       198 
211 
     | 
    
         
             
                      end
         
     | 
| 
       199 
     | 
    
         
            -
             
     | 
| 
       200 
     | 
    
         
            -
                       
     | 
| 
       201 
     | 
    
         
            -
             
     | 
| 
       202 
     | 
    
         
            -
                       
     | 
| 
       203 
     | 
    
         
            -
             
     | 
| 
       204 
     | 
    
         
            -
                       
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
                      if conditions[:author_member]
         
     | 
| 
      
 214 
     | 
    
         
            +
                        results << Filters::AuthorMemberConditionsFilter.new(resource, conditions[:author_member], network).calculate
         
     | 
| 
      
 215 
     | 
    
         
            +
                      end
         
     | 
| 
      
 216 
     | 
    
         
            +
             
     | 
| 
      
 217 
     | 
    
         
            +
                      if conditions[:assignee_member]
         
     | 
| 
      
 218 
     | 
    
         
            +
                        results << Filters::AssigneeMemberConditionsFilter.new(resource, conditions[:assignee_member], network).calculate
         
     | 
| 
      
 219 
     | 
    
         
            +
                      end
         
     | 
| 
      
 220 
     | 
    
         
            +
             
     | 
| 
      
 221 
     | 
    
         
            +
                      if conditions[:ruby]
         
     | 
| 
      
 222 
     | 
    
         
            +
                        results << Filters::RubyConditionsFilter.new(resource, conditions, network).calculate
         
     | 
| 
      
 223 
     | 
    
         
            +
                      end
         
     | 
| 
      
 224 
     | 
    
         
            +
                      # rubocop:enable Style/IfUnlessModifier
         
     | 
| 
       205 
225 
     | 
    
         | 
| 
       206 
226 
     | 
    
         
             
                      results.all?
         
     | 
| 
       207 
227 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -229,12 +249,17 @@ module Gitlab 
     | 
|
| 
       229 
249 
     | 
    
         
             
                    condition_builders << APIQueryBuilders::SingleQueryParamBuilder.new('source_branch', conditions[:source_branch]) if conditions[:source_branch]
         
     | 
| 
       230 
250 
     | 
    
         
             
                    condition_builders << APIQueryBuilders::SingleQueryParamBuilder.new('target_branch', conditions[:target_branch]) if conditions[:target_branch]
         
     | 
| 
       231 
251 
     | 
    
         | 
| 
      
 252 
     | 
    
         
            +
                    if conditions[:date] && APIQueryBuilders::DateQueryParamBuilder.applicable?(conditions[:date])
         
     | 
| 
      
 253 
     | 
    
         
            +
                      condition_builders << APIQueryBuilders::DateQueryParamBuilder.new(conditions.delete(:date))
         
     | 
| 
      
 254 
     | 
    
         
            +
                    end
         
     | 
| 
      
 255 
     | 
    
         
            +
             
     | 
| 
       232 
256 
     | 
    
         
             
                    condition_builders.each do |condition_builder|
         
     | 
| 
       233 
257 
     | 
    
         
             
                      params[condition_builder.param_name] = condition_builder.param_content
         
     | 
| 
       234 
258 
     | 
    
         
             
                    end
         
     | 
| 
       235 
259 
     | 
    
         | 
| 
       236 
260 
     | 
    
         
             
                    UrlBuilders::UrlBuilder.new(
         
     | 
| 
       237 
261 
     | 
    
         
             
                      network_options: options,
         
     | 
| 
      
 262 
     | 
    
         
            +
                      all: options.all,
         
     | 
| 
       238 
263 
     | 
    
         
             
                      source: options.source,
         
     | 
| 
       239 
264 
     | 
    
         
             
                      source_id: options.source_id,
         
     | 
| 
       240 
265 
     | 
    
         
             
                      resource_type: resource_type,
         
     | 
    
        data/lib/gitlab/triage/errors.rb
    CHANGED
    
    | 
         @@ -1 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
      
 1 
     | 
    
         
            +
            require_relative 'errors/network'
         
     | 
| 
         @@ -1,21 +1,67 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require_relative ' 
     | 
| 
      
 1 
     | 
    
         
            +
            require_relative 'base_conditions_filter'
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module Gitlab
         
     | 
| 
       4 
4 
     | 
    
         
             
              module Triage
         
     | 
| 
       5 
5 
     | 
    
         
             
                module Filters
         
     | 
| 
       6 
     | 
    
         
            -
                  class MergeRequestDateConditionsFilter <  
     | 
| 
       7 
     | 
    
         
            -
                    ATTRIBUTES = %w[ 
     | 
| 
      
 6 
     | 
    
         
            +
                  class MergeRequestDateConditionsFilter < BaseConditionsFilter
         
     | 
| 
      
 7 
     | 
    
         
            +
                    ATTRIBUTES = %w[merged_at].freeze
         
     | 
| 
      
 8 
     | 
    
         
            +
                    CONDITIONS = %w[older_than newer_than].freeze
         
     | 
| 
      
 9 
     | 
    
         
            +
                    INTERVAL_TYPES = %w[days weeks months years].freeze
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                    def self.allowed_attributes
         
     | 
| 
      
 12 
     | 
    
         
            +
                      self::ATTRIBUTES
         
     | 
| 
      
 13 
     | 
    
         
            +
                    end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    def self.filter_parameters
         
     | 
| 
      
 16 
     | 
    
         
            +
                      [
         
     | 
| 
      
 17 
     | 
    
         
            +
                        {
         
     | 
| 
      
 18 
     | 
    
         
            +
                          name: :attribute,
         
     | 
| 
      
 19 
     | 
    
         
            +
                          type: String,
         
     | 
| 
      
 20 
     | 
    
         
            +
                          values: allowed_attributes
         
     | 
| 
      
 21 
     | 
    
         
            +
                        },
         
     | 
| 
      
 22 
     | 
    
         
            +
                        {
         
     | 
| 
      
 23 
     | 
    
         
            +
                          name: :condition,
         
     | 
| 
      
 24 
     | 
    
         
            +
                          type: String,
         
     | 
| 
      
 25 
     | 
    
         
            +
                          values: CONDITIONS
         
     | 
| 
      
 26 
     | 
    
         
            +
                        },
         
     | 
| 
      
 27 
     | 
    
         
            +
                        {
         
     | 
| 
      
 28 
     | 
    
         
            +
                          name: :interval_type,
         
     | 
| 
      
 29 
     | 
    
         
            +
                          type: String,
         
     | 
| 
      
 30 
     | 
    
         
            +
                          values: INTERVAL_TYPES
         
     | 
| 
      
 31 
     | 
    
         
            +
                        },
         
     | 
| 
      
 32 
     | 
    
         
            +
                        {
         
     | 
| 
      
 33 
     | 
    
         
            +
                          name: :interval,
         
     | 
| 
      
 34 
     | 
    
         
            +
                          type: Numeric
         
     | 
| 
      
 35 
     | 
    
         
            +
                        }
         
     | 
| 
      
 36 
     | 
    
         
            +
                      ]
         
     | 
| 
      
 37 
     | 
    
         
            +
                    end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    def initialize_variables(condition)
         
     | 
| 
      
 40 
     | 
    
         
            +
                      @attribute = condition[:attribute].to_sym
         
     | 
| 
      
 41 
     | 
    
         
            +
                      @condition = condition[:condition].to_sym
         
     | 
| 
      
 42 
     | 
    
         
            +
                      @interval_type = condition[:interval_type].to_sym
         
     | 
| 
      
 43 
     | 
    
         
            +
                      @interval = condition[:interval]
         
     | 
| 
      
 44 
     | 
    
         
            +
                    end
         
     | 
| 
       8 
45 
     | 
    
         | 
| 
       9 
46 
     | 
    
         
             
                    # Guard against merge requests with no merged_at values
         
     | 
| 
       10 
47 
     | 
    
         
             
                    def resource_value
         
     | 
| 
       11 
     | 
    
         
            -
                       
     | 
| 
      
 48 
     | 
    
         
            +
                      @resource[@attribute]&.to_date
         
     | 
| 
      
 49 
     | 
    
         
            +
                    end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    def condition_value
         
     | 
| 
      
 52 
     | 
    
         
            +
                      @interval.public_send(@interval_type).ago.to_date # rubocop:disable GitlabSecurity/PublicSend
         
     | 
| 
       12 
53 
     | 
    
         
             
                    end
         
     | 
| 
       13 
54 
     | 
    
         | 
| 
       14 
55 
     | 
    
         
             
                    # Guard against merge requests with no merged_at values
         
     | 
| 
       15 
56 
     | 
    
         
             
                    def calculate
         
     | 
| 
       16 
57 
     | 
    
         
             
                      return false unless resource_value
         
     | 
| 
       17 
58 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
                       
     | 
| 
      
 59 
     | 
    
         
            +
                      case @condition
         
     | 
| 
      
 60 
     | 
    
         
            +
                      when :older_than
         
     | 
| 
      
 61 
     | 
    
         
            +
                        resource_value < condition_value
         
     | 
| 
      
 62 
     | 
    
         
            +
                      when :newer_than
         
     | 
| 
      
 63 
     | 
    
         
            +
                        resource_value > condition_value
         
     | 
| 
      
 64 
     | 
    
         
            +
                      end
         
     | 
| 
       19 
65 
     | 
    
         
             
                    end
         
     | 
| 
       20 
66 
     | 
    
         
             
                  end
         
     | 
| 
       21 
67 
     | 
    
         
             
                end
         
     | 
| 
         @@ -31,11 +31,12 @@ module Gitlab 
     | 
|
| 
       31 
31 
     | 
    
         | 
| 
       32 
32 
     | 
    
         
             
                    begin
         
     | 
| 
       33 
33 
     | 
    
         
             
                      print '.'
         
     | 
| 
      
 34 
     | 
    
         
            +
                      url = response.fetch(:next_page_url) { url }
         
     | 
| 
       34 
35 
     | 
    
         | 
| 
       35 
36 
     | 
    
         
             
                      response = execute_with_retry([Net::ReadTimeout, Errors::Network::InternalServerError]) do
         
     | 
| 
       36 
37 
     | 
    
         
             
                        puts Gitlab::Triage::UI.debug "query_api: #{url}" if options.debug
         
     | 
| 
       37 
38 
     | 
    
         | 
| 
       38 
     | 
    
         
            -
                        @adapter.get(token,  
     | 
| 
      
 39 
     | 
    
         
            +
                        @adapter.get(token, url)
         
     | 
| 
       39 
40 
     | 
    
         
             
                      end
         
     | 
| 
       40 
41 
     | 
    
         | 
| 
       41 
42 
     | 
    
         
             
                      results = response.delete(:results)
         
     | 
| 
         @@ -22,7 +22,7 @@ module Gitlab 
     | 
|
| 
       22 
22 
     | 
    
         | 
| 
       23 
23 
     | 
    
         
             
                      {
         
     | 
| 
       24 
24 
     | 
    
         
             
                        more_pages: (response.headers["x-next-page"].to_s != ""),
         
     | 
| 
       25 
     | 
    
         
            -
                        next_page_url: url  
     | 
| 
      
 25 
     | 
    
         
            +
                        next_page_url: next_page_url(url, response),
         
     | 
| 
       26 
26 
     | 
    
         
             
                        results: response.parsed_response,
         
     | 
| 
       27 
27 
     | 
    
         
             
                        ratelimit_remaining: response.headers["ratelimit-remaining"].to_i,
         
     | 
| 
       28 
28 
     | 
    
         
             
                        ratelimit_reset_at: Time.at(response.headers["ratelimit-reset"].to_i)
         
     | 
| 
         @@ -66,6 +66,18 @@ module Gitlab 
     | 
|
| 
       66 
66 
     | 
    
         | 
| 
       67 
67 
     | 
    
         
             
                      raise Errors::Network::InternalServerError, 'Internal server error encountered!'
         
     | 
| 
       68 
68 
     | 
    
         
             
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                    def next_page_url(url, response)
         
     | 
| 
      
 71 
     | 
    
         
            +
                      return unless response.headers['x-next-page'].present?
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                      next_page = "&page=#{response.headers['x-next-page']}"
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                      if url.include?('&page')
         
     | 
| 
      
 76 
     | 
    
         
            +
                        url.gsub(/&page=\d+/, next_page)
         
     | 
| 
      
 77 
     | 
    
         
            +
                      else
         
     | 
| 
      
 78 
     | 
    
         
            +
                        url + next_page
         
     | 
| 
      
 79 
     | 
    
         
            +
                      end
         
     | 
| 
      
 80 
     | 
    
         
            +
                    end
         
     | 
| 
       69 
81 
     | 
    
         
             
                  end
         
     | 
| 
       70 
82 
     | 
    
         
             
                end
         
     | 
| 
       71 
83 
     | 
    
         
             
              end
         
     | 
| 
         @@ -23,6 +23,10 @@ module Gitlab 
     | 
|
| 
       23 
23 
     | 
    
         
             
                          options.policies_files << value
         
     | 
| 
       24 
24 
     | 
    
         
             
                        end
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
      
 26 
     | 
    
         
            +
                        opts.on('--all-projects', 'Process all projects the token has access to') do |value|
         
     | 
| 
      
 27 
     | 
    
         
            +
                          options.all = value
         
     | 
| 
      
 28 
     | 
    
         
            +
                        end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
       26 
30 
     | 
    
         
             
                        opts.on('-s', '--source [type]', [:projects, :groups], 'The source type between [ projects or groups ], default value: projects') do |value|
         
     | 
| 
       27 
31 
     | 
    
         
             
                          options.source = value
         
     | 
| 
       28 
32 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -59,6 +63,12 @@ module Gitlab 
     | 
|
| 
       59 
63 
     | 
    
         
             
                          exit # rubocop:disable Rails/Exit
         
     | 
| 
       60 
64 
     | 
    
         
             
                        end
         
     | 
| 
       61 
65 
     | 
    
         | 
| 
      
 66 
     | 
    
         
            +
                        opts.on('-v', '--version', 'Print version') do
         
     | 
| 
      
 67 
     | 
    
         
            +
                          require_relative 'version'
         
     | 
| 
      
 68 
     | 
    
         
            +
                          $stdout.puts Gitlab::Triage::VERSION
         
     | 
| 
      
 69 
     | 
    
         
            +
                          exit # rubocop:disable Rails/Exit
         
     | 
| 
      
 70 
     | 
    
         
            +
                        end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
       62 
72 
     | 
    
         
             
                        opts.on('--init', 'Initialize the project with a policy file') do
         
     | 
| 
       63 
73 
     | 
    
         
             
                          example_path =
         
     | 
| 
       64 
74 
     | 
    
         
             
                            File.expand_path('../../../support/.triage-policies.example.yml', __dir__)
         
     | 
| 
         @@ -3,6 +3,7 @@ module Gitlab 
     | 
|
| 
       3 
3 
     | 
    
         
             
                Options = Struct.new(
         
     | 
| 
       4 
4 
     | 
    
         
             
                  :dry_run,
         
     | 
| 
       5 
5 
     | 
    
         
             
                  :policies_files,
         
     | 
| 
      
 6 
     | 
    
         
            +
                  :all,
         
     | 
| 
       6 
7 
     | 
    
         
             
                  :source,
         
     | 
| 
       7 
8 
     | 
    
         
             
                  :source_id,
         
     | 
| 
       8 
9 
     | 
    
         
             
                  :token,
         
     | 
| 
         @@ -17,6 +18,7 @@ module Gitlab 
     | 
|
| 
       17 
18 
     | 
    
         
             
                    # Defaults
         
     | 
| 
       18 
19 
     | 
    
         
             
                    self.host_url ||= 'https://gitlab.com'
         
     | 
| 
       19 
20 
     | 
    
         
             
                    self.api_version ||= 'v4'
         
     | 
| 
      
 21 
     | 
    
         
            +
                    self.all ||= false
         
     | 
| 
       20 
22 
     | 
    
         
             
                    self.source ||= 'projects'
         
     | 
| 
       21 
23 
     | 
    
         
             
                    self.require_files ||= []
         
     | 
| 
       22 
24 
     | 
    
         
             
                    self.policies_files ||= Set.new
         
     | 
| 
         @@ -10,7 +10,7 @@ module Gitlab 
     | 
|
| 
       10 
10 
     | 
    
         
             
                    # Build an issue from several rules policies
         
     | 
| 
       11 
11 
     | 
    
         
             
                    def build_issue
         
     | 
| 
       12 
12 
     | 
    
         
             
                      action = actions[:summarize]
         
     | 
| 
       13 
     | 
    
         
            -
                      issues = resources. 
     | 
| 
      
 13 
     | 
    
         
            +
                      issues = resources.map do |inner_policy_spec, inner_resources|
         
     | 
| 
       14 
14 
     | 
    
         
             
                        Policies::RulePolicy.new(
         
     | 
| 
       15 
15 
     | 
    
         
             
                          type, inner_policy_spec, inner_resources, network)
         
     | 
| 
       16 
16 
     | 
    
         
             
                          .build_issue
         
     | 
| 
         @@ -1,20 +1,19 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            require 'forwardable'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
       3 
5 
     | 
    
         
             
            module Gitlab
         
     | 
| 
       4 
6 
     | 
    
         
             
              module Triage
         
     | 
| 
       5 
7 
     | 
    
         
             
                module PoliciesResources
         
     | 
| 
       6 
8 
     | 
    
         
             
                  class RuleResources
         
     | 
| 
       7 
     | 
    
         
            -
                     
     | 
| 
      
 9 
     | 
    
         
            +
                    include Enumerable
         
     | 
| 
      
 10 
     | 
    
         
            +
                    extend Forwardable
         
     | 
| 
       8 
11 
     | 
    
         | 
| 
       9 
12 
     | 
    
         
             
                    def initialize(new_resources)
         
     | 
| 
       10 
13 
     | 
    
         
             
                      @resources = new_resources
         
     | 
| 
       11 
14 
     | 
    
         
             
                    end
         
     | 
| 
       12 
15 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
                     
     | 
| 
       14 
     | 
    
         
            -
                      resources.each do |resource|
         
     | 
| 
       15 
     | 
    
         
            -
                        yield(resource)
         
     | 
| 
       16 
     | 
    
         
            -
                      end
         
     | 
| 
       17 
     | 
    
         
            -
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
                    def_delegator :@resources, :each
         
     | 
| 
       18 
17 
     | 
    
         
             
                  end
         
     | 
| 
       19 
18 
     | 
    
         
             
                end
         
     | 
| 
       20 
19 
     | 
    
         
             
              end
         
     |