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 +4 -4
- data/.gitignore +0 -1
- data/.gitlab/merge_request_templates/Release.md +5 -2
- data/.gitlab-ci.yml +6 -5
- data/.rubocop_todo.yml +57 -8
- data/.ruby-version +1 -1
- data/.tool-versions +1 -1
- data/CONTRIBUTING.md +4 -4
- data/Gemfile.lock +239 -0
- data/LICENSE.md +1 -1
- data/README.md +111 -5
- data/gitlab-triage.gemspec +3 -6
- data/lefthook.yml +1 -3
- data/lib/gitlab/triage/action/comment.rb +11 -1
- data/lib/gitlab/triage/action/comment_on_summary.rb +1 -1
- data/lib/gitlab/triage/action/delete.rb +7 -2
- data/lib/gitlab/triage/action/summarize.rb +7 -3
- data/lib/gitlab/triage/engine.rb +24 -5
- data/lib/gitlab/triage/entity_builders/issue_builder.rb +5 -1
- data/lib/gitlab/triage/entity_builders/summary_builder.rb +16 -3
- data/lib/gitlab/triage/graphql_queries/query_builder.rb +3 -2
- data/lib/gitlab/triage/option_parser.rb +8 -0
- data/lib/gitlab/triage/options.rb +2 -1
- data/lib/gitlab/triage/policies/base_policy.rb +1 -1
- data/lib/gitlab/triage/policies/summary_policy.rb +2 -2
- data/lib/gitlab/triage/resource/milestone.rb +5 -5
- data/lib/gitlab/triage/rest_api_network.rb +54 -3
- data/lib/gitlab/triage/version.rb +1 -1
- metadata +8 -21
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '066092d8567b3b76494b99f0c244c565d1c9b65938082e741fe955742c89e88e'
|
|
4
|
+
data.tar.gz: 3fc1d9bf0c94a47b6d6a39002014bb60fe52ac93624cb50f6a06cc2f73d11528
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cd1f5e1088ec9cbe4e21ed6c968ce47489be3d83c95fffd07fd8e59a8eb92240ed44172f09f34390901dd43241a70320e859b5350b1afd20007550736d4bad75
|
|
7
|
+
data.tar.gz: ef7c028266e48926aba06c4fc908798eb7b9b60d3a16cfe7fe05a6134e5756374419961f52baf6c41e12a38f61b5a9c66f11c7e771b725d640619bc13db9bf04
|
data/.gitignore
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
<!--
|
|
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
|
|
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) --
|
|
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-
|
|
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.
|
|
1
|
+
3.2.4
|
data/.tool-versions
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
ruby 3.2.
|
|
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
|
|
4
|
-
conditions for Your present and future Contributions submitted to GitLab
|
|
5
|
-
Except for the license granted herein to GitLab
|
|
6
|
-
distributed by GitLab
|
|
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
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
|
-
|
|
1159
|
-
|
|
1172
|
+
conditions:
|
|
1173
|
+
labels:
|
|
1174
|
+
- needs-testing
|
|
1160
1175
|
actions:
|
|
1161
1176
|
issue:
|
|
1162
1177
|
title: |
|
|
1163
|
-
Testing: {{
|
|
1178
|
+
Testing: {{title}}
|
|
1164
1179
|
description: |
|
|
1165
|
-
The issue {{
|
|
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).
|
data/gitlab-triage.gemspec
CHANGED
|
@@ -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
|
-
|
|
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', '~>
|
|
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
|
@@ -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:
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
data/lib/gitlab/triage/engine.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
|
@@ -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
|
-
|
|
39
|
+
title_present? && content_available?
|
|
39
40
|
end
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
['
|
|
155
|
+
['labelName', condition_params, { negated: true }]
|
|
155
156
|
when 'labels'
|
|
156
|
-
['
|
|
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
|
|
@@ -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
|
-
|
|
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:
|
|
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
|
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.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:
|
|
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:
|
|
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:
|
|
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: '
|
|
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: '
|
|
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.
|
|
342
|
+
rubygems_version: 3.5.22
|
|
356
343
|
signing_key:
|
|
357
344
|
specification_version: 4
|
|
358
345
|
summary: GitLab triage automation project.
|