gitlab-triage 1.43.0 → 1.50.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 95d1d38e50b3032593baffe5e3122da139f542294529cadaaffa5e2861d0a428
4
- data.tar.gz: 83ac90f1c5815c5a39a6cb5d3d84b34112a1a3a72f2dd9a9481291bc171648c3
3
+ metadata.gz: '066092d8567b3b76494b99f0c244c565d1c9b65938082e741fe955742c89e88e'
4
+ data.tar.gz: 3fc1d9bf0c94a47b6d6a39002014bb60fe52ac93624cb50f6a06cc2f73d11528
5
5
  SHA512:
6
- metadata.gz: 8d0aef0429e6892959468c199b0bddbb18ecf02bf864ee038f59b01f35e779a200724e8841b3f603add6267a5a6b3c7746520d10bc48d77c2a6a025e5d3ddaa2
7
- data.tar.gz: 70ea6376e7855ce5ac2207d0f0dc779d8d4e32eb800192c5d3ec8cbfa546425797087525c6a281bfd5513b4d8d4619cf6a81e7fd2e59b7c48d77972653ca5b37
6
+ metadata.gz: cd1f5e1088ec9cbe4e21ed6c968ce47489be3d83c95fffd07fd8e59a8eb92240ed44172f09f34390901dd43241a70320e859b5350b1afd20007550736d4bad75
7
+ data.tar.gz: ef7c028266e48926aba06c4fc908798eb7b9b60d3a16cfe7fe05a6134e5756374419961f52baf6c41e12a38f61b5a9c66f11c7e771b725d640619bc13db9bf04
data/.gitignore CHANGED
@@ -3,7 +3,6 @@
3
3
  /.rspec
4
4
  /.bundle/
5
5
  /.yardoc
6
- /Gemfile.lock
7
6
  /_yardoc/
8
7
  /coverage/
9
8
  /pkg/
@@ -1,8 +1,11 @@
1
- <!-- Replace `<PREVIOUS_VERSION>` with the previous version number here, `<COMMIT_UPDATING_VERSION>` with the latest
1
+ <!--1. Modify /Gemfile.lock, updating specs: gitlab-triage to the new release. See the project's git tags for the latest release. -->
2
+ <!--2. Modify /lib/gitlab/triage/version.rb, updating the version to the new release. -->
3
+ <!--3. Open a merge request with this template -->
4
+ <!--4. Replace `<PREVIOUS_VERSION>` with the previous version number here, `<COMMIT_UPDATING_VERSION>` with the latest
2
5
  commit from this merge request, and `<NEW_VERSION>` with the upcoming version number. -->
3
6
  ## Diff
4
7
 
5
- https://gitlab.com/gitlab-org/ruby/gems/gitlab-triage/-/compare/v<PREVIOUS_VERSION>...<COMMIT_UPDATING_VERSION>
8
+ https://gitlab.com/gitlab-org/ruby/gems/gitlab-triage/-/compare/<PREVIOUS_VERSION>...<COMMIT_UPDATING_VERSION>
6
9
 
7
10
  ## Checklist
8
11
 
data/.gitlab-ci.yml CHANGED
@@ -7,26 +7,27 @@ stages:
7
7
  default:
8
8
  tags:
9
9
  - gitlab-org
10
-
10
+
11
11
  .ruby-cache: &ruby-cache
12
12
  cache:
13
13
  key:
14
14
  files:
15
- - Gemfile
16
- - gitlab-triage.gemspec
15
+ - Gemfile.lock
17
16
  paths:
18
17
  - vendor/ruby
19
- - Gemfile.lock
20
18
  policy: pull
21
19
 
22
20
  .use-ruby:
23
21
  image: ruby:3.2
24
22
  <<: *ruby-cache
23
+ variables:
24
+ BUNDLE_FROZEN: "true"
25
+ BUNDLE_PATH: "vendor"
25
26
  before_script:
26
27
  - ruby --version
27
28
  - gem install bundler --no-document
28
29
  - bundle --version
29
- - bundle install --jobs $(nproc) --path=vendor --retry 3 --quiet
30
+ - bundle install --jobs $(nproc) --retry 3 --quiet
30
31
  - bundle check
31
32
 
