gitlab-labkit 2.0.0 → 2.1.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/.copier-answers.yml +2 -1
- data/.gitlab-ci-other-versions.yml +5 -0
- data/.gitlab-ci.yml +1 -1
- data/docker-compose.yml +1 -1
- data/gitlab-labkit.gemspec +7 -7
- data/lib/labkit/rate_limit/evaluator.rb +84 -5
- data/lib/labkit/rate_limit/rule.rb +26 -3
- metadata +44 -19
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1457da9fa7cec587b47834870a4eb60f5a21c9966111d1d9edd0e7e0a49b4ff3
|
|
4
|
+
data.tar.gz: 631e56481d2be50e976a16aefa6fd6a250759089b56dde0414af059fd55c4ba7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5d6aba7952cc495dd4b74ea0aa452f473e01dc6a6bda2a94d1238d9102f5b448de2b4ae1765f87e2020d2fb460b1613044fe9403f0019b54b050b3a48261b425
|
|
7
|
+
data.tar.gz: 21ddb1d302b53049a605052d67bbdf2d51bee9a4e80f82c6c10f689d5b292397e0d913dae4b05e66c93ee4c93d831e14e885c448a77b049dab48ac1bda3b84b5
|
data/.copier-answers.yml
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# See the project for instructions on how to update the project
|
|
4
4
|
#
|
|
5
5
|
# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
|
|
6
|
-
_commit: v1.
|
|
6
|
+
_commit: v1.50.0
|
|
7
7
|
_src_path: https://gitlab.com/gitlab-com/gl-infra/common-template-copier.git
|
|
8
8
|
ee_licensed: false
|
|
9
9
|
gitlab_namespace: gitlab-org/ruby/gems
|
|
@@ -11,6 +11,7 @@ golang: false
|
|
|
11
11
|
helm: false
|
|
12
12
|
initial_codeowners: '@reprazent @andrewn @mkaeppler @ayufan'
|
|
13
13
|
jsonnet: false
|
|
14
|
+
measure_performance: false
|
|
14
15
|
project_name: labkit-ruby
|
|
15
16
|
release_platform: false
|
|
16
17
|
ruby: true
|
data/.gitlab-ci.yml
CHANGED
data/docker-compose.yml
CHANGED
data/gitlab-labkit.gemspec
CHANGED
|
@@ -22,17 +22,17 @@ Gem::Specification.new do |spec|
|
|
|
22
22
|
spec.required_ruby_version = ">= 3.3", "< 5"
|
|
23
23
|
|
|
24
24
|
# Please maintain alphabetical order for dependencies
|
|
25
|
-
spec.add_runtime_dependency "actionpack", ">= 5.0.0", "< 8.
|
|
26
|
-
spec.add_runtime_dependency "activesupport", ">= 5.0.0", "< 8.
|
|
25
|
+
spec.add_runtime_dependency "actionpack", ">= 5.0.0", "< 8.2.0"
|
|
26
|
+
spec.add_runtime_dependency "activesupport", ">= 5.0.0", "< 8.2.0"
|
|
27
27
|
spec.add_runtime_dependency "grpc", ">= 1.75" # Be sure to update the "grpc-tools" dev_dependency too
|
|
28
28
|
spec.add_runtime_dependency "google-protobuf", ">= 3.25", "< 5.0"
|
|
29
29
|
spec.add_runtime_dependency "jaeger-client", "~> 1.1.0"
|
|
30
30
|
spec.add_runtime_dependency "json_schemer", ">= 2.3.0", "< 3.0"
|
|
31
31
|
spec.add_runtime_dependency "openssl", "~> 3.3.2"
|
|
32
|
-
spec.add_runtime_dependency "opentelemetry-sdk", "
|
|
33
|
-
spec.add_runtime_dependency "opentelemetry-instrumentation-all", "
|
|
34
|
-
spec.add_runtime_dependency "opentelemetry-exporter-otlp", "
|
|
35
|
-
spec.add_runtime_dependency "opentracing", "
|
|
32
|
+
spec.add_runtime_dependency "opentelemetry-sdk", ">= 1.10", "< 2"
|
|
33
|
+
spec.add_runtime_dependency "opentelemetry-instrumentation-all", ">= 0.89", "< 1"
|
|
34
|
+
spec.add_runtime_dependency "opentelemetry-exporter-otlp", ">= 0.31", "< 1"
|
|
35
|
+
spec.add_runtime_dependency "opentracing", ">= 0.4", "< 1"
|
|
36
36
|
spec.add_runtime_dependency "pg_query", ">= 6.1.0", "< 7.0"
|
|
37
37
|
spec.add_runtime_dependency "prometheus-client-mmap", ">= 1.2", "< 2.0"
|
|
38
38
|
spec.add_runtime_dependency "redis", "> 3.0.0", "< 6.0.0"
|
|
@@ -49,7 +49,7 @@ Gem::Specification.new do |spec|
|
|
|
49
49
|
spec.add_development_dependency "pry", "~> 0.12"
|
|
50
50
|
spec.add_development_dependency "pry-byebug", "~> 3.11"
|
|
51
51
|
spec.add_development_dependency "rack", "~> 2.0"
|
|
52
|
-
spec.add_development_dependency "railties", ">= 5.0.0", "< 8.
|
|
52
|
+
spec.add_development_dependency "railties", ">= 5.0.0", "< 8.2.0"
|
|
53
53
|
spec.add_development_dependency "rake", "~> 13.2"
|
|
54
54
|
spec.add_development_dependency "rest-client", "~> 2.1.0"
|
|
55
55
|
spec.add_development_dependency "rspec", "~> 3.12.0"
|
|
@@ -38,6 +38,26 @@ module Labkit
|
|
|
38
38
|
return {count, redis.call('TTL', KEYS[1])}
|
|
39
39
|
LUA
|
|
40
40
|
|
|
41
|
+
# Atomic SADD + SCARD + conditional EXPIRE. SET-cardinality counterpart
|
|
42
|
+
# of INCR_SCRIPT; same shape (read TTL, mutate, set TTL when missing,
|
|
43
|
+
# return post-state {count, TTL}). count is SCARD, not the SADD return.
|
|
44
|
+
#
|
|
45
|
+
# ttl_before < 0 covers TTL=-2 (key missing) and TTL=-1 (no expiry),
|
|
46
|
+
# so this also self-heals orphan keys left without TTL.
|
|
47
|
+
SADD_SCRIPT = Labkit::Redis::Script.new(<<~LUA)
|
|
48
|
+
local ttl = ARGV[1]
|
|
49
|
+
local member = ARGV[2]
|
|
50
|
+
local ttl_before = redis.call('TTL', KEYS[1])
|
|
51
|
+
|
|
52
|
+
redis.call('SADD', KEYS[1], member)
|
|
53
|
+
local count = redis.call('SCARD', KEYS[1])
|
|
54
|
+
if ttl_before < 0 then
|
|
55
|
+
redis.call('EXPIRE', KEYS[1], ttl)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
return {count, redis.call('TTL', KEYS[1])}
|
|
59
|
+
LUA
|
|
60
|
+
|
|
41
61
|
def initialize(name:, rules:, redis:, logger:)
|
|
42
62
|
@name = name
|
|
43
63
|
@rules = rules
|
|
@@ -70,10 +90,21 @@ module Labkit
|
|
|
70
90
|
|
|
71
91
|
# :log rules are non-terminating: they emit metrics and continue,
|
|
72
92
|
# so a shadow :log rule cannot disable a following :block rule.
|
|
93
|
+
#
|
|
94
|
+
# SET-mode rules (rule.count_distinct set) that match but whose identifier
|
|
95
|
+
# is missing the count_distinct key fail open + log + bump errors_total, and
|
|
96
|
+
# the loop continues to the next rule (the rule is treated as not applicable
|
|
97
|
+
# rather than aborting the whole evaluation).
|
|
73
98
|
def check_rules(identifier, cost)
|
|
74
99
|
@rules.each do |rule|
|
|
75
100
|
next unless rule_matches?(rule, identifier)
|
|
76
101
|
|
|
102
|
+
if rule.count_distinct && missing_count_distinct_value?(rule, identifier)
|
|
103
|
+
log_missing_count_distinct(rule, identifier)
|
|
104
|
+
report_error_metrics
|
|
105
|
+
next
|
|
106
|
+
end
|
|
107
|
+
|
|
77
108
|
result = evaluate_rule(rule, identifier, cost)
|
|
78
109
|
report_matched_metrics(result)
|
|
79
110
|
return result unless rule.action == :log
|
|
@@ -85,6 +116,10 @@ module Labkit
|
|
|
85
116
|
|
|
86
117
|
# Mirror of check_rules without metrics: peek skips :log rules (their state
|
|
87
118
|
# is unobservable through peek).
|
|
119
|
+
#
|
|
120
|
+
# peek does not need the count_distinct identifier key - it reads SCARD on
|
|
121
|
+
# the rule-keyed compound key, which contains the cardinality across all
|
|
122
|
+
# members. So missing-key fail-open does not apply here.
|
|
88
123
|
def peek_rules(identifier)
|
|
89
124
|
@rules.each do |rule|
|
|
90
125
|
next if rule.action == :log
|
|
@@ -100,12 +135,25 @@ module Labkit
|
|
|
100
135
|
rule.match.all? { |key, matcher| matcher.match?(identifier[key]) }
|
|
101
136
|
end
|
|
102
137
|
|
|
138
|
+
def missing_count_distinct_value?(rule, identifier)
|
|
139
|
+
value = identifier[rule.count_distinct]
|
|
140
|
+
value.nil? || value.to_s.empty?
|
|
141
|
+
end
|
|
142
|
+
|
|
103
143
|
def evaluate_rule(rule, identifier, cost)
|
|
104
144
|
redis_key = build_redis_key(rule, identifier)
|
|
105
145
|
resolved_limit = Integer(resolve_value(rule.limit))
|
|
106
146
|
resolved_period = Integer(resolve_value(rule.period))
|
|
107
147
|
|
|
108
|
-
|
|
148
|
+
# cost is ignored for count_distinct rules: SADD is binary (a member is
|
|
149
|
+
# either added or not), and the post-add count is SCARD regardless.
|
|
150
|
+
count, ttl =
|
|
151
|
+
if rule.count_distinct
|
|
152
|
+
sadd_with_ttl(redis_key, identifier[rule.count_distinct], resolved_period)
|
|
153
|
+
else
|
|
154
|
+
incr_with_ttl(redis_key, resolved_period, cost)
|
|
155
|
+
end
|
|
156
|
+
|
|
109
157
|
build_result(rule, resolved_limit, resolved_period, count, ttl)
|
|
110
158
|
end
|
|
111
159
|
|
|
@@ -114,7 +162,7 @@ module Labkit
|
|
|
114
162
|
resolved_limit = Integer(resolve_value(rule.limit))
|
|
115
163
|
resolved_period = Integer(resolve_value(rule.period))
|
|
116
164
|
|
|
117
|
-
count, ttl = read_with_ttl(redis_key)
|
|
165
|
+
count, ttl = rule.count_distinct ? scard_with_ttl(redis_key) : read_with_ttl(redis_key)
|
|
118
166
|
build_result(rule, resolved_limit, resolved_period, count, ttl)
|
|
119
167
|
end
|
|
120
168
|
|
|
@@ -168,7 +216,7 @@ module Labkit
|
|
|
168
216
|
# otherwise.
|
|
169
217
|
def incr_with_ttl(redis_key, period, cost)
|
|
170
218
|
@redis.with do |conn|
|
|
171
|
-
raw_count, ttl =
|
|
219
|
+
raw_count, ttl = INCR_SCRIPT.eval(conn, keys: [redis_key], argv: [period, cost])
|
|
172
220
|
[Float(raw_count), ttl]
|
|
173
221
|
end
|
|
174
222
|
end
|
|
@@ -191,8 +239,29 @@ module Labkit
|
|
|
191
239
|
end
|
|
192
240
|
end
|
|
193
241
|
|
|
194
|
-
|
|
195
|
-
|
|
242
|
+
# Atomic SADD + SCARD + conditional EXPIRE in one Redis operation via Lua.
|
|
243
|
+
# See SADD_SCRIPT for the body. Mirrors incr_with_ttl's shape, including
|
|
244
|
+
# the Float-typed count for uniformity with the INCR path.
|
|
245
|
+
def sadd_with_ttl(redis_key, member, period)
|
|
246
|
+
member_str = encode_char_value(member.to_s)
|
|
247
|
+
@redis.with do |conn|
|
|
248
|
+
raw_count, ttl = SADD_SCRIPT.eval(conn, keys: [redis_key], argv: [period, member_str])
|
|
249
|
+
[Float(raw_count), ttl]
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Pipelined SCARD + TTL. SCARD on a missing key returns 0, so no
|
|
254
|
+
# explicit nil handling is needed (unlike GET in read_with_ttl).
|
|
255
|
+
# SCARD is integer-valued; coerced to Float for type uniformity with
|
|
256
|
+
# the INCR path so callers see a consistent count type.
|
|
257
|
+
def scard_with_ttl(redis_key)
|
|
258
|
+
@redis.with do |conn|
|
|
259
|
+
scard, ttl = conn.pipelined do |pipe|
|
|
260
|
+
pipe.scard(redis_key)
|
|
261
|
+
pipe.ttl(redis_key)
|
|
262
|
+
end
|
|
263
|
+
[Float(scard), ttl]
|
|
264
|
+
end
|
|
196
265
|
end
|
|
197
266
|
|
|
198
267
|
def log_error(error, identifier)
|
|
@@ -204,6 +273,16 @@ module Labkit
|
|
|
204
273
|
)
|
|
205
274
|
end
|
|
206
275
|
|
|
276
|
+
def log_missing_count_distinct(rule, identifier)
|
|
277
|
+
@logger.warn(
|
|
278
|
+
message: "rate_limit_missing_count_distinct",
|
|
279
|
+
name: @name,
|
|
280
|
+
rule: rule.name,
|
|
281
|
+
count_distinct: rule.count_distinct.to_s,
|
|
282
|
+
identifier: identifier&.to_h
|
|
283
|
+
)
|
|
284
|
+
end
|
|
285
|
+
|
|
207
286
|
def report_matched_metrics(result)
|
|
208
287
|
Metrics.calls_total.increment(
|
|
209
288
|
rate_limiter: @name,
|
|
@@ -17,12 +17,32 @@ module Labkit
|
|
|
17
17
|
# (count but always permit; terminates evaluation on match
|
|
18
18
|
# regardless of whether the limit was exceeded)
|
|
19
19
|
# characteristics - identifier keys used to build the compound Redis counter key
|
|
20
|
+
# count_distinct - optional Symbol naming an identifier key. When set, the rule
|
|
21
|
+
# counts the number of distinct values seen for that key within
|
|
22
|
+
# the (characteristics-bucketed) period, backed by a Redis SET.
|
|
23
|
+
# When nil (default), the rule counts the number of calls,
|
|
24
|
+
# backed by INCR. The named key must not overlap +characteristics+.
|
|
20
25
|
#
|
|
21
26
|
# +name+ must be a lowercase alphanumeric-and-underscore string of at most 64
|
|
22
27
|
# characters. It is used as the middle segment of every Redis counter key for
|
|
23
28
|
# this rule, so changing a rule's name mid-window abandons its in-flight counters.
|
|
24
|
-
Rule = Data.define(:name, :match, :limit, :period, :action, :characteristics) do
|
|
25
|
-
def
|
|
29
|
+
Rule = Data.define(:name, :match, :limit, :period, :action, :characteristics, :count_distinct) do
|
|
30
|
+
def self.normalize_count_distinct(value, characteristics_arr)
|
|
31
|
+
sym =
|
|
32
|
+
case value
|
|
33
|
+
when nil then nil
|
|
34
|
+
when Symbol then value
|
|
35
|
+
when String then value.to_sym
|
|
36
|
+
else
|
|
37
|
+
raise ArgumentError, "count_distinct must be a Symbol, String, or nil, got #{value.class}"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
raise ArgumentError, "count_distinct #{sym.inspect} must not overlap characteristics #{characteristics_arr.inspect}" if sym && characteristics_arr.include?(sym)
|
|
41
|
+
|
|
42
|
+
sym
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def initialize(name:, limit:, period:, characteristics:, match: {}, action: :block, count_distinct: nil)
|
|
26
46
|
raise ArgumentError, "name must be a String or Symbol, got #{name.class}" unless name.is_a?(String) || name.is_a?(Symbol)
|
|
27
47
|
|
|
28
48
|
name_str = name.to_s
|
|
@@ -36,13 +56,16 @@ module Labkit
|
|
|
36
56
|
raise ArgumentError, "Rule name too long: #{name.inspect}. Maximum 64 characters" if name_str.length > RULE_NAME_MAX_LENGTH
|
|
37
57
|
end
|
|
38
58
|
|
|
59
|
+
characteristics_arr = Array(characteristics).map(&:to_sym).freeze
|
|
60
|
+
|
|
39
61
|
super(
|
|
40
62
|
name: name_str.freeze,
|
|
41
63
|
match: match.transform_keys(&:to_sym).transform_values { |v| Matcher.build(v) }.freeze,
|
|
42
64
|
limit: limit,
|
|
43
65
|
period: period,
|
|
44
66
|
action: action_sym,
|
|
45
|
-
characteristics:
|
|
67
|
+
characteristics: characteristics_arr,
|
|
68
|
+
count_distinct: self.class.normalize_count_distinct(count_distinct, characteristics_arr)
|
|
46
69
|
)
|
|
47
70
|
end
|
|
48
71
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gitlab-labkit
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrew Newdigate
|
|
@@ -18,7 +18,7 @@ dependencies:
|
|
|
18
18
|
version: 5.0.0
|
|
19
19
|
- - "<"
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
|
-
version: 8.
|
|
21
|
+
version: 8.2.0
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -28,7 +28,7 @@ dependencies:
|
|
|
28
28
|
version: 5.0.0
|
|
29
29
|
- - "<"
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
|
-
version: 8.
|
|
31
|
+
version: 8.2.0
|
|
32
32
|
- !ruby/object:Gem::Dependency
|
|
33
33
|
name: activesupport
|
|
34
34
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -38,7 +38,7 @@ dependencies:
|
|
|
38
38
|
version: 5.0.0
|
|
39
39
|
- - "<"
|
|
40
40
|
- !ruby/object:Gem::Version
|
|
41
|
-
version: 8.
|
|
41
|
+
version: 8.2.0
|
|
42
42
|
type: :runtime
|
|
43
43
|
prerelease: false
|
|
44
44
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -48,7 +48,7 @@ dependencies:
|
|
|
48
48
|
version: 5.0.0
|
|
49
49
|
- - "<"
|
|
50
50
|
- !ruby/object:Gem::Version
|
|
51
|
-
version: 8.
|
|
51
|
+
version: 8.2.0
|
|
52
52
|
- !ruby/object:Gem::Dependency
|
|
53
53
|
name: grpc
|
|
54
54
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -135,58 +135,82 @@ dependencies:
|
|
|
135
135
|
name: opentelemetry-sdk
|
|
136
136
|
requirement: !ruby/object:Gem::Requirement
|
|
137
137
|
requirements:
|
|
138
|
-
- - "
|
|
138
|
+
- - ">="
|
|
139
139
|
- !ruby/object:Gem::Version
|
|
140
140
|
version: '1.10'
|
|
141
|
+
- - "<"
|
|
142
|
+
- !ruby/object:Gem::Version
|
|
143
|
+
version: '2'
|
|
141
144
|
type: :runtime
|
|
142
145
|
prerelease: false
|
|
143
146
|
version_requirements: !ruby/object:Gem::Requirement
|
|
144
147
|
requirements:
|
|
145
|
-
- - "
|
|
148
|
+
- - ">="
|
|
146
149
|
- !ruby/object:Gem::Version
|
|
147
150
|
version: '1.10'
|
|
151
|
+
- - "<"
|
|
152
|
+
- !ruby/object:Gem::Version
|
|
153
|
+
version: '2'
|
|
148
154
|
- !ruby/object:Gem::Dependency
|
|
149
155
|
name: opentelemetry-instrumentation-all
|
|
150
156
|
requirement: !ruby/object:Gem::Requirement
|
|
151
157
|
requirements:
|
|
152
|
-
- - "
|
|
158
|
+
- - ">="
|
|
159
|
+
- !ruby/object:Gem::Version
|
|
160
|
+
version: '0.89'
|
|
161
|
+
- - "<"
|
|
153
162
|
- !ruby/object:Gem::Version
|
|
154
|
-
version:
|
|
163
|
+
version: '1'
|
|
155
164
|
type: :runtime
|
|
156
165
|
prerelease: false
|
|
157
166
|
version_requirements: !ruby/object:Gem::Requirement
|
|
158
167
|
requirements:
|
|
159
|
-
- - "
|
|
168
|
+
- - ">="
|
|
169
|
+
- !ruby/object:Gem::Version
|
|
170
|
+
version: '0.89'
|
|
171
|
+
- - "<"
|
|
160
172
|
- !ruby/object:Gem::Version
|
|
161
|
-
version:
|
|
173
|
+
version: '1'
|
|
162
174
|
- !ruby/object:Gem::Dependency
|
|
163
175
|
name: opentelemetry-exporter-otlp
|
|
164
176
|
requirement: !ruby/object:Gem::Requirement
|
|
165
177
|
requirements:
|
|
166
|
-
- - "
|
|
178
|
+
- - ">="
|
|
179
|
+
- !ruby/object:Gem::Version
|
|
180
|
+
version: '0.31'
|
|
181
|
+
- - "<"
|
|
167
182
|
- !ruby/object:Gem::Version
|
|
168
|
-
version:
|
|
183
|
+
version: '1'
|
|
169
184
|
type: :runtime
|
|
170
185
|
prerelease: false
|
|
171
186
|
version_requirements: !ruby/object:Gem::Requirement
|
|
172
187
|
requirements:
|
|
173
|
-
- - "
|
|
188
|
+
- - ">="
|
|
189
|
+
- !ruby/object:Gem::Version
|
|
190
|
+
version: '0.31'
|
|
191
|
+
- - "<"
|
|
174
192
|
- !ruby/object:Gem::Version
|
|
175
|
-
version:
|
|
193
|
+
version: '1'
|
|
176
194
|
- !ruby/object:Gem::Dependency
|
|
177
195
|
name: opentracing
|
|
178
196
|
requirement: !ruby/object:Gem::Requirement
|
|
179
197
|
requirements:
|
|
180
|
-
- - "
|
|
198
|
+
- - ">="
|
|
181
199
|
- !ruby/object:Gem::Version
|
|
182
200
|
version: '0.4'
|
|
201
|
+
- - "<"
|
|
202
|
+
- !ruby/object:Gem::Version
|
|
203
|
+
version: '1'
|
|
183
204
|
type: :runtime
|
|
184
205
|
prerelease: false
|
|
185
206
|
version_requirements: !ruby/object:Gem::Requirement
|
|
186
207
|
requirements:
|
|
187
|
-
- - "
|
|
208
|
+
- - ">="
|
|
188
209
|
- !ruby/object:Gem::Version
|
|
189
210
|
version: '0.4'
|
|
211
|
+
- - "<"
|
|
212
|
+
- !ruby/object:Gem::Version
|
|
213
|
+
version: '1'
|
|
190
214
|
- !ruby/object:Gem::Dependency
|
|
191
215
|
name: pg_query
|
|
192
216
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -410,7 +434,7 @@ dependencies:
|
|
|
410
434
|
version: 5.0.0
|
|
411
435
|
- - "<"
|
|
412
436
|
- !ruby/object:Gem::Version
|
|
413
|
-
version: 8.
|
|
437
|
+
version: 8.2.0
|
|
414
438
|
type: :development
|
|
415
439
|
prerelease: false
|
|
416
440
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -420,7 +444,7 @@ dependencies:
|
|
|
420
444
|
version: 5.0.0
|
|
421
445
|
- - "<"
|
|
422
446
|
- !ruby/object:Gem::Version
|
|
423
|
-
version: 8.
|
|
447
|
+
version: 8.2.0
|
|
424
448
|
- !ruby/object:Gem::Dependency
|
|
425
449
|
name: rake
|
|
426
450
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -523,6 +547,7 @@ files:
|
|
|
523
547
|
- ".env.example.sh"
|
|
524
548
|
- ".gitignore"
|
|
525
549
|
- ".gitlab-ci-asdf-versions.yml"
|
|
550
|
+
- ".gitlab-ci-other-versions.yml"
|
|
526
551
|
- ".gitlab-ci.yml"
|
|
527
552
|
- ".gitlab/CODEOWNERS"
|
|
528
553
|
- ".gitlab/merge_request_templates/default.md"
|