gitlab-triage 1.41.0 → 1.42.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: 3eb3292f79448004c49e7196b24da06e6609f5a0215a985472c95de9aeac4150
4
- data.tar.gz: f6f94b45be9c7fe6cc43732e3d953455dad93e7246d69ea81162a91f6557a862
3
+ metadata.gz: 2cd7bbbde45634c445e721eba9e30e348f0d1fef2428a008d4f417f32b8184f7
4
+ data.tar.gz: 283dfe4c32c0ca14c5fbdb984c0661a522bcd1afa59af97816fc01008e30e48e
5
5
  SHA512:
6
- metadata.gz: 2b9866966f5f200c25500af8679d2206e413fdd212dba09bbf48ae63d4cb55bf1415b0afded9f308864657f5246fe55cb859769fb2564aa49b4bb0adc946145a
7
- data.tar.gz: d662bcbe691135305db76078e76d67be3073273ba4c3dd4f39d5a98a649be5ed0ed06c280869549a3bb3e7bceb74942a34aa8312e3a514ebfec835b1f343f5bd
6
+ metadata.gz: 1d80bbebf6eb2ce0eb319b8fa65ec6575e5b654135c431216a72e6486ba370a15dbc2b4bbb6c21350c08d215c98670d985ce7400d6c5072f0b79fe78551df0e9
7
+ data.tar.gz: 3a0f7060d8a6caaa63d89cafad80b3a0962e8198f9d1e4f09aab8671aeba1270f8770163599475ac7bbb33e39ad83660e7d55875425176df75fba8dd8d9f3e90
data/README.md CHANGED
@@ -4,6 +4,10 @@
4
4
 
5
5
  This project allows to automate triaging of issues and merge requests for GitLab projects or groups.
6
6
 
7
+ ## Note this Gem is not supported by the GitLab Support team
8
+
9
+ If you are a customer who has a GitLab License, **support for this gem is not covered by that license agreement as this is not part of the GitLab Product**. Feel free to open an issue in this project and the maintainers may be able to help.
10
+
7
11
  ## gitlab-triage gem
8
12
 
9
13
  ### Abstract