32
33
  workflow:
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config --exclude-limit 10000`
3
- # on 2024-04-16 16:23:46 UTC using RuboCop version 1.57.2.
3
+ # on 2024-06-13 12:56:53 UTC using RuboCop version 1.62.1.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
@@ -25,6 +25,17 @@ CodeReuse/ActiveRecord:
25
25
  - 'spec/support/shared_examples/label_command_shared_examples.rb'
26
26
  - 'spec/support/stub_api.rb'
27
27
 
28
+ # Offense count: 4
29
+ # This cop supports unsafe autocorrection (--autocorrect-all).
30
+ # Configuration parameters: Categories, ExpectedOrder.
31
+ # ExpectedOrder: module_inclusion, constants, public_class_methods, initializer, public_methods, protected_methods, private_methods
32
+ Layout/ClassStructure:
33
+ Exclude:
34
+ - 'lib/gitlab/triage/filters/base_conditions_filter.rb'
35
+ - 'lib/gitlab/triage/filters/member_conditions_filter.rb'
36
+ - 'lib/gitlab/triage/graphql_queries/query_builder.rb'
37
+ - 'lib/gitlab/triage/limiters/base_limiter.rb'
38
+
28
39
  # Offense count: 1
29
40
  Lint/ToEnumArguments:
30
41
  Exclude:
@@ -43,6 +54,51 @@ Performance/MethodObjectAsBlock:
43
54
  RSpec/MultipleMemoizedHelpers:
44
55
  Max: 10
45
56
 
57
+ # Offense count: 305
58
+ # Configuration parameters: EnforcedStyle, IgnoreSharedExamples.
59
+ # SupportedStyles: always, named_only
60
+ RSpec/NamedSubject:
61
+ Exclude:
62
+ - 'spec/gitlab/triage/action/comment_on_summary_spec.rb'
63
+ - 'spec/gitlab/triage/action/comment_spec.rb'
64
+ - 'spec/gitlab/triage/action/delete_spec.rb'
65
+ - 'spec/gitlab/triage/action/issue_spec.rb'
66
+ - 'spec/gitlab/triage/action/summarize_spec.rb'
67
+ - 'spec/gitlab/triage/action_spec.rb'
68
+ - 'spec/gitlab/triage/engine_spec.rb'
69
+ - 'spec/gitlab/triage/entity_builders/issue_builder_spec.rb'
70
+ - 'spec/gitlab/triage/entity_builders/summary_builder_spec.rb'
71
+ - 'spec/gitlab/triage/expand_condition/expansion_spec.rb'
72
+ - 'spec/gitlab/triage/expand_condition/list_spec.rb'
73
+ - 'spec/gitlab/triage/expand_condition/sequence_spec.rb'
74
+ - 'spec/gitlab/triage/expand_condition_spec.rb'
75
+ - 'spec/gitlab/triage/filters/branch_date_filter_spec.rb'
76
+ - 'spec/gitlab/triage/filters/discussions_conditions_filter_spec.rb'
77
+ - 'spec/gitlab/triage/filters/issue_date_conditions_filter_spec.rb'
78
+ - 'spec/gitlab/triage/filters/merge_request_date_conditions_filter_spec.rb'
79
+ - 'spec/gitlab/triage/filters/no_additional_labels_conditions_filter_spec.rb'
80
+ - 'spec/gitlab/triage/filters/ruby_conditions_filter_spec.rb'
81
+ - 'spec/gitlab/triage/filters/votes_conditions_filter_spec.rb'
82
+ - 'spec/gitlab/triage/limiters/date_field_limiter_spec.rb'
83
+ - 'spec/gitlab/triage/network_adapters/httparty_adapter_spec.rb'
84
+ - 'spec/gitlab/triage/policies/base_policy_spec.rb'
85
+ - 'spec/gitlab/triage/policies/rule_policy_spec.rb'
86
+ - 'spec/gitlab/triage/policies/summary_policy_spec.rb'
87
+ - 'spec/gitlab/triage/resource/base_spec.rb'
88
+ - 'spec/gitlab/triage/resource/context_spec.rb'
89
+ - 'spec/gitlab/triage/resource/epic_spec.rb'
90
+ - 'spec/gitlab/triage/resource/instance_version_spec.rb'
91
+ - 'spec/gitlab/triage/resource/issue_spec.rb'
92
+ - 'spec/gitlab/triage/resource/label_event_spec.rb'
93
+ - 'spec/gitlab/triage/resource/label_spec.rb'
94
+ - 'spec/gitlab/triage/resource/linked_issue_spec.rb'
95
+ - 'spec/gitlab/triage/resource/merge_request_spec.rb'
96
+ - 'spec/gitlab/triage/resource/milestone_spec.rb'
97
+ - 'spec/gitlab/triage/resource/shared/issuable_spec.rb'
98
+ - 'spec/gitlab/triage/rest_api_network_spec.rb'
99
+ - 'spec/gitlab/triage/retryable_spec.rb'
100
+ - 'spec/gitlab/triage/url_builders/url_builder_spec.rb'
101
+
46
102
  # Offense count: 10
47
103
  # Configuration parameters: AllowedPatterns.
48
104
  # AllowedPatterns: ^expect_, ^assert_
@@ -54,13 +110,6 @@ RSpec/NoExpectationExample:
54
110
  - 'spec/integration/redact_confidentials_spec.rb'
55
111
  - 'spec/integration/summary_policies_spec.rb'
56
112
 
57
- # Offense count: 1
58
- # Configuration parameters: Include.
59
- # Include: **/*_spec*rb*, **/spec/**/*
60
- RSpec/SpecFilePathSuffix:
61
- Exclude:
62
- - 'spec/integration/issue_action_policy.rb'
63
-
64
113
  # Offense count: 12
65
114
  # Configuration parameters: IgnoreNameless, IgnoreSymbolicNames.
66
115
  RSpec/VerifiedDoubles:
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.2.3
1
+ 3.2.4
data/.tool-versions CHANGED
@@ -1 +1 @@
1
- ruby 3.2.3
1
+ ruby 3.2.4
data/CONTRIBUTING.md CHANGED
@@ -1,9 +1,9 @@
1
1
  ## Developer Certificate of Origin + License
2
2
 
3
- By contributing to GitLab B.V., You accept and agree to the following terms and
4
- conditions for Your present and future Contributions submitted to GitLab B.V.
5
- Except for the license granted herein to GitLab B.V. and recipients of software
6
- distributed by GitLab B.V., You reserve all right, title, and interest in and to
3
+ By contributing to GitLab Inc., You accept and agree to the following terms and
4
+ conditions for Your present and future Contributions submitted to GitLab Inc.
5
+ Except for the license granted herein to GitLab Inc. and recipients of software
6
+ distributed by GitLab Inc., You reserve all right, title, and interest in and to
7
7
  Your Contributions. All Contributions are subject to the following DCO + License
8
8
  terms.
9
9
 
data/Gemfile.lock ADDED
@@ -0,0 +1,239 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ gitlab-triage (1.50.0)
5
+ activesupport (>= 5.1)
6
+ globalid (~> 1.0, >= 1.0.1)
7
+ graphql (< 2.1.0)
8
+ graphql-client (~> 0.16)
9
+ httparty (~> 0.20.0)
10
+
11
+ GEM
12
+ remote: https://rubygems.org/
13
+ specs:
14
+ activesupport (7.1.3.4)
15
+ base64
16
+ bigdecimal
17
+ concurrent-ruby (~> 1.0, >= 1.0.2)
18
+ connection_pool (>= 2.2.5)
19
+ drb
20
+ i18n (>= 1.6, < 2)
21
+ minitest (>= 5.1)
22
+ mutex_m
23
+ tzinfo (~> 2.0)
24
+ addressable (2.8.6)
25
+ public_suffix (>= 2.0.2, < 6.0)
26
+ ast (2.4.2)
27
+ base64 (0.2.0)
28
+ bigdecimal (3.1.8)
29
+ claide (1.1.0)
30
+ claide-plugins (0.9.2)
31
+ cork
32
+ nap
33
+ open4 (~> 1.3)
34
+ coderay (1.1.3)
35
+ colored2 (3.1.2)
36
+ concurrent-ruby (1.3.3)
37
+ connection_pool (2.4.1)
38
+ cork (0.3.0)
39
+ colored2 (~> 3.1)
40
+ crack (1.0.0)
41
+ bigdecimal
42
+ rexml
43
+ danger (9.4.3)
44
+ claide (~> 1.0)
45
+ claide-plugins (>= 0.9.2)
46
+ colored2 (~> 3.1)
47
+ cork (~> 0.1)
48
+ faraday (>= 0.9.0, < 3.0)
49
+ faraday-http-cache (~> 2.0)
50
+ git (~> 1.13)
51
+ kramdown (~> 2.3)
52
+ kramdown-parser-gfm (~> 1.0)
53
+ no_proxy_fix
54
+ octokit (>= 4.0)
55
+ terminal-table (>= 1, < 4)
56
+ danger-gitlab (8.0.0)
57
+ danger
58
+ gitlab (~> 4.2, >= 4.2.0)
59
+ diff-lcs (1.5.1)
60
+ drb (2.2.1)
61
+ faraday (2.9.1)
62
+ faraday-net_http (>= 2.0, < 3.2)
63
+ faraday-http-cache (2.5.1)
64
+ faraday (>= 0.8)
65
+ faraday-net_http (3.1.0)
66
+ net-http
67
+ ffi (1.17.0)
68
+ formatador (1.1.0)
69
+ git (1.19.1)
70
+ addressable (~> 2.8)
71
+ rchardet (~> 1.8)
72
+ gitlab (4.19.0)
73
+ httparty (~> 0.20)
74
+ terminal-table (>= 1.5.1)
75
+ gitlab-dangerfiles (2.11.0)
76
+ danger (>= 8.4.5)
77
+ danger-gitlab (>= 8.0.0)
78
+ gitlab-styles (12.0.1)
79
+ rubocop (~> 1.62.1)
80
+ rubocop-factory_bot (~> 2.25.1)
81
+ rubocop-graphql (~> 1.5.0)
82
+ rubocop-performance (~> 1.20.2)
83
+ rubocop-rails (~> 2.24.0)
84
+ rubocop-rspec (~> 2.27.1)
85
+ globalid (1.2.1)
86
+ activesupport (>= 6.1)
87
+ graphql (2.0.31)
88
+ base64
89
+ graphql-client (0.22.0)
90
+ activesupport (>= 3.0)
91
+ graphql (>= 1.13.0)
92
+ guard (2.18.1)
93
+ formatador (>= 0.2.4)
94
+ listen (>= 2.7, < 4.0)
95
+ lumberjack (>= 1.0.12, < 2.0)
96
+ nenv (~> 0.1)
97
+ notiffany (~> 0.0)
98
+ pry (>= 0.13.0)
99
+ shellany (~> 0.0)
100
+ thor (>= 0.18.1)
101
+ guard-compat (1.2.1)
102
+ guard-rspec (4.7.3)
103
+ guard (~> 2.1)
104
+ guard-compat (~> 1.1)
105
+ rspec (>= 2.99.0, < 4.0)
106
+ hashdiff (1.1.0)
107
+ httparty (0.20.0)
108
+ mime-types (~> 3.0)
109
+ multi_xml (>= 0.5.2)
110
+ i18n (1.14.5)
111
+ concurrent-ruby (~> 1.0)
112
+ json (2.7.2)
113
+ kramdown (2.4.0)
114
+ rexml
115
+ kramdown-parser-gfm (1.1.0)
116
+ kramdown (~> 2.0)
117
+ language_server-protocol (3.17.0.3)
118
+ lefthook (1.6.16)
119
+ listen (3.9.0)
120
+ rb-fsevent (~> 0.10, >= 0.10.3)
121
+ rb-inotify (~> 0.9, >= 0.9.10)
122
+ lumberjack (1.2.10)
123
+ method_source (1.1.0)
124
+ mime-types (3.5.2)
125
+ mime-types-data (~> 3.2015)
126
+ mime-types-data (3.2024.0305)
127
+ minitest (5.23.1)
128
+ multi_xml (0.6.0)
129
+ mutex_m (0.2.0)
130
+ nap (1.1.0)
131
+ nenv (0.3.0)
132
+ net-http (0.4.1)
133
+ uri
134
+ no_proxy_fix (0.1.2)
135
+ notiffany (0.1.3)
136
+ nenv (~> 0.1)
137
+ shellany (~> 0.0)
138
+ octokit (9.1.0)
139
+ faraday (>= 1, < 3)
140
+ sawyer (~> 0.9)
141
+ open4 (1.3.4)
142
+ parallel (1.25.1)
143
+ parser (3.3.3.0)
144
+ ast (~> 2.4.1)
145
+ racc
146
+ pry (0.14.2)
147
+ coderay (~> 1.1)
148
+ method_source (~> 1.0)
149
+ public_suffix (5.0.5)
150
+ racc (1.8.0)
151
+ rack (3.1.3)
152
+ rainbow (3.1.1)
153
+ rake (13.2.1)
154
+ rb-fsevent (0.11.2)
155
+ rb-inotify (0.11.1)
156
+ ffi (~> 1.0)
157
+ rchardet (1.8.0)
158
+ regexp_parser (2.9.2)
159
+ rexml (3.3.0)
160
+ strscan
161
+ rspec (3.13.0)
162
+ rspec-core (~> 3.13.0)
163
+ rspec-expectations (~> 3.13.0)
164
+ rspec-mocks (~> 3.13.0)
165
+ rspec-core (3.13.0)
166
+ rspec-support (~> 3.13.0)
167
+ rspec-expectations (3.13.0)
168
+ diff-lcs (>= 1.2.0, < 2.0)
169
+ rspec-support (~> 3.13.0)
170
+ rspec-mocks (3.13.1)
171
+ diff-lcs (>= 1.2.0, < 2.0)
172
+ rspec-support (~> 3.13.0)
173
+ rspec-support (3.13.1)
174
+ rubocop (1.62.1)
175
+ json (~> 2.3)
176
+ language_server-protocol (>= 3.17.0)
177
+ parallel (~> 1.10)
178
+ parser (>= 3.3.0.2)
179
+ rainbow (>= 2.2.2, < 4.0)
180
+ regexp_parser (>= 1.8, < 3.0)
181
+ rexml (>= 3.2.5, < 4.0)
182
+ rubocop-ast (>= 1.31.1, < 2.0)
183
+ ruby-progressbar (~> 1.7)
184
+ unicode-display_width (>= 2.4.0, < 3.0)
185
+ rubocop-ast (1.31.3)
186
+ parser (>= 3.3.1.0)
187
+ rubocop-capybara (2.21.0)
188
+ rubocop (~> 1.41)
189
+ rubocop-factory_bot (2.25.1)
190
+ rubocop (~> 1.41)
191
+ rubocop-graphql (1.5.2)
192
+ rubocop (>= 0.90, < 2)
193
+ rubocop-performance (1.20.2)
194
+ rubocop (>= 1.48.1, < 2.0)
195
+ rubocop-ast (>= 1.30.0, < 2.0)
196
+ rubocop-rails (2.24.1)
197
+ activesupport (>= 4.2.0)
198
+ rack (>= 1.1)
199
+ rubocop (>= 1.33.0, < 2.0)
200
+ rubocop-ast (>= 1.31.1, < 2.0)
201
+ rubocop-rspec (2.27.1)
202
+ rubocop (~> 1.40)
203
+ rubocop-capybara (~> 2.17)
204
+ rubocop-factory_bot (~> 2.22)
205
+ ruby-progressbar (1.13.0)
206
+ sawyer (0.9.2)
207
+ addressable (>= 2.3.5)
208
+ faraday (>= 0.17.3, < 3)
209
+ shellany (0.0.1)
210
+ strscan (3.1.0)
211
+ terminal-table (3.0.2)
212
+ unicode-display_width (>= 1.1.1, < 3)
213
+ thor (1.3.1)
214
+ tzinfo (2.0.6)
215
+ concurrent-ruby (~> 1.0)
216
+ unicode-display_width (2.5.0)
217
+ uri (0.13.0)
218
+ webmock (3.23.1)
219
+ addressable (>= 2.8.0)
220
+ crack (>= 0.3.2)
221
+ hashdiff (>= 0.4.0, < 2.0.0)
222
+ yard (0.9.36)
223
+
224
+ PLATFORMS
225
+ ruby
226
+
227
+ DEPENDENCIES
228
+ gitlab-dangerfiles (~> 2.11.0)
229
+ gitlab-styles (~> 12.0)
230
+ gitlab-triage!
231
+ guard-rspec (~> 4.7.3)
232
+ lefthook (~> 1.3)
233
+ rake (~> 13.2)
234
+ rspec (~> 3.8)
235
+ webmock (~> 3.4)
236
+ yard
237
+
238
+ BUNDLED WITH
239
+ 2.5.11
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011-2017 GitLab B.V.
1
+ Copyright (c) 2011-2024 GitLab Inc.
2
2
 
3
3
  With regard to the GitLab Software:
4
4
 
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  # GitLab Triage Project
4
4
 
5
+ [[_TOC_]]
6
+
5
7
  This project allows to automate triaging of issues and merge requests for GitLab projects or groups.
6
8
 
7
9
  ## Note this Gem is not supported by the GitLab Support team
@@ -177,6 +179,7 @@ Available condition types:
177
179
  - [`labels` condition](#labels-condition)
178
180
  - [`forbidden_labels` condition](#forbidden-labels-condition)
179
181
  - [`no_additional_labels` condition](#no-additional-labels-condition)
182
+ - [`author_username` condition](#author-username-condition)
180
183
  - [`author_member` condition](#author-member-condition)
181
184
  - [`assignee_member` condition](#assignee-member-condition)
182
185
  - [`draft` condition](#draft-condition)
@@ -489,6 +492,17 @@ conditions:
489
492
  no_additional_labels: true
490
493
  ```
