gitlab-triage 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ab21a6dffa12d92f9321ac3c6d2bc0c92627fad703fceb7ebf68494d8f5b259
4
- data.tar.gz: e5868058935e55d70ccadaada8030a8bec92dee6ceeeea2f9996cd60f3823cdf
3
+ metadata.gz: 0b8300cf129b3aefc203d528814c84eb8e06fa54154599b1b4e818f9365ab93c
4
+ data.tar.gz: e9d4b656207d0fa3322e10cd8618d6ac4bed5122b02f2dca34220d576cf81f57
5
5
  SHA512:
6
- metadata.gz: a875bebf70cd7dcc2a6c5f064d692535cdf98b664323fb640b22fed7f52ac4d5f49e8b21adb5b4942f626e4f4638d23f3042109ae13c495ae9c732d177e9298f
7
- data.tar.gz: 01a627062e23ba73d40be5cc7260a92aa7be9ec30b9fb694585305ae919435174099a701d6045998c03738ee7fd7dcf0cac9ebf821abfea9b4697fd6f8f55e06
6
+ metadata.gz: 2ceb150c8d07902495e80852aa914c91a14bbd82f84ab4123713f086282a5a7445bb141228eb50a9caef65d78957aecc0e889ec948a95193c046d659feaf31ba
7
+ data.tar.gz: b5e183ed3ab41aea72b54c4eb790d24e61c2422297d652139b22170da2cab69a04fe38e07e5de0ba9c99d95fd1a0a9c8c3169a7241f62bafffb94c2947a5263b
data/README.md CHANGED
@@ -46,6 +46,8 @@ resource_rules:
46
46
  state: opened
47
47
  labels:
48
48
  - No Label
49
+ limits:
50
+ most_recent: 50
49
51
  actions:
50
52
  labels:
51
53
  - needs attention
@@ -63,6 +65,7 @@ resource_rules:
63
65
  A policy consists of the following fields:
64
66
  - [Name field](#name-field)
65
67
  - [Conditions field](#conditions-field)
68
+ - [Limits field](#limits-field)
66
69
  - [Actions field](#actions-field)
67
70
 
68
71
  #### Name field
@@ -381,6 +384,30 @@ Here's a list of currently available API:
381
384
  | succ | Milestone | The next active milestone beside this milestone |
382
385
  | active? | Boolean | `true` if `state` is `active`; `false` otherwise |
383
386
 
387
+ #### Limits field
388
+
389
+ Limits restrict the number of resources on which an action is carried out. They
390
+ can be useful when combined with conditions that return a large number of
391
+ resources. For example, if the conditions are satisfied by thousands of issues a
392
+ limit can be configured to process only fifty of them to avoid making an
393
+ overwhelming number of changes at once.
394
+
395
+ Accepts a key and value pair where the key is `most_recent` or `oldest`and the
396
+ value is the number of resources to act on. The following table outlines how
397
+ each key affects the sorting and order of resources that it limits.
398
+
399
+ | Name / Key | Sorted by | Order |
400
+ | --------- | ---- | ------ |
401
+ | `most_recent` | `created_at` | descending |
402
+ | `oldest` | `created_at` | ascending |
403
+
404
+ Example:
405
+
406
+ ```yml
407
+ limits:
408
+ most_recent: 50
409
+ ```
410
+
384
411
  #### Actions field
385
412
 
386
413
  Used to declare an action to be carried out on a resource if **all** conditions are satisfied.
@@ -8,6 +8,7 @@ require_relative 'filters/no_additional_labels_conditions_filter'
8
8
  require_relative 'filters/author_member_conditions_filter'
9
9
  require_relative 'filters/assignee_member_conditions_filter'
10
10
  require_relative 'filters/ruby_conditions_filter'
11
+ require_relative 'limiters/date_field_limiter'
11
12
  require_relative 'command_builders/comment_body_builder'
12
13
  require_relative 'command_builders/comment_command_builder'
13
14
  require_relative 'command_builders/label_command_builder'
@@ -88,20 +89,27 @@ module Gitlab
88
89
  rule.fetch(:actions) { {} }
89
90
  end
90
91
 
92
+ def rule_limits(rule)
93
+ rule.fetch(:limits) { {} }
94
+ end
95
+
91
96
  def process_rule(resource_type, rule)
92
97
  ExpandCondition.perform(rule_conditions(rule)) do |conditions|
93
98
  # retrieving the resources for every rule is inefficient
94
99
  # however, previous rules may affect those upcoming
95
100
  resources = network.query_api(options.token, build_get_url(resource_type, conditions))
96
101
  puts "\n\n* Found #{resources.count} resources..."
102
+ print "* Filtering resources..."
103
+ resources = filter_resources(resources, conditions)
104
+ puts "\n* Total after filtering: #{resources.count} resources"
97
105
  print "* Limiting resources..."
98
- resources = limit_resources(resources, conditions)
99
- puts "\n* Total resource after limiting: #{resources.count} resources"
106
+ resources = limit_resources(resources, rule_limits(rule))
107
+ puts "\n* Total after limiting: #{resources.count} resources"
100
108
  process_resources(resource_type, resources, rule)
101
109
  end
102
110
  end
103
111
 
104
- def limit_resources(resources, conditions)
112
+ def filter_resources(resources, conditions)
105
113
  net = { host_url: host_url, api_version: api_version, token: options.token, network: network }
106
114
 
107
115
  resources.select do |resource|
@@ -119,6 +127,14 @@ module Gitlab
119
127
  end
120
128
  end
121
129
 
130
+ def limit_resources(resources, limits)
131
+ if limits.empty?
132
+ resources
133
+ else
134
+ Limiters::DateFieldLimiter.new(resources, limits).limit
135
+ end
136
+ end
137
+
122
138
  def process_resources(resource_type, resources, rule)
123
139
  if options.dry_run
124
140
  puts "\nThe following comments would be posted for the rule **#{rule[:name]}**:\n\n"
@@ -1,4 +1,5 @@
1
1
  require 'active_support/all'
2
+ require_relative '../validators/params_validator'
2
3
 
3
4
  module Gitlab
4
5
  module Triage
@@ -47,33 +48,10 @@ module Gitlab
47
48
  private
48
49
 
49
50
  def validate_condition(condition)
50
- validate_required_parameters(condition)
51
- validate_parameter_types(condition)
52
- validate_parameter_content(condition)
51
+ ParamsValidator.new(self.class.filter_parameters, condition).validate!
53
52
  end
54
53
 
55
54
  def initialize_variables(condition); end
56
-
57
- def validate_required_parameters(condition)
58
- self.class.filter_parameters.each do |param|
59
- raise ArgumentError, "#{param[:name]} is a required parameter" unless condition[param[:name]]
60
- end
61
- end
62
-
63
- def validate_parameter_types(condition)
64
- self.class.filter_parameters.each do |param|
65
- param_types = Array(param[:type]).flatten
66
- raise ArgumentError, "#{param[:name]} must be of type #{param[:type]}" unless param_types.any? { |type| condition[param[:name]].is_a?(type) }
67
- end
68
- end
69
-
70
- def validate_parameter_content(condition)
71
- self.class.filter_parameters.each do |param|
72
- if param[:values]
73
- raise ArgumentError, "#{param[:name]} must be of one of #{param[:values].join(',')}" unless param[:values].include?(condition[param[:name]])
74
- end
75
- end
76
- end
77
55
  end
78
56
  end
79
57
  end
@@ -0,0 +1,35 @@
1
+ require 'active_support/all'
2
+
3
+ module Gitlab
4
+ module Triage
5
+ module Limiters
6
+ class BaseLimiter
7
+ def initialize(resources, limit)
8
+ @resources = initialize_resources(resources)
9
+ validate_limit(limit)
10
+ initialize_variables(limit)
11
+ end
12
+
13
+ def limit
14
+ raise NotImplementedError
15
+ end
16
+
17
+ def self.limiter_parameters
18
+ []
19
+ end
20
+
21
+ private
22
+
23
+ def initialize_variables(limit); end
24
+
25
+ def initialize_resources(resources)
26
+ resources
27
+ end
28
+
29
+ def validate_limit(limit)
30
+ LimiterValidator.new(self.class.limiter_parameters, limit).validate!
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,45 @@
1
+ require_relative 'base_limiter'
2
+ require_relative '../validators/limiter_validator'
3
+
4
+ module Gitlab
5
+ module Triage
6
+ module Limiters
7
+ class DateFieldLimiter < BaseLimiter
8
+ LIMITS = %i[most_recent oldest].freeze
9
+
10
+ def self.limiter_parameters
11
+ [
12
+ {
13
+ name: :most_recent,
14
+ type: Integer
15
+ },
16
+ {
17
+ name: :oldest,
18
+ type: Integer
19
+ }
20
+ ]
21
+ end
22
+
23
+ def initialize_variables(limit)
24
+ @criterion = LIMITS.find(&limit.method(:[]))
25
+ @threshold = limit[@criterion]
26
+ end
27
+
28
+ def limit
29
+ case @criterion
30
+ when :most_recent
31
+ @resources.first(@threshold)
32
+ when :oldest
33
+ @resources.last(@threshold)
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def initialize_resources(resources)
40
+ resources.sort_by { |res| res[:created_at] }
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,19 @@
1
+ require_relative 'params_validator'
2
+
3
+ module Gitlab
4
+ module Triage
5
+ class LimiterValidator < ParamsValidator
6
+ private
7
+
8
+ def params_limiter_names
9
+ @parameter_definitions.map do |param|
10
+ param[:name]
11
+ end
12
+ end
13
+
14
+ def validate_required_parameters(value)
15
+ raise ArgumentError, "For the limits field, please specify one of: `#{params_limiter_names.join('`, `')}`" unless value.keys.map(&:to_sym).one? { |key| params_limiter_names.include?(key) }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,41 @@
1
+ module Gitlab
2
+ module Triage
3
+ class ParamsValidator
4
+ def initialize(parameter_definitions, value)
5
+ @parameter_definitions = parameter_definitions
6
+ @value = value
7
+ end
8
+
9
+ def validate!
10
+ validate_required_parameters(@value)
11
+ validate_parameter_types(@value)
12
+ validate_parameter_content(@value)
13
+ end
14
+
15
+ private
16
+
17
+ def validate_required_parameters(value)
18
+ @parameter_definitions.each do |param|
19
+ raise ArgumentError, "#{param[:name]} is a required parameter" unless value[param[:name]]
20
+ end
21
+ end
22
+
23
+ def validate_parameter_types(value)
24
+ @parameter_definitions.each do |param|
25
+ if value.has_key?(param[:name])
26
+ param_types = Array(param[:type]).flatten
27
+ raise ArgumentError, "#{param[:name]} must be of type #{param[:type]}" unless param_types.any? { |type| value[param[:name]].is_a?(type) }
28
+ end
29
+ end
30
+ end
31
+
32
+ def validate_parameter_content(value)
33
+ @parameter_definitions.each do |param|
34
+ if param[:values]
35
+ raise ArgumentError, "#{param[:name]} must be of one of #{param[:values].join(',')}" unless param[:values].include?(value[param[:name]])
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,5 +1,5 @@
1
1
  module Gitlab
2
2
  module Triage
3
- VERSION = '0.7.0'.freeze
3
+ VERSION = '0.8.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-triage
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-10 00:00:00.000000000 Z
11
+ date: 2018-08-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -155,6 +155,8 @@ files:
155
155
  - lib/gitlab/triage/filters/no_additional_labels_conditions_filter.rb
156
156
  - lib/gitlab/triage/filters/ruby_conditions_filter.rb
157
157
  - lib/gitlab/triage/filters/votes_conditions_filter.rb
158
+ - lib/gitlab/triage/limiters/base_limiter.rb
159
+ - lib/gitlab/triage/limiters/date_field_limiter.rb
158
160
  - lib/gitlab/triage/network.rb
159
161
  - lib/gitlab/triage/network_adapters/base_adapter.rb
160
162
  - lib/gitlab/triage/network_adapters/httparty_adapter.rb
@@ -165,6 +167,8 @@ files:
165
167
  - lib/gitlab/triage/retryable.rb
166
168
  - lib/gitlab/triage/ui.rb
167
169
  - lib/gitlab/triage/url_builders/url_builder.rb
170
+ - lib/gitlab/triage/validators/limiter_validator.rb
171
+ - lib/gitlab/triage/validators/params_validator.rb
168
172
  - lib/gitlab/triage/version.rb
169
173
  - support/.gitlab-ci.example.yml
170
174
  - support/.triage-policies.example.yml