@@ -180,6 +184,7 @@ Available condition types:
180
184
  - [`target_branch` condition](#target-branch-condition)
181
185
  - [`health_status` condition](#health-status-condition)
182
186
  - [`weight` condition](#weight-condition)
187
+ - [`issue_type` condition](#issue-type-condition)
183
188
  - [`discussions` condition](#discussions-condition)
184
189
  - [`protected` condition](#protected-condition)
185
190
  - [`ruby` condition](#ruby-condition)
@@ -609,6 +614,25 @@ conditions:
609
614
  weight: Any
610
615
  ```
611
616
 
617
+ ##### Issue type condition
618
+
619
+ **This condition is only applicable for issues.**
620
+
621
+ Accepts a string per the [API documentation](https://docs.gitlab.com/ee/api/issues.html#list-issues). This condition can only filter by one issue type.
622
+
623
+ | Issue type | Type | Value |
624
+ | --------- | ---- | ------ |
625
+ | Regular issue | string | `issue` |
626
+ | Incident | string | `incident` |
627
+ | Test case | string | `test_case` |
628
+
629
+ Example:
630
+
631
+ ```yml
632
+ conditions:
633
+ issue_type: issue
634
+ ```
635
+
612
636
  ##### Discussions condition
613
637
 
614
638
  Accepts a hash of fields.
data/bin/gitlab-triage CHANGED
@@ -9,7 +9,11 @@ options = Gitlab::Triage::OptionParser.parse(ARGV)
9
9
  options.policies_files << '.triage-policies.yml' if options.policies_files.empty?
10
10
 
11
11
  options.policies_files.each do |policies_file|
12
- policies = HashWithIndifferentAccess.new(YAML.load_file(policies_file))
12
+ policies = if Psych::VERSION >= '4.0'
13
+ HashWithIndifferentAccess.new(YAML.load_file(policies_file, aliases: true))
14
+ else
15
+ HashWithIndifferentAccess.new(YAML.load_file(policies_file))
16
+ end
13
17
 
14
18
  policy_engine = Gitlab::Triage::Engine
15
19
  .new(policies: policies, options: options)
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
  spec.summary = 'GitLab triage automation project.'
12
12
  spec.homepage = 'https://gitlab.com/gitlab-org/ruby/gems/gitlab-triage'
13
13
  spec.license = 'MIT'
14
- spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
14
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
15
15
 
16
16
  spec.metadata["allowed_push_host"] = "https://rubygems.org"
17
17
 
@@ -31,6 +31,12 @@ Gem::Specification.new do |spec|
31
31
  spec.add_dependency 'activesupport', '>= 5.1'
32
32
  spec.add_dependency 'globalid', '~> 0.4'
33
33
  spec.add_dependency 'graphql-client', '~> 0.16'
34
+ # Workaround - pin graphql version
35
+ # see: https://github.com/github/graphql-client/issues/310
36
+ # see: https://github.com/rmosolgo/graphql-ruby/pull/4577
37
+ # see: https://github.com/github/graphql-client/pull/314
38
+ # We can remove this check once PR 314 is merged and released
39
+ spec.add_dependency 'graphql', '< 2.1.0'
34
40
  spec.add_dependency 'httparty', '~> 0.17'
35
41
 
36
42
  spec.add_development_dependency 'bundler'
@@ -35,6 +35,25 @@ module Gitlab
35
35
  class Engine
36
36
  attr_reader :per_page, :policies, :options
37
37
 
38
+ # This filter map is used to help make the filter_resource method
39
+ # smaller. We loop through each of the keys (conditions) and map
40
+ # that to the filters that will be used for it.
41
+ FILTER_MAP = {
42
+ date: {
43
+ 'branches' => Filters::BranchDateFilter,
44
+ 'issues' => Filters::IssueDateConditionsFilter,
45
+ 'merge_requests' => Filters::MergeRequestDateConditionsFilter
46
+ },
47
+ protected: Filters::BranchProtectedFilter,
48
+ assignee_member: Filters::AssigneeMemberConditionsFilter,
49
+ author_member: Filters::AuthorMemberConditionsFilter,
50
+ discussions: Filters::DiscussionsConditionsFilter,
51
+ no_additional_labels: Filters::NoAdditionalLabelsConditionsFilter,
52
+ ruby: Filters::RubyConditionsFilter,
53
+ votes: Filters::VotesConditionsFilter,
54
+ upvotes: Filters::VotesConditionsFilter
55
+ }.freeze
56
+
38
57
  DEFAULT_NETWORK_ADAPTER = Gitlab::Triage::NetworkAdapters::HttpartyAdapter
39
58
  DEFAULT_GRAPHQL_ADAPTER = Gitlab::Triage::NetworkAdapters::GraphqlAdapter
40
59
  ALLOWED_STATE_VALUES = {
@@ -361,6 +380,8 @@ module Gitlab
361
380
  puts "\n* Total after limiting: #{resources.count} resources"
362
381
  puts
363
382
 
383
+ resources = sanitize_resources(resources)
384
+
364
385
  yield(PoliciesResources::RuleResources.new(resources), expanded_conditions)
365
386
  end
366
387
  end
@@ -416,61 +437,47 @@ module Gitlab
416
437
  puts
417
438
  end
418
439
 
419
- def filter_resources(resources, conditions) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
440
+ def filter_resources(resources, conditions)
420
441
  resources.select do |resource|
421
- results = []
422
-
423
- # rubocop:disable Style/IfUnlessModifier
424
- if conditions[:date]
425
- case resource[:type]
426
- when 'branches'
427
- results << Filters::BranchDateFilter.new(resource, conditions[:date]).calculate
428
- when 'issues'
429
- if conditions.dig(:date, :filter_in_ruby)
430
- results << Filters::IssueDateConditionsFilter.new(resource, conditions[:date]).calculate
431
- end
432
- when 'merge_requests'
433
- if conditions.dig(:date, :filter_in_ruby) ||
434
- # REST API does not support filtering with merged_at,
435
- # so we have to filter it in Ruby
436
- conditions.dig(:date, :attribute) == 'merged_at'
437
- results << Filters::MergeRequestDateConditionsFilter.new(resource, conditions[:date]).calculate
438
- end
439
- end
440
- end
441
-
442
- if resource[:type] == 'branches'
443
- results << Filters::BranchProtectedFilter.new(resource, conditions[:protected]).calculate
444
- end
445
-
446
- votes_condition = conditions[:votes] || conditions[:upvotes]
447
- if votes_condition
448
- results << Filters::VotesConditionsFilter.new(resource, votes_condition).calculate
449
- end
450
-
451
- if conditions[:no_additional_labels]
452
- results << Filters::NoAdditionalLabelsConditionsFilter.new(resource, conditions.fetch(:labels) { [] }).calculate
453
- end
442
+ filter_resource(resource, conditions)
443
+ end
444
+ end
454
445
 
455
- if conditions[:author_member]
456
- results << Filters::AuthorMemberConditionsFilter.new(resource, conditions[:author_member], network).calculate
457
- end
446
+ def filter_resource(resource, conditions)
447
+ results = []
458
448
 
459
- if conditions[:assignee_member]
460
- results << Filters::AssigneeMemberConditionsFilter.new(resource, conditions[:assignee_member], network).calculate
461
- end
449
+ FILTER_MAP.each do |condition_key, filter_value|
450
+ # Skips to the next key value pair if the condition is not applicable
451
+ next unless conditions[condition_key]
462
452
 
463
- if conditions[:discussions]
464
- results << Filters::DiscussionsConditionsFilter.new(resource, conditions[:discussions]).calculate
465
- end
453
+ case filter_value
454
+ when Hash
455
+ filter_in_ruby = conditions[condition_key].dig(:filter_in_ruby)
456
+ merged_at = conditions[condition_key].dig(:attribute) == 'merged_at'
457
+ filter_branch = conditions.dig(:date) && resource[:type] == 'branches'
466
458
 
467
- if conditions[:ruby]
468
- results << Filters::RubyConditionsFilter.new(resource, conditions, network).calculate
459
+ # Set the filter to the resource type
460
+ if filter_in_ruby || merged_at || filter_branch
461
+ filter = filter_value[resource[:type]]
462
+ results << filter.new(resource, conditions[condition_key]).calculate
463
+ end
464
+ else
465
+ # The `filter_value` set is not of type `hash`
466
+ filter = filter_value
467
+
468
+ # If the :ruby condition exists then filter based off of conditions
469
+ # else we base off of the `conditions[condition_key]`.
470
+ results <<
471
+ if condition_key.to_s == 'no_additional_labels'
472
+ filter.new(resource, conditions[:labels]).calculate
473
+ elsif filter.instance_method(:initialize).arity == 2
474
+ filter.new(resource, conditions[condition_key]).calculate
475
+ else
476
+ filter.new(resource, conditions[condition_key], network).calculate
477
+ end
469
478
  end
470
- # rubocop:enable Style/IfUnlessModifier
471
-
472
- results.all?
473
479
  end
480
+ results.all?
474
481
  end
475
482
 
476
483
  def limit_resources(resources, limits)
@@ -481,6 +488,13 @@ module Gitlab
481
488
  end
482
489
  end
483
490
 
491
+ def sanitize_resources(resources)
492
+ resources.each do |resource|
493
+ # Titles should not contain newlines. Translate them to spaces.
494
+ resource[:title]&.tr!("\r\n", ' ')
495
+ end
496
+ end
497
+
484
498
  # rubocop:disable Metrics/AbcSize
485
499
  # rubocop:disable Metrics/CyclomaticComplexity
486
500
  def build_get_url(resource_type, conditions)
@@ -574,6 +588,7 @@ module Gitlab
574
588
  condition_builders << APIQueryBuilders::SingleQueryParamBuilder.new('weight', conditions[:weight]) if conditions[:weight]
575
589
  condition_builders << iteration_condition_builder(conditions[:iteration]) if conditions[:iteration]
576
590
  condition_builders << APIQueryBuilders::SingleQueryParamBuilder.new('health_status', conditions[:health_status]) if conditions[:health_status]
591
+ condition_builders << APIQueryBuilders::SingleQueryParamBuilder.new('issue_type', conditions[:issue_type]) if conditions[:issue_type]
577
592
  end
578
593
  end
579
594
 
@@ -11,7 +11,7 @@ module Gitlab
11
11
  end
12
12
 
13
13
  def initialize(resource, condition, network = nil)
14
- super(resource, condition)
14
+ super(resource, { ruby: condition })
15
15
 
16
16
  @network = network
17
17
  end
@@ -1,6 +1,6 @@
1
1
  require_relative 'query_param_builders/base_param_builder'
2
2
  require_relative 'query_param_builders/date_param_builder'
3
- require_relative 'query_param_builders/labels_param_builder'
3
+ require_relative 'query_param_builders/array_param_builder'
4
4
 
5
5
  module Gitlab
6
6
  module Triage
@@ -15,6 +15,9 @@ module Gitlab
15
15
  '$source: ID!',
16
16
  '$after: String'
17
17
  ]
18
+
19
+ has_any_iids = conditions.each_key.find { |key| key.to_s == 'iids' }
20
+ @resource_declarations << '$iids: [String!]' if has_any_iids
18
21
  end
19
22
 
20
23
  def resource_path
@@ -88,15 +91,12 @@ module Gitlab
88
91
  condition_queries << QueryParamBuilders::DateParamBuilder.new(condition_params) if condition.to_s == 'date'
89
92
  condition_queries << QueryParamBuilders::BaseParamBuilder.new('milestoneTitle', condition_params) if condition.to_s == 'milestone'
90
93
  condition_queries << QueryParamBuilders::BaseParamBuilder.new('state', condition_params, with_quotes: false) if condition.to_s == 'state'
91
-
92
- if condition.to_s == 'iids'
93
- @resource_declarations << '$iids: [String!]'
94
- condition_queries << QueryParamBuilders::BaseParamBuilder.new('iids', '$iids', with_quotes: false)
95
- end
94
+ condition_queries << QueryParamBuilders::BaseParamBuilder.new('iids', '$iids', with_quotes: false) if condition.to_s == 'iids'
96
95
 
97
96
  case resource_type
98
97
  when 'issues'
99
98
  condition_queries << issues_label_query(condition, condition_params)
99
+ condition_queries << issues_type_query(condition, condition_params)
100
100
  when 'merge_requests'
101
101
  condition_queries << merge_requests_label_query(condition, condition_params)
102
102
  condition_queries << merge_requests_resource_query(condition, condition_params)
@@ -120,7 +120,13 @@ module Gitlab
120
120
  return nil
121
121
  end
122
122
 
123
- QueryParamBuilders::LabelsParamBuilder.new(*args[0...-1], **args.last)
123
+ QueryParamBuilders::ArrayParamBuilder.new(*args[0...-1], **args.last)
124
+ end
125
+
126
+ def issues_type_query(condition, condition_params)
127
+ return unless condition.to_s == 'issue_type'
128
+
129
+ QueryParamBuilders::ArrayParamBuilder.new('types', [condition_params.upcase], with_quotes: false)
124
130
  end
125
131
 
126
132
  def merge_requests_resource_query(condition, condition_params)
@@ -150,7 +156,7 @@ module Gitlab
150
156
  return nil
151
157
  end
152
158
 
153
- QueryParamBuilders::LabelsParamBuilder.new(*args[0...-1], **args.last)
159
+ QueryParamBuilders::ArrayParamBuilder.new(*args[0...-1], **args.last)
154
160
  end
155
161
  end
156
162
  end
@@ -0,0 +1,27 @@
1
+ require_relative '../../utils'
2
+ require_relative 'base_param_builder'
3
+
4
+ module Gitlab
5
+ module Triage
6
+ module GraphqlQueries
7
+ module QueryParamBuilders
8
+ class ArrayParamBuilder < BaseParamBuilder
9
+ def initialize(param_name, values, with_quotes: true, negated: false)
10
+ quoted_values = values.map do |value|
11
+ if with_quotes
12
+ Utils.graphql_quote(value)
13
+ else
14
+ value
15
+ end
16
+ end
17
+
18
+ array_param_content =
19
+ quoted_values.join(', ').then { |content| "[#{content}]" }
20
+
21
+ super(param_name, array_param_content, with_quotes: false, negated: negated)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Gitlab
4
4
  module Triage
5
- VERSION = '1.41.0'
5
+ VERSION = '1.42.0'
6
6
  end
7
7
  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: 1.41.0
4
+ version: 1.42.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-02 00:00:00.000000000 Z
11
+ date: 2023-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0.16'
55
+ - !ruby/object:Gem::Dependency
56
+ name: graphql
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "<"
60
+ - !ruby/object:Gem::Version
61
+ version: 2.1.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "<"
67
+ - !ruby/object:Gem::Version
68
+ version: 2.1.0
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: httparty
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -211,9 +225,9 @@ files:
211
225
  - lib/gitlab/triage/filters/votes_conditions_filter.rb
212
226
  - lib/gitlab/triage/graphql_network.rb
213
227
  - lib/gitlab/triage/graphql_queries/query_builder.rb
228
+ - lib/gitlab/triage/graphql_queries/query_param_builders/array_param_builder.rb
214
229
  - lib/gitlab/triage/graphql_queries/query_param_builders/base_param_builder.rb
215
230
  - lib/gitlab/triage/graphql_queries/query_param_builders/date_param_builder.rb
216
- - lib/gitlab/triage/graphql_queries/query_param_builders/labels_param_builder.rb
217
231
  - lib/gitlab/triage/limiters/base_limiter.rb
218
232
  - lib/gitlab/triage/limiters/date_field_limiter.rb
219
233
  - lib/gitlab/triage/network.rb
@@ -267,7 +281,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
267
281
  requirements:
268
282
  - - ">="
269
283
  - !ruby/object:Gem::Version
270
- version: 2.5.0
284
+ version: 3.0.0
271
285
  required_rubygems_version: !ruby/object:Gem::Requirement
272
286
  requirements:
273
287
  - - ">="
@@ -1,18 +0,0 @@
1
- require_relative '../../utils'
2
- require_relative 'base_param_builder'
3
-
4
- module Gitlab
5
- module Triage
6
- module GraphqlQueries
7
- module QueryParamBuilders
8
- class LabelsParamBuilder < BaseParamBuilder
9
- def initialize(param_name, labels, negated: false)
10
- label_param_content = labels.map { |label| Utils.graphql_quote(label) }.join(', ').then { |content| "[#{content}]" }
11
-
12
- super(param_name, label_param_content, with_quotes: false, negated: negated)
13
- end
14
- end
15
- end
16
- end
17
- end
18
- end