491
494
 
495
+ ##### Author username condition
496
+
497
+ Accepts the username to filter on.
498
+
499
+ Example:
500
+
501
+ ```yml
502
+ conditions:
503
+ author_username: gitlab-bot
504
+ ```
505
+
492
506
  ##### Author Member condition
493
507
 
494
508
  This condition determines whether the author of a resource is a member of the specified group or project.
@@ -1155,14 +1169,15 @@ resource_rules:
1155
1169
  issues:
1156
1170
  rules:
1157
1171
  - name: Issues requiring extra testing
1158
- labels:
1159
- - needs-testing
1172
+ conditions:
1173
+ labels:
1174
+ - needs-testing
1160
1175
  actions:
1161
1176
  issue:
1162
1177
  title: |
1163
- Testing: {{ title }}
1178
+ Testing: {{title}}
1164
1179
  description: |
1165
- The issue {{ full_reference }} needs testing.
1180
+ The issue {{full_reference}} needs testing.
1166
1181
 
1167
1182
  Please take care of them before the end of #{7.days.from_now.strftime('%Y-%m-%d')}
1168
1183
 
@@ -1171,7 +1186,7 @@ resource_rules:
1171
1186
 
1172
1187
  ##### Delete action
1173
1188
 
1174
- **This action is only applicable for branches.**
1189
+ **This action is only applicable for branches, issues and merge requests.**
1175
1190
 
