gitlab-triage 1.49.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/Gemfile.lock +1 -1
- data/README.md +42 -0
- data/lib/gitlab/triage/action/summarize.rb +2 -1
- data/lib/gitlab/triage/option_parser.rb +8 -0
- data/lib/gitlab/triage/options.rb +2 -1
- data/lib/gitlab/triage/rest_api_network.rb +54 -3
- data/lib/gitlab/triage/version.rb +1 -1
- metadata +2 -2
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/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -1467,6 +1467,10 @@ Usage: gitlab-triage [options]
|
|
|
1467
1467
|
-H, --host-url [string] A valid host url
|
|
1468
1468
|
-r, --require [string] Require a file before performing
|
|
1469
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.
|
|
1470
1474
|
-h, --help Print help message
|
|
1471
1475
|
-v, --version Print version
|
|
1472
1476
|
--init Initialize the project with a policy file
|
|
@@ -1592,6 +1596,44 @@ resource_rules:
|
|
|
1592
1596
|
#{'/label ~P3' unless has_priority_label?}
|
|
1593
1597
|
```
|
|
1594
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
|
+
|
|
1595
1637
|
### Contributing
|
|
1596
1638
|
|
|
1597
1639
|
Please refer to the [Contributing Guide](CONTRIBUTING.md).
|
|
@@ -44,7 +44,8 @@ module Gitlab
|
|
|
44
44
|
return
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
response = network.post_api(post_issue_url, post_issue_body)
|
|
48
|
+
policy.summary = response.merge('type' => SUMMARY_RESOURCE_TYPE)
|
|
48
49
|
end
|
|
49
50
|
|
|
50
51
|
def issue
|
|
@@ -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
|
|
@@ -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: 2026-
|
|
11
|
+
date: 2026-03-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|