gitlab-triage 1.41.0 → 1.42.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/README.md +24 -0
- data/bin/gitlab-triage +5 -1
- data/gitlab-triage.gemspec +7 -1
- data/lib/gitlab/triage/engine.rb +63 -48
- data/lib/gitlab/triage/filters/ruby_conditions_filter.rb +1 -1
- data/lib/gitlab/triage/graphql_queries/query_builder.rb +14 -8
- data/lib/gitlab/triage/graphql_queries/query_param_builders/array_param_builder.rb +27 -0
- data/lib/gitlab/triage/version.rb +1 -1
- metadata +18 -4
- data/lib/gitlab/triage/graphql_queries/query_param_builders/labels_param_builder.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2cd7bbbde45634c445e721eba9e30e348f0d1fef2428a008d4f417f32b8184f7
|
4
|
+
data.tar.gz: 283dfe4c32c0ca14c5fbdb984c0661a522bcd1afa59af97816fc01008e30e48e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 =
|
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)
|
data/gitlab-triage.gemspec
CHANGED
@@ -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(">=
|
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'
|
data/lib/gitlab/triage/engine.rb
CHANGED
@@ -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)
|
440
|
+
def filter_resources(resources, conditions)
|
420
441
|
resources.select do |resource|
|
421
|
-
|
422
|
-
|
423
|
-
|
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
|
-
|
456
|
-
|
457
|
-
end
|
446
|
+
def filter_resource(resource, conditions)
|
447
|
+
results = []
|
458
448
|
|
459
|
-
|
460
|
-
|
461
|
-
|
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
|
-
|
464
|
-
|
465
|
-
|
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
|
-
|
468
|
-
|
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
|
|
@@ -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/
|
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::
|
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::
|
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
|
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.
|
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-
|
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:
|
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
|