1176
1191
  Delete the resource.
1177
1192
 
@@ -1205,6 +1220,55 @@ sub-policies' summary.
1205
1220
  Note that only the `summarize` keys in the sub-policies' `actions` is used. Any
1206
1221
  other keys (e.g. `mention`, `comment`, `labels` etc.) are ignored.
1207
1222
 
1223
+ #### Custom type summaries
1224
+
1225
+ By default, summary rules fetch GitLab resources (issues, merge requests, etc.) and use them to generate the summary content. However, you can create summaries that pull data from external sources (like ClickHouse, Prometheus, or custom APIs) without fetching any GitLab resources.
1226
+
1227
+ To create a custom summary, add `type: custom` to your rule definition:
1228
+
1229
+ ```yml
1230
+ resource_rules:
1231
+ issues:
1232
+ summaries:
1233
+ - name: Weekly Report
1234
+ rules:
1235
+ - name: Bug Heatmap
1236
+ conditions:
1237
+ labels:
1238
+ - bug
1239
+ actions:
1240
+ summarize:
1241
+ title: "Bugs"
1242
+ item: "- {{title}}"
1243
+ summary: "{{items}}"
1244
+
1245
+ - name: Quarantined Tests
1246
+ type: custom # Skip resource fetching
1247
+ actions:
1248
+ summarize:
1249
+ title: "Quarantined Tests"
1250
+ summary: |
1251
+ #{ fetch_quarantined_tests_from_clickhouse() }
1252
+ actions:
1253
+ summarize:
1254
+ title: "Weekly Report"
1255
+ summary: |
1256
+ {{items}}
1257
+ ```
1258
+
1259
+ When `type: custom` is specified:
1260
+ - No GitLab resources are fetched
1261
+ - The `conditions` field is optional and ignored
1262
+ - The `item` field in `actions.summarize` is not needed
1263
+ - The summary is always included in the report (as long as it has a title)
1264
+ - You can use Ruby expressions in the `summary` field to fetch data from external sources
1265
+
1266
+ This is useful for:
1267
+ - Including metrics from external monitoring systems
1268
+ - Aggregating data from multiple sources
1269
+ - Generating reports from custom databases
1270
+ - Adding static sections to your triage reports
1271
+
1208
1272
  You can define such policy as follows:
1209
1273
 
1210
1274
  ```yml
@@ -1403,6 +1467,10 @@ Usage: gitlab-triage [options]
1403
1467
  -H, --host-url [string] A valid host url
1404
1468
  -r, --require [string] Require a file before performing
1405
1469
  -d, --debug Print debug information
1470
+ --cache-dir [string] Directory containing pre-fetched API responses.
1471
+ Files must follow the naming convention: <source>_<id>_<resource>.json
1472
+ (e.g. groups_9970_members.json).
1473
+ Can also be set via the GITLAB_TRIAGE_CACHE_DIR environment variable.
1406
1474
  -h, --help Print help message
1407
1475
  -v, --version Print version
1408
1476
  --init Initialize the project with a policy file
@@ -1528,6 +1596,44 @@ resource_rules:
1528
1596
  #{'/label ~P3' unless has_priority_label?}
1529
1597
  ```
1530
1598
 
1599
+ ### API Response Caching (`--cache-dir`)
1600
+
1601
+ In large CI pipelines with many concurrent triage jobs, each job independently fetches the same paginated API responses (e.g., group members). This results in many redundant API calls.
1602
+
1603
+ The `--cache-dir` option (or `CACHE_DIR` environment variable) allows you to pre-fetch responses once and share them across all jobs via CI artifacts.
1604
+
1605
+ #### File naming convention
1606
+
1607
+ Cache files must be named `<source_type>_<source_id>_<resource>.json`, for example:
1608
+
1609
+ - `groups_9970_members.json` — members of group 9970 (numeric ID)
1610
+ - `projects_278964_members.json` — members of project 278964 (numeric ID)
1611
+ - `groups_gitlab-org_gitlab_members.json` — members of `gitlab-org/gitlab` (path slashes replaced with `_`)
1612
+
1613
+ The gem checks for a matching cache file before making each `query_api_cached` call. If a file exists, its contents are returned directly. If not, the gem falls back to the normal API call transparently.
1614
+
1615
+ #### Usage in CI
1616
+
1617
+ Pre-fetch in a `pre-hygiene` stage and share as an artifact:
1618
+
1619
+ ```yaml
1620
+ # pre-hygiene job writes the cache
1621
+ prefetch-members:
1622
+ stage: pre-hygiene
1623
+ script:
1624
+ - ruby bin/prefetch_members
1625
+ artifacts:
1626
+ paths:
1627
+ - tmp/members_cache/
1628
+ expire_in: 1 hour
1629
+
1630
+ # triage jobs read from the cache
1631
+ triage-job:
1632
+ stage: hygiene
1633
+ script:
1634
+ - gitlab-triage --cache-dir tmp/members_cache --token $TOKEN --source groups --source-id 9970 -f policy.yml
1635
+ ```
1636
+
1531
1637
  ### Contributing
1532
1638
 
1533
1639
  Please refer to the [Contributing Guide](CONTRIBUTING.md).
@@ -40,18 +40,15 @@ Gem::Specification.new do |spec|
40
40
  # see: https://github.com/github/graphql-client/pull/314
41
41
  # We can remove this check once PR 314 is merged and released
42
42
  spec.add_dependency 'graphql', '< 2.1.0'
43
- spec.add_dependency 'httparty', '~> 0.17'
43
+ # Matching version of triage-ops's httparty
44
+ spec.add_dependency 'httparty', '~> 0.20.0'
44
45
 
45
46
  spec.add_development_dependency 'gitlab-dangerfiles', '~> 2.11.0'
46
- spec.add_development_dependency 'gitlab-styles', '~> 10.0'
47
+ spec.add_development_dependency 'gitlab-styles', '~> 12.0'
47
48
  spec.add_development_dependency 'guard-rspec', '~> 4.7.3'
48
49
  spec.add_development_dependency 'lefthook', '~> 1.3'
49
50
  spec.add_development_dependency 'rake', '~> 13.2'
50
51
  spec.add_development_dependency 'rspec', '~> 3.8'
51
- # we do not commit the bundle lockfile, so this temporary workaround needs to be
52
- # present until 2.21.3 or 2.22.x is released
53
- # See https://gitlab.com/gitlab-org/ruby/gems/gitlab-styles/-/issues/63
54
- spec.add_development_dependency 'rubocop-rails', '!= 2.21.2'
55
52
  spec.add_development_dependency 'webmock', '~> 3.4'
56
53
  spec.add_development_dependency 'yard'
57
54
  end
data/lefthook.yml CHANGED
@@ -9,6 +9,4 @@ pre-push:
9
9
  glob: '*.{rb,rake}'
10
10
  run: bundle exec rubocop {files}
11
11
  rspec:
12
- files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
13
- glob: '*.{rb,rake}'
14
- run: bundle exec rspec {files}
12
+ run: bundle exec rspec
@@ -61,6 +61,16 @@ module Gitlab
61
61
  end
62
62
 
63
63
  def perform(resource, comment)
64
+ if network.options.debug
65
+ if policy.actions.fetch(:redact_confidential_resources, true) && resource[:confidential]
66
+ puts Gitlab::Triage::UI.debug "Comment action resource: (confidential)"
67
+ else
68
+ puts Gitlab::Triage::UI.debug "Comment action resource: #{resource.inspect}"
69
+ end
70
+
71
+ puts Gitlab::Triage::UI.debug "Comment action content: #{comment}"
72
+ end
73
+
64
74
  network.post_api(
65
75
  build_post_url(resource),
66
76
  post_body(comment))
@@ -79,7 +89,7 @@ module Gitlab
79
89
  # POST /(groups|projects)/:id/(epics|issues|merge_requests)/:iid/notes
80
90
  post_url = UrlBuilders::UrlBuilder.new(url_builder_opts).build
81
91
 
82
- puts Gitlab::Triage::UI.debug "post_url: #{post_url}" if network.options.debug
92
+ puts Gitlab::Triage::UI.debug "Comment action post_url: #{post_url}" if network.options.debug
83
93
 
84
94
  post_url
85
95
  end
@@ -57,7 +57,7 @@ module Gitlab
57
57
  post_url = UrlBuilders::UrlBuilder.new(
58
58
  network_options: network.options,
59
59
  source_id: summary['project_id'],
60
- resource_type: policy.type,
60
+ resource_type: summary['type'],
61
61
  resource_id: summary['iid'],
62
62
  sub_resource_type: sub_resource_type
63
63
  ).build
@@ -20,7 +20,7 @@ module Gitlab
20
20
  end
21
21
 
22
22
  def act
23
- return unless policy.type&.to_sym == :branches
23
+ return unless [:branches, :issues, :merge_requests].include?(policy.type&.to_sym)
24
24
 
25
25
  policy.resources.each do |resource|
26
26
  perform(resource)
@@ -48,7 +48,12 @@ module Gitlab
48
48
  end
49
49
 
50
50
  def resource_id(resource)
51
- resource[:name]
51
+ case policy.type&.to_sym
52
+ when :branches
53
+ resource[:name]
54
+ when :issues, :merge_requests
55
+ resource[:iid]
56
+ end
52
57
  end
53
58
  end
54
59
  end
@@ -6,6 +6,8 @@ module Gitlab
6
6
  module Triage
7
7
  module Action
8
8
  class Summarize < Base
9
+ SUMMARY_RESOURCE_TYPE = 'issues'
10
+
9
11
  class Dry < Summarize
10
12
  private
11
13
 
@@ -13,7 +15,8 @@ module Gitlab
13
15
  policy.summary = {
14
16
  web_url: '[the-created-issue-url]',
15
17
  project_id: 'some-id',
16
- iid: 'some-iid'
18
+ iid: 'some-iid',
19
+ type: SUMMARY_RESOURCE_TYPE
17
20
  }.with_indifferent_access
18
21
 
19
22
  if group_summary_without_destination?
@@ -41,7 +44,8 @@ module Gitlab
41
44
  return
42
45
  end
43
46
 
44
- policy.summary = network.post_api(post_issue_url, post_issue_body)
47
+ response = network.post_api(post_issue_url, post_issue_body)
48
+ policy.summary = response.merge('type' => SUMMARY_RESOURCE_TYPE)
45
49
  end
46
50
 
47
51
  def issue
@@ -62,7 +66,7 @@ module Gitlab
62
66
  post_url = UrlBuilders::UrlBuilder.new(
63
67
  network_options: network.options,
64
68
  source_id: destination,
65
- resource_type: 'issues'
69
+ resource_type: SUMMARY_RESOURCE_TYPE
66
70
  ).build
67
71
 
68
72
  puts Gitlab::Triage::UI.debug "post_issue_url: #{post_url}" if network.options.debug
@@ -168,7 +168,7 @@ module Gitlab
168
168
  raise(
169
169
  ArgumentError,
170
170
  "--resource-reference can only start with '#' or '!' when --source=projects is passed " \
171
- "('#{options.resource_reference}' passed)!"
171
+ "('#{options.resource_reference}' passed)!"
172
172
  )
173
173
  end
174
174
  end
@@ -268,7 +268,7 @@ module Gitlab
268
268
  return if rule_definitions.blank?
269
269
 
270
270
  rule_definitions.each do |rule_definition|
271
- resources_for_rule(resource_type, rule_definition) do |resources|
271
+ resources_for_rule(resource_type, rule_definition, in_summary: false) do |resources|
272
272
  policy = Policies::RulePolicy.new(
273
273
  resource_type, rule_definition, resources, network)
274
274
 
@@ -336,7 +336,7 @@ module Gitlab
336
336
  def summary_parts_for_rules(resource_type, rule_definitions)
337
337
  # { summary_rule => resources }
338
338
  parts = rule_definitions.each_with_object({}) do |rule_definition, result|
339
- to_enum(:resources_for_rule, resource_type, rule_definition).each do |rule_resources, expanded_conditions|
339
+ to_enum(:resources_for_rule, resource_type, rule_definition, in_summary: true).each do |rule_resources, expanded_conditions|
340
340
  # We replace the non-expanded rule conditions with the expanded ones
341
341
  result.merge!(rule_definition.merge(conditions: expanded_conditions) => rule_resources)
342
342
  end
@@ -355,15 +355,27 @@ module Gitlab
355
355
  #
356
356
  # @param resource_type [String] The resource type, e.g. +issues+ or +merge_requests+.
357
357
  # @param rule_definition [Hash] A rule definition, e.g. +{ name: 'Foo', conditions: { milestone: 'v1' } }+.
358
+ # @param in_summary [Boolean] Whether this rule is part of a summary definition.
358
359
  #
359
360
  # @yieldparam rule_resources [PoliciesResources::RuleResources] An object which contains an array of resources.
360
361
  # @yieldparam expanded_conditions [Hash] A hash of expanded conditions.
361
362
  # @yieldreturn [nil]
362
363
  #
363
364
  # @return [nil]
364
- def resources_for_rule(resource_type, rule_definition)
365
+ def resources_for_rule(resource_type, rule_definition, in_summary: false)
365
366
  puts Gitlab::Triage::UI.header("Gathering resources for rule: **#{rule_definition[:name]}**", char: '-')
366
367
 
368
+ # Skip resource fetching for custom type rules
369
+ if rule_definition[:type] == 'custom'
370
+ unless in_summary
371
+ raise ArgumentError, "type: custom can only be used in summary rules, not in top-level rules (rule: #{rule_definition[:name]})"
372
+ end
373
+
374
+ puts "\n* Skipping resource fetch for custom type rule"
375
+ yield(PoliciesResources::RuleResources.new([]), {})
376
+ return
377
+ end
378
+
367
379
  ExpandCondition.perform(rule_conditions(rule_definition)) do |expanded_conditions|
368
380
  # retrieving the resources for every rule is inefficient
369
381
  # however, previous rules may affect those upcoming
@@ -450,7 +462,7 @@ module Gitlab
450
462
 
451
463
  FILTER_MAP.each do |condition_key, filter_value|
452
464
  # Skips to the next key value pair if the condition is not applicable
453
- next unless conditions[condition_key]
465
+ next if conditions[condition_key].nil?
454
466
 
455
467
  case filter_value
456
468
  when Hash
@@ -469,9 +481,12 @@ module Gitlab
469
481
 
470
482
  # If the :ruby condition exists then filter based off of conditions
471
483
  # else we base off of the `conditions[condition_key]`.
484
+
472
485
  result =
473
486
  if condition_key.to_s == 'no_additional_labels'
474
487
  filter.new(resource, conditions[:labels]).calculate
488
+ elsif condition_key.to_s == 'protected'
489
+ filter.new(resource, conditions[:protected]).calculate
475
490
  elsif filter.instance_method(:initialize).arity == 2
476
491
  filter.new(resource, conditions[condition_key]).calculate
477
492
  else
@@ -501,6 +516,7 @@ module Gitlab
501
516
 
502
517
  # rubocop:disable Metrics/AbcSize
503
518
  # rubocop:disable Metrics/CyclomaticComplexity
519
+ # rubocop:disable Metrics/PerceivedComplexity
504
520
  def build_get_url(resource_type, conditions)
505
521
  # Example issues query with state and labels
506
522
  # https://gitlab.com/api/v4/projects/test-triage%2Fissue-project/issues?state=open&labels=project%20label%20with%20spaces,group_label_no_spaces
@@ -510,6 +526,8 @@ module Gitlab
510
526
 
511
527
  condition_builders = []
512
528
  condition_builders << APIQueryBuilders::SingleQueryParamBuilder.new('iids', options.resource_reference[1..]) if options.resource_reference
529
+ author_username = conditions[:author_username]
530
+ condition_builders << APIQueryBuilders::SingleQueryParamBuilder.new('author_username', author_username) if author_username
513
531
 
514
532
  condition_builders << APIQueryBuilders::MultiQueryParamBuilder.new('labels', conditions[:labels], ',') if conditions[:labels]
515
533
 
@@ -560,6 +578,7 @@ module Gitlab
560
578
  end
561
579
  # rubocop:enable Metrics/AbcSize
562
580
  # rubocop:enable Metrics/CyclomaticComplexity
581
+ # rubocop:enable Metrics/PerceivedComplexity
563
582
 
564
583
  def milestone_condition_builder(resource_type, milestone_condition)
565
584
  milestone_value = Array(milestone_condition)[0].to_s # back-compatibility
@@ -33,11 +33,15 @@ module Gitlab
33
33
  end
34
34
 
35
35
  def valid?
36
- title =~ /\S+/
36
+ title_present?
37
37
  end
38
38
 
39
39
  private
40
40
 
41
+ def title_present?
42
+ /\S+/.match?(title)
43
+ end
44
+
41
45
  def build_text(template)
42
46
  return '' unless template
43
47
 
@@ -20,6 +20,7 @@ module Gitlab
20
20
  @resources = resources
21
21
  @network = network
22
22
  @separator = separator
23
+ @is_custom = policy_spec[:type] == 'custom'
23
24
  end
24
25
 
25
26
  def title
@@ -35,15 +36,27 @@ module Gitlab
35
36
  end
36
37
 
37
38
  def valid?
38
- title =~ /\S+/ && any_resources?
39
+ title_present? && content_available?
39
40
  end
40
41
 
41
- def any_resources?
42
- @resources.any?
42
+ # Check if this summary has content to include in a parent summary.
43
+ # Custom type summaries generate content from templates (external data),
44
+ # but only if the template produces non-empty output.
45
+ # Regular summaries need GitLab resources to generate content.
46
+ def content_available?
47
+ if @is_custom
48
+ /\S+/.match?(description)
49
+ else
50
+ @resources.any?
51
+ end
43
52
  end
44
53
 
45
54
  private
46
55
 
56
+ def title_present?
57
+ /\S+/.match?(title)
58
+ end
59
+
47
60
  def title_resource
48
61
  { type: @type }
49
62
  end
@@ -91,6 +91,7 @@ module Gitlab
91
91
 
92
92
  conditions.each do |condition, condition_params|
93
93
  condition_queries << QueryParamBuilders::DateParamBuilder.new(condition_params) if condition.to_s == 'date'
94
+ condition_queries << QueryParamBuilders::BaseParamBuilder.new('authorUsername', condition_params) if condition.to_s == 'author_username'
94
95
  condition_queries << QueryParamBuilders::BaseParamBuilder.new('milestoneTitle', condition_params) if condition.to_s == 'milestone'
95
96
  condition_queries << QueryParamBuilders::BaseParamBuilder.new('state', condition_params, with_quotes: false) if condition.to_s == 'state'
96
97
  condition_queries << QueryParamBuilders::BaseParamBuilder.new('iids', '$iids', with_quotes: false) if condition.to_s == 'iids'
@@ -151,9 +152,9 @@ module Gitlab
151
152
  args =
152
153
  case condition.to_s
153
154
  when 'forbidden_labels'
154
- ['labels', condition_params, { negated: true }]
155
+ ['labelName', condition_params, { negated: true }]
155
156
  when 'labels'
156
- ['labels', condition_params, {}]
157
+ ['labelName', condition_params, {}]
157
158
  else
158
159
  return nil
159
160
  end
@@ -65,6 +65,14 @@ module Gitlab
65
65
  options.debug = value
66
66
  end
67
67
 
68
+ opts.on('--cache-dir [string]', String,
69
+ 'Directory containing pre-fetched API responses. ' \
70
+ 'Files must follow the naming convention: <source>_<id>_<resource>.json ' \
71
+ '(e.g. groups_9970_members.json). ' \
72
+ 'Can also be set via the GITLAB_TRIAGE_CACHE_DIR environment variable.') do |value|
73
+ options.cache_dir = value
74
+ end
75
+
68
76
  opts.on('-h', '--help', 'Print help message') do
69
77
  $stdout.puts opts
70
78
  exit # rubocop:disable Rails/Exit
@@ -14,7 +14,8 @@ module Gitlab
14
14
  :debug,
15
15
  :host_url,
16
16
  :require_files,
17
- :api_version
17
+ :api_version,
18
+ :cache_dir
18
19
  ) do
19
20
  def initialize(*args)
20
21
  super
@@ -21,7 +21,7 @@ module Gitlab
21
21
  end
22
22
 
23
23
  def name
24
- @name ||= (policy_spec[:name] || "#{type}-#{object_id}")
24
+ @name ||= policy_spec[:name] || "#{type}-#{object_id}"
25
25
  end
26
26
 
27
27
  def source
@@ -10,7 +10,7 @@ module Gitlab
10
10
  # Build a summary from several rules policies
11
11
  def build_summary
12
12
  action = actions[:summarize]
13
- issues = resources.map do |inner_policy_spec, inner_resources|
13
+ child_summaries = 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_summary
@@ -19,7 +19,7 @@ module Gitlab
19
19
  EntityBuilders::SummaryBuilder.new(
20
20
  type: type,
21
21
  action: action,
22
- resources: issues.select(&:any_resources?),
22
+ resources: child_summaries.select(&:content_available?),
23
23
  network: network,
24
24
  separator: "\n\n")
25
25
  end
@@ -76,6 +76,11 @@ module Gitlab
76
76
  started?(today) && !expired?(today)
77
77
  end
78
78
 
79
+ def all_active_with_start_date
80
+ @all_active_with_start_date ||=
81
+ all_active.select(&:start_date).sort_by(&:start_date)
82
+ end
83
+
79
84
  private
80
85
 
81
86
  def current_index
@@ -83,11 +88,6 @@ module Gitlab
83
88
  .index { |milestone| milestone.id == id }
84
89
  end
85
90
 
86
- def all_active_with_start_date
87
- @all_active_with_start_date ||=
88
- all_active.select(&:start_date).sort_by(&:start_date)
89
- end
90
-
91
91
  def all_active
92
92
  @all_active ||=
93
93
  network
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_support/all'
4
+ require 'json'
4
5
  require 'net/protocol'
6
+ require 'uri'
5
7
 
6
8
  require_relative 'retryable'
7
9
  require_relative 'ui'
@@ -13,6 +15,7 @@ module Gitlab
13
15
  include Retryable
14
16
 
15
17
  MINIMUM_RATE_LIMIT = 25
18
+ CACHE_URL_PATTERN = %r{/api/v[^/]+/(groups|projects)/(.+?)/(members)(?:\z|\?)}
16
19
 
17
20
  attr_reader :options, :adapter
18
21
 
@@ -20,10 +23,11 @@ module Gitlab
20
23
  @adapter = adapter
21
24
  @options = adapter.options
22
25
  @cache = {}
26
+ @file_cache = {}
23
27
  end
24
28
 
25
29
  def query_api_cached(url)
26
- @cache[url] || @cache[url] = query_api(url)
30
+ @cache[url] || @cache[url] = load_from_file_cache(url) || query_api(url)
27
31
  end
28
32
 
29
33
  def query_api(url)
@@ -66,7 +70,7 @@ module Gitlab
66
70
 
67
71
  def post_api(url, body)
68
72
  response = execute_with_retry(
69
- exception_types: Net::ReadTimeout,
73
+ exception_types: [Net::ReadTimeout, Errors::Network::InternalServerError],
70
74
  backoff_exceptions: Errors::Network::TooManyRequests, debug: options.debug) do
71
75
  puts Gitlab::Triage::UI.debug "post_api: #{url}" if options.debug
72
76
 
@@ -88,7 +92,7 @@ module Gitlab
88
92
 
89
93
  def delete_api(url)
90
94
  response = execute_with_retry(
91
- exception_types: Net::ReadTimeout,
95
+ exception_types: [Net::ReadTimeout, Errors::Network::InternalServerError],
92
96
  backoff_exceptions: Errors::Network::TooManyRequests, debug: options.debug) do
93
97
  puts Gitlab::Triage::UI.debug "delete_api: #{url}" if options.debug
94
98
 
@@ -101,6 +105,53 @@ module Gitlab
101
105
 
102
106
  private
103
107
 
108
+ def cache_dir
109
+ options.cache_dir || ENV.fetch('GITLAB_TRIAGE_CACHE_DIR', nil)
110
+ end
111
+
112
+ def load_from_file_cache(url)
113
+ return nil unless cache_dir_valid?
114
+
115
+ cache_key = cache_key_for(url)
116
+ return nil unless cache_key
117
+
118
+ @file_cache[cache_key] || read_cache_file(cache_key)
119
+ end
120
+
121
+ def cache_dir_valid?
122
+ cache_dir && File.directory?(cache_dir)
123
+ end
124
+
125
+ def cache_key_for(url)
126
+ match = url.match(CACHE_URL_PATTERN)
127
+ return nil unless match
128
+
129
+ source_type = match[1]
130
+ source_id = URI.decode_www_form_component(match[2]).tr('/', '_')
131
+ resource = match[3]
132
+
133
+ "#{source_type}_#{source_id}_#{resource}"
134
+ end
135
+
136
+ def read_cache_file(cache_key)
137
+ data = parse_cache_file(cache_key)
138
+ return nil unless data
139
+
140
+ @file_cache[cache_key] = data
141
+ puts Gitlab::Triage::UI.debug "cache_dir: loaded #{data.size} records" if options.debug
142
+ data
143
+ end
144
+
145
+ def parse_cache_file(cache_key)
146
+ file = File.join(cache_dir, "#{cache_key}.json")
147
+ parsed = JSON.parse(File.read(file))
148
+ return nil unless parsed.is_a?(Array) && parsed.all?(Hash)
149
+
150
+ parsed.map(&:with_indifferent_access)
151
+ rescue JSON::ParserError, Errno::ENOENT, Errno::EACCES
152
+ nil
153
+ end
154
+
104
155
  def token
105
156
  options.token
106
157
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Gitlab
4
4
  module Triage
5
- VERSION = '1.43.0'
5
+ VERSION = '1.50.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.43.0
4
+ version: 1.50.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-11 00:00:00.000000000 Z
11
+ date: 2026-03-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -78,14 +78,14 @@ dependencies:
78
78
  requirements:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
- version: '0.17'
81
+ version: 0.20.0
82
82
  type: :runtime
83
83
  prerelease: false
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
- version: '0.17'
88
+ version: 0.20.0
89
89
  - !ruby/object:Gem::Dependency
90
90
  name: gitlab-dangerfiles
91
91
  requirement: !ruby/object:Gem::Requirement
@@ -106,14 +106,14 @@ dependencies:
106
106
  requirements:
107
107
  - - "~>"
108
108
  - !ruby/object:Gem::Version
109
- version: '10.0'
109
+ version: '12.0'
110
110
  type: :development
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - "~>"
115
115
  - !ruby/object:Gem::Version
116
- version: '10.0'
116
+ version: '12.0'
117
117
  - !ruby/object:Gem::Dependency
118
118
  name: guard-rspec
119
119
  requirement: !ruby/object:Gem::Requirement
@@ -170,20 +170,6 @@ dependencies:
170
170
  - - "~>"
171
171
  - !ruby/object:Gem::Version
172
172
  version: '3.8'
173
- - !ruby/object:Gem::Dependency
174
- name: rubocop-rails
175
- requirement: !ruby/object:Gem::Requirement
176
- requirements:
177
- - - "!="
178
- - !ruby/object:Gem::Version
179
- version: 2.21.2
180
- type: :development
181
- prerelease: false
182
- version_requirements: !ruby/object:Gem::Requirement
183
- requirements:
184
- - - "!="
185
- - !ruby/object:Gem::Version
186
- version: 2.21.2
187
173
  - !ruby/object:Gem::Dependency
188
174
  name: webmock
189
175
  requirement: !ruby/object:Gem::Requirement
@@ -237,6 +223,7 @@ files:
237
223
  - CONTRIBUTING.md
238
224
  - Dangerfile
239
225
  - Gemfile
226
+ - Gemfile.lock
240
227
  - Guardfile
241
228
  - LICENSE.md
242
229
  - README.md
@@ -352,7 +339,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
352
339
  - !ruby/object:Gem::Version
353
340
  version: '0'
354
341
  requirements: []
355
- rubygems_version: 3.3.27
342
+ rubygems_version: 3.5.22
356
343
  signing_key:
357
344
  specification_version: 4
358
345
  summary: GitLab triage automation project.