gitlab-labkit 1.0.0 → 1.1.2

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: 848c7a3b2a208349e041ead5190bb2f665190100e9c4868b3391f040674834b7
4
- data.tar.gz: be220cf29fa57499b1101cabda163816fd37f77b09b5b3be93464cd87c6294b6
3
+ metadata.gz: a3f875b5fa4af36bdb6646a69d5acab871bd2fe84ee6876a57958e9264441378
4
+ data.tar.gz: f86e176c5bed6fcbeae0ac82570b7b98349a56dac3b032cb0072573206ea273e
5
5
  SHA512:
6
- metadata.gz: e5e4181d842aa238bc113b4d1486471f71b44e3d04d7f8613583e2ae23eeb33a4c6e275a5fccb18b2db5a962c0e4ff294b2df7a6eb9bd6c08a8aaf88a9146a96
7
- data.tar.gz: eeab7e40652242988f381b9192a9384a9098a7bd31ad8ef6e8f0b17c5c6f17032a8f2199f9b1fbe543e9d11ba04a30cb5c59a2b96d9bb86df3a30a026924e96f
6
+ metadata.gz: d47772da83bcf81c149e957c4e692042ce1388dc774abbfcf9e9d3a765fa9fda88da1b8742314df3b1010e800935327cf4338c0f7ef05f6d2141d8aad3cb317d
7
+ data.tar.gz: fc070e4ef55f7fac9bedf2af11a88aa5c27aff9c8cae3d634b78a3381e2694a67871a7c16c7865950ad3f7d7371c10cc14e1bbeb38c9bca8f36d00c68717a70c
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.36.0
6
+ _commit: v1.38.0
7
7
  _src_path: https://gitlab.com/gitlab-com/gl-infra/common-template-copier.git
8
8
  ee_licensed: false
9
9
  golang: false
@@ -1,5 +1,5 @@
1
1
  # DO NOT MANUALLY EDIT; Run ./scripts/update-asdf-version-variables.sh to update this
2
2
  variables:
3
- GL_ASDF_RUBY_VERSION: "3.4.7"
3
+ GL_ASDF_RUBY_VERSION: "3.4.8"
4
4
  GL_ASDF_SHELLCHECK_VERSION: "0.11"
5
5
  GL_ASDF_SHFMT_VERSION: "3.12"
data/.gitlab-ci.yml CHANGED
@@ -19,13 +19,13 @@ include:
19
19
  # It includes standard checks, gitlab-scanners, validations and release processes
20
20
  # common to all projects using this template library.
21
21
  # see https://gitlab.com/gitlab-com/gl-infra/common-ci-tasks/-/blob/main/templates/standard.md
22
- - component: $CI_SERVER_FQDN/gitlab-com/gl-infra/common-ci-tasks/standard-build@v2.78
22
+ - component: $CI_SERVER_FQDN/gitlab-com/gl-infra/common-ci-tasks/standard-build@v3.4
23
23
 
24
24
  # Runs rspec tests and rubocop on the project
25
25
  # see https://gitlab.com/gitlab-com/gl-infra/common-ci-tasks/-/blob/main/templates/ruby.md
26
- - component: $CI_SERVER_FQDN/gitlab-com/gl-infra/common-ci-tasks/ruby-build@v2.78
26
+ - component: $CI_SERVER_FQDN/gitlab-com/gl-infra/common-ci-tasks/ruby-build@v3.4
27
27
 
28
- - component: $CI_SERVER_FQDN/gitlab-com/gl-infra/common-ci-tasks/danger@v2.78
28
+ - component: $CI_SERVER_FQDN/gitlab-com/gl-infra/common-ci-tasks/danger@v3.4
29
29
 
30
30
  .test_template: &test_definition
31
31
  extends: .with_bundle
@@ -25,7 +25,7 @@ repos:
25
25
  # Documentation available at
26
26
  # https://gitlab.com/gitlab-com/gl-infra/common-ci-tasks/-/blob/main/docs/pre-commit.md
27
27
  - repo: https://gitlab.com/gitlab-com/gl-infra/common-ci-tasks
28
- rev: v3.0 # renovate:managed
28
+ rev: v3.4 # renovate:managed
29
29
 
30
30
  hooks:
31
31
  - id: shellcheck # Run shellcheck for changed Shell files
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2025-05-05 15:54:30 UTC using RuboCop version 1.68.0.
3
+ # on 2025-11-17 07:59:08 UTC using RuboCop version 1.71.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,7 +25,7 @@ Fips/SHA1:
25
25
  Exclude:
26
26
  - 'spec/labkit/fips_spec.rb'
27
27
 
28
- # Offense count: 8
28
+ # Offense count: 10
29
29
  # This cop supports safe autocorrection (--autocorrect).
30
30
  # Configuration parameters: Include.
31
31
  # Include: **/*.gemspec
@@ -56,11 +56,26 @@ Layout/ClassStructure:
56
56
  Exclude:
57
57
  - 'lib/labkit/tracing/rack_middleware.rb'
58
58
 
59
- # Offense count: 1
59
+ # Offense count: 2
60
60
  # This cop supports safe autocorrection (--autocorrect).
61
61
  Layout/EmptyLineAfterMagicComment:
62
62
  Exclude:
63
63
  - 'lib/labkit/logging/json_logger.rb'
64
+ - 'spec/support/grpc_service/test_pb.rb'
65
+
66
+ # Offense count: 1
67
+ # This cop supports safe autocorrection (--autocorrect).
68
+ Layout/EmptyLines:
69
+ Exclude:
70
+ - 'spec/support/grpc_service/test_pb.rb'
71
+
72
+ # Offense count: 1
73
+ # This cop supports safe autocorrection (--autocorrect).
74
+ # Configuration parameters: EnforcedStyle.
75
+ # SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines, beginning_only, ending_only
76
+ Layout/EmptyLinesAroundClassBody:
77
+ Exclude:
78
+ - 'spec/support/grpc_service/test_services_pb.rb'
64
79
 
65
80
  # Offense count: 1
66
81
  # This cop supports safe autocorrection (--autocorrect).
@@ -144,7 +159,8 @@ Lint/UnexpectedBlockArity:
144
159
 
145
160
  # Offense count: 41
146
161
  # This cop supports safe autocorrection (--autocorrect).
147
- # Configuration parameters: AutoCorrect, AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods.
162
+ # Configuration parameters: AutoCorrect, AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
163
+ # NotImplementedExceptions: NotImplementedError
148
164
  Lint/UnusedMethodArgument:
149
165
  Exclude:
150
166
  - 'lib/labkit/correlation/grpc/client_interceptor.rb'
@@ -254,7 +270,7 @@ RSpec/LetBeforeExamples:
254
270
  Exclude:
255
271
  - 'spec/labkit/tracing_spec.rb'
256
272
 
257
- # Offense count: 20
273
+ # Offense count: 31
258
274
  # Configuration parameters: AllowSubject.
259
275
  RSpec/MultipleMemoizedHelpers:
260
276
  Max: 8
@@ -326,7 +342,7 @@ Rails/NegateInclude:
326
342
  Exclude:
327
343
  - 'spec/labkit/correlation/grpc/client_interceptor_spec.rb'
328
344
 
329
- # Offense count: 1
345
+ # Offense count: 2
330
346
  # This cop supports unsafe autocorrection (--autocorrect-all).
331
347
  # Configuration parameters: Include.
332
348
  # Include: **/Rakefile, **/*.rake
@@ -361,6 +377,14 @@ Style/AsciiComments:
361
377
  Exclude:
362
378
  - 'spec/support/grpc_service/test_service_impl.rb'
363
379
 
380
+ # Offense count: 7
381
+ # This cop supports safe autocorrection (--autocorrect).
382
+ # Configuration parameters: EnforcedStyle.
383
+ # SupportedStyles: allow_single_line, allow_always, disallow
384
+ Style/EndlessMethod:
385
+ Exclude:
386
+ - 'lib/labkit/user_experience_sli/null.rb'
387
+
364
388
  # Offense count: 3
365
389
  # This cop supports safe autocorrection (--autocorrect).
366
390
  # Configuration parameters: AllowedVars.
@@ -369,6 +393,15 @@ Style/FetchEnvVar:
369
393
  - 'lib/labkit/tracing.rb'
370
394
  - 'spec/helpers/stub_env.rb'
371
395
 
396
+ # Offense count: 5
397
+ # This cop supports unsafe autocorrection (--autocorrect-all).
398
+ Style/FileNull:
399
+ Exclude:
400
+ - 'spec/labkit/logging/json_logger_spec.rb'
401
+ - 'spec/labkit/middleware/sidekiq/user_experience_sli/client_spec.rb'
402
+ - 'spec/labkit/middleware/sidekiq/user_experience_sli/server_spec.rb'
403
+ - 'spec/spec_helper.rb'
404
+
372
405
  # Offense count: 8
373
406
  # This cop supports unsafe autocorrection (--autocorrect-all).
374
407
  # Configuration parameters: EnforcedStyle.
@@ -381,7 +414,7 @@ Style/FrozenStringLiteralComment:
381
414
  - 'spec/labkit/tracing/rails/active_support/cache_generate_instrumenter_spec.rb'
382
415
  - 'spec/labkit/tracing/rails/active_support/cache_read_instrumenter_spec.rb'
383
416
  - 'spec/labkit/tracing/rails/active_support/cache_write_instrumenter_spec.rb'
384
- - 'spec/support/grpc_service/test_pb.rb'
417
+ - 'spec/support/grpc_service/test_services_pb.rb'
385
418
  - 'tools/update-changelog.rb'
386
419
 
387
420
  # Offense count: 2
@@ -397,7 +430,7 @@ Style/GuardClause:
397
430
  Exclude:
398
431
  - 'lib/labkit/logging/json_logger.rb'
399
432
 
400
- # Offense count: 34
433
+ # Offense count: 33
401
434
  # This cop supports safe autocorrection (--autocorrect).
402
435
  # Configuration parameters: EnforcedStyle, EnforcedShorthandSyntax, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols.
403
436
  # SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
@@ -408,7 +441,6 @@ Style/HashSyntax:
408
441
  - 'lib/labkit/tracing/tracing_utils.rb'
409
442
  - 'spec/labkit/tracing/rack_middleware_spec.rb'
410
443
  - 'spec/labkit/tracing/redis/redis_interceptor_helper_spec.rb'
411
- - 'spec/support/grpc_service/test_pb.rb'
412
444
  - 'spec/support/tracing/shared_examples.rb'
413
445
 
414
446
  # Offense count: 1
@@ -459,11 +491,12 @@ Style/RedundantBegin:
459
491
  Exclude:
460
492
  - 'spec/labkit/net_http_publisher_spec.rb'
461
493
 
462
- # Offense count: 3
494
+ # Offense count: 4
463
495
  # This cop supports safe autocorrection (--autocorrect).
464
496
  Style/RedundantConstantBase:
465
497
  Exclude:
466
498
  - 'spec/labkit/logging/grpc/server_interceptor_spec.rb'
499
+ - 'spec/support/grpc_service/test_pb.rb'
467
500
 
468
501
  # Offense count: 3
469
502
  # This cop supports safe autocorrection (--autocorrect).
@@ -491,6 +524,12 @@ Style/RedundantReturn:
491
524
  Exclude:
492
525
  - 'lib/labkit/tracing/jaeger_factory.rb'
493
526
 
527
+ # Offense count: 1
528
+ # This cop supports safe autocorrection (--autocorrect).
529
+ Style/RedundantStringEscape:
530
+ Exclude:
531
+ - 'spec/support/grpc_service/test_pb.rb'
532
+
494
533
  # Offense count: 3
495
534
  # This cop supports unsafe autocorrection (--autocorrect-all).
496
535
  # Configuration parameters: Mode.
@@ -519,7 +558,7 @@ Style/SymbolLiteral:
519
558
  - 'lib/labkit/tracing/tracing_utils.rb'
520
559
  - 'spec/support/tracing/shared_examples.rb'
521
560
 
522
- # Offense count: 39
561
+ # Offense count: 42
523
562
  # This cop supports safe autocorrection (--autocorrect).
524
563
  # Configuration parameters: EnforcedStyleForMultiline.
525
564
  # SupportedStylesForMultiline: comma, consistent_comma, no_comma
@@ -545,16 +584,16 @@ Style/TrailingCommaInArrayLiteral:
545
584
  - 'spec/labkit/tracing/rails/active_support/cache_generate_instrumenter_spec.rb'
546
585
  - 'spec/labkit/tracing/rails/active_support/cache_write_instrumenter_spec.rb'
547
586
 
548
- # Offense count: 84
587
+ # Offense count: 85
549
588
  # This cop supports safe autocorrection (--autocorrect).
550
589
  # Configuration parameters: EnforcedStyleForMultiline.
551
590
  # SupportedStylesForMultiline: comma, consistent_comma, no_comma
552
591
  Style/TrailingCommaInHashLiteral:
553
592
  Enabled: false
554
593
 
555
- # Offense count: 68
594
+ # Offense count: 75
556
595
  # This cop supports safe autocorrection (--autocorrect).
557
- # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
596
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
558
597
  # URISchemes: http, https
559
598
  Layout/LineLength:
560
- Max: 294
599
+ Max: 567
data/.tool-versions CHANGED
@@ -1,3 +1,3 @@
1
- ruby 3.4.7
1
+ ruby 3.4.8
2
2
  shfmt 3.12
3
3
  shellcheck 0.11
data/Rakefile CHANGED
@@ -18,7 +18,13 @@ end
18
18
  desc "Generate test protobuf stubs"
19
19
  task :gen_test_proto do
20
20
  system "grpc_tools_ruby_protoc --ruby_out=. --grpc_out=. spec/support/grpc_service/test.proto"
21
- Rufo::Command.run(["spec/support/grpc_service/test_pb.rb", "spec/support/grpc_service/test_services_pb.rb"])
21
+
22
+ # Fix require statement to use require_relative for test environment.
23
+ # This is a workaround for https://github.com/grpc/grpc/issues/29027.
24
+ services_file = "spec/support/grpc_service/test_services_pb.rb"
25
+ content = File.read(services_file)
26
+ content.gsub!(%r{^require ['"]spec/support/grpc_service/test_pb['"]$}, "require_relative 'test_pb'")
27
+ File.write(services_file, content)
22
28
  end
23
29
 
24
30
  task :fix => ["rubocop:autocorrect"]
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "http://json-schema.org/draft-06/schema#",
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "https://gitlab.com/gitlab-org/ruby/gems/labkit-ruby/-/raw/master/config/user_experience_slis/schema.json",
4
4
  "title": "User Experience SLI Definition",
5
5
  "description": "Schema for GitLab User Experience SLI files",
@@ -12,8 +12,8 @@
12
12
  },
13
13
  "feature_category": {
14
14
  "type": "string",
15
- "minLength": 1,
16
- "description": "GitLab feature category this experience belongs to"
15
+ "description": "GitLab feature category this experience belongs to",
16
+ "$ref": "https://gitlab.com/gitlab-org/gitlab/-/raw/master/config/feature_categories/schema.json"
17
17
  },
18
18
  "urgency": {
19
19
  "type": "string",
@@ -23,9 +23,10 @@ Gem::Specification.new do |spec|
23
23
  spec.add_runtime_dependency "actionpack", ">= 5.0.0", "< 8.1.0"
24
24
  spec.add_runtime_dependency "activesupport", ">= 5.0.0", "< 8.1.0"
25
25
  spec.add_runtime_dependency "grpc", ">= 1.75" # Be sure to update the "grpc-tools" dev_dependency too
26
- spec.add_runtime_dependency "google-protobuf", "~> 3" # Keep the major version to 3 until we update the `grpc` gem
26
+ spec.add_runtime_dependency "google-protobuf", ">= 3.25", "< 5.0"
27
27
  spec.add_runtime_dependency "jaeger-client", "~> 1.1.0"
28
- spec.add_runtime_dependency 'json-schema', '~> 5.1'
28
+ spec.add_runtime_dependency 'json_schemer', '>= 2.3.0', '< 3.0'
29
+ spec.add_runtime_dependency "openssl", "~> 3.3.2"
29
30
  spec.add_runtime_dependency "opentracing", "~> 0.4"
30
31
  spec.add_runtime_dependency "pg_query", ">= 6.1.0", "< 7.0"
31
32
  spec.add_runtime_dependency "prometheus-client-mmap", "~> 1.2.9"
@@ -35,7 +36,7 @@ Gem::Specification.new do |spec|
35
36
  spec.add_development_dependency "excon", "~> 0.78.1"
36
37
  spec.add_development_dependency "faraday", "~> 1.10.3"
37
38
  spec.add_development_dependency "gitlab-dangerfiles", "~> 2.11.0"
38
- spec.add_development_dependency "gitlab-styles", "~> 13.0.2"
39
+ spec.add_development_dependency "gitlab-styles", "~> 13.1"
39
40
  spec.add_development_dependency "grpc-tools", ">= 1.75"
40
41
  spec.add_development_dependency "httparty", "~> 0.22.0"
41
42
  spec.add_development_dependency "httpclient", "~> 2.9.0"
@@ -0,0 +1,74 @@
1
+ # JSON Schema Reference Resolver
2
+
3
+ ## Overview
4
+
5
+ The `RefResolver` class provides HTTP/HTTPS-based resolution for external JSON schema references. It enables validation of JSON data against schemas that reference remote schema definitions, with built-in caching and timeout protection.
6
+
7
+ ## Why Use RefResolver?
8
+
9
+ When working with JSON schemas, you may encounter `$ref` properties that point to external schema definitions hosted remotely:
10
+
11
+ ```json
12
+ {
13
+ "$ref": "https://example.com/schemas/common.json#/definitions/address"
14
+ }
15
+ ```
16
+
17
+ The `RefResolver` solves several key challenges:
18
+
19
+ - **Remote Schema Resolution**: Automatically fetches and parses external schema definitions over HTTP/HTTPS
20
+ - **Performance Optimization**: Caches fetched schemas to avoid redundant network requests
21
+ - **Reliability**: Implements configurable timeouts to prevent hanging on slow or unresponsive endpoints
22
+ - **Error Handling**: Provides clear error messages for network failures, timeouts, and invalid JSON responses
23
+
24
+ ## How to Use
25
+
26
+ ### Basic Usage
27
+
28
+ The `RefResolver` is designed to work with the [JSONSchemer](https://github.com/davishmcclurg/json_schemer) gem:
29
+
30
+ ```ruby
31
+ require 'labkit/json_schema/ref_resolver'
32
+
33
+ # Create a resolver instance
34
+ resolver = Labkit::JsonSchema::RefResolver.new
35
+
36
+ # Use with JSONSchemer
37
+ schema = JSONSchemer.schema(
38
+ your_schema_hash,
39
+ ref_resolver: resolver
40
+ )
41
+
42
+ # Validate data
43
+ schema.valid?(your_data)
44
+ ```
45
+
46
+ ### Custom Timeout Configuration
47
+
48
+ By default, the resolver uses a 2-second timeout for both connection and read operations. You can customize this:
49
+
50
+ ```ruby
51
+ # Use a 5-second timeout
52
+ resolver = Labkit::JsonSchema::RefResolver.new(timeout_s: 5)
53
+ ```
54
+
55
+ ### Cache Management
56
+
57
+ The resolver maintains a class-level cache to share fetched schemas across instances:
58
+
59
+ ```ruby
60
+ # Access the cache
61
+ Labkit::JsonSchema::RefResolver.cache
62
+
63
+ # Clear the cache if needed
64
+ Labkit::JsonSchema::RefResolver.cache.clear
65
+ ```
66
+
67
+ ## Use Case Example
68
+
69
+ The `RefResolver` is used in the User Experience SLI Registry [lib/labkit/user_experience_sli/registry.rb](lib/labkit/user_experience_sli/registry.rb) to validate user experience definitions against a JSON schema.
70
+
71
+ ## Implementation Details
72
+
73
+ - Only HTTP and HTTPS schemes are supported. Other schemes (FTP, file://, etc.) will raise an error.
74
+ - The class-level cache is shared across all instances. In multi-threaded environments, consider using appropriate synchronization mechanisms if cache consistency is critical.
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'uri'
5
+ require 'json'
6
+
7
+ module Labkit
8
+ module JsonSchema
9
+ # This class resolves JSON schema references (e.g., "$ref": "http://example.com/schema.json")
10
+ # by fetching remote schemas over HTTP/HTTPS and caching them.
11
+ # It is used by JSONSchemer to resolve external schema definitions.
12
+ # We need it to validate JSON data against schemas that might be hosted remotely.
13
+ class RefResolver
14
+ mattr_accessor :cache, default: {}
15
+
16
+ def initialize(timeout_s: 2)
17
+ @timeout_s = timeout_s
18
+ end
19
+
20
+ def call(uri)
21
+ uri_str = uri.to_s
22
+
23
+ return cache[uri_str] if cache.key?(uri_str)
24
+
25
+ cache[uri_str] = fetch_remote_schema(uri_str)
26
+ end
27
+
28
+ private
29
+
30
+ def fetch_remote_schema(uri_str)
31
+ uri = URI(uri_str)
32
+
33
+ raise(JSONSchemer::UnknownRef, "Unsupported URI scheme: #{uri_str}") unless %w[http https].include?(uri.scheme)
34
+
35
+ response = Net::HTTP.start(
36
+ uri.host,
37
+ uri.port,
38
+ use_ssl: uri.scheme == 'https',
39
+ open_timeout: @timeout_s,
40
+ read_timeout: @timeout_s
41
+ ) do |http|
42
+ request = Net::HTTP::Get.new(uri.request_uri)
43
+ http.request(request)
44
+ end
45
+
46
+ unless response.is_a?(Net::HTTPSuccess)
47
+ raise(
48
+ JSONSchemer::UnknownRef,
49
+ "Failed to fetch #{uri_str}: #{response.code} #{response.message}"
50
+ )
51
+ end
52
+
53
+ JSON.parse(response.body)
54
+ rescue Net::OpenTimeout, Net::ReadTimeout => e
55
+ raise(JSONSchemer::UnknownRef, "Timeout fetching #{uri_str}: #{e.message}")
56
+ rescue JSON::ParserError => e
57
+ raise(JSONSchemer::UnknownRef, "Invalid JSON at #{uri_str}: #{e.message}")
58
+ rescue SocketError, Errno::ECONNREFUSED => e
59
+ raise(JSONSchemer::UnknownRef, "Connection failed for #{uri_str}: #{e.message}")
60
+ end
61
+ end
62
+ end
63
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require "time"
3
+ require "date"
3
4
  require "logger"
4
5
  require "json"
5
6
 
@@ -52,7 +53,7 @@ module Labkit
52
53
  data[:message] = message
53
54
  when Hash
54
55
  reject_reserved_log_keys!(message)
55
- format_time!(data)
56
+ format_time!(message)
56
57
  data.merge!(message)
57
58
  end
58
59
 
@@ -81,11 +82,23 @@ module Labkit
81
82
 
82
83
  def format_time!(hash)
83
84
  hash.each do |key, value|
84
- if value.is_a?(Time)
85
- hash[key] = value.utc.iso8601(3)
86
- elsif value.is_a?(Hash)
87
- format_time!(value)
88
- end
85
+ hash[key] = convert_time_value(value)
86
+ end
87
+ end
88
+
89
+ def convert_time_value(value)
90
+ case value
91
+ when Time
92
+ value.utc.iso8601(3)
93
+ when DateTime
94
+ value.to_time.utc.iso8601(3)
95
+ when Hash
96
+ format_time!(value)
97
+ value
98
+ when Array
99
+ value.map { |v| convert_time_value(v) }
100
+ else
101
+ value
89
102
  end
90
103
  end
91
104
  end
@@ -33,6 +33,23 @@ This allows you to:
33
33
 
34
34
  **Note:** The registry is automatically reset when the configuration changes, so the new path takes effect immediately.
35
35
 
36
+ ### RefResolver Timeout Configuration
37
+
38
+ When validating user experience SLI definitions against JSON schemas, the system may need to fetch remote schema references over HTTP/HTTPS. By default, the timeout for these requests is 2 seconds. You can configure a custom timeout:
39
+
40
+ ```ruby
41
+ Labkit::UserExperienceSli.configure do |config|
42
+ config.ref_resolver_timeout = 5 # Set timeout to 5 seconds
43
+ end
44
+ ```
45
+
46
+ This configuration is useful when:
47
+ - Working in environments with slower network connections
48
+ - Fetching schemas from remote servers with higher latency
49
+ - Needing stricter timeout constraints for faster failure detection
50
+
51
+ **Note:** The timeout applies to both connection opening and reading operations when fetching remote JSON schema references.
52
+
36
53
  ### User Experience Definitions
37
54
 
38
55
  User Experience SLI definitions will be lazy loaded from the default directory (`config/user_experience_slis`).
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'forwardable'
4
- require 'json-schema'
4
+ require 'json_schemer'
5
5
  require 'pathname'
6
6
  require 'yaml'
7
+ require 'labkit/json_schema/ref_resolver'
7
8
 
8
9
  module Labkit
9
10
  module UserExperienceSli
@@ -77,8 +78,7 @@ module Labkit
77
78
  content = YAML.safe_load(file_path.read)
78
79
  return nil unless content.is_a?(Hash)
79
80
 
80
- errors = JSON::Validator.fully_validate(schema, content)
81
- return Definition.new(user_experience_id: experience_id, **content) if errors.empty?
81
+ return Definition.new(user_experience_id: experience_id, **content) if schema.valid?(content)
82
82
 
83
83
  warn("Invalid schema for #{file_path}")
84
84
 
@@ -90,7 +90,11 @@ module Labkit
90
90
  end
91
91
 
92
92
  def schema
93
- @schema ||= JSON.parse(File.read(SCHEMA_PATH))
93
+ @schema ||= begin
94
+ schema = JSON.parse(File.read(SCHEMA_PATH))
95
+ timeout = Labkit::UserExperienceSli.configuration.ref_resolver_timeout
96
+ JSONSchemer.schema(schema, ref_resolver: Labkit::JsonSchema::RefResolver.new(timeout_s: timeout))
97
+ end
94
98
  end
95
99
 
96
100
  def warn(message)
@@ -16,11 +16,12 @@ module Labkit
16
16
  module UserExperienceSli
17
17
  # Configuration class for UserExperienceSli
18
18
  class Configuration
19
- attr_accessor :logger, :registry_path
19
+ attr_accessor :logger, :registry_path, :ref_resolver_timeout
20
20
 
21
21
  def initialize
22
22
  @logger = Labkit::Logging::JsonLogger.new($stdout)
23
23
  @registry_path = File.join("config", "user_experience_slis")
24
+ @ref_resolver_timeout = 2
24
25
  end
25
26
  end
26
27
 
@@ -53,8 +53,11 @@ fi
53
53
 
54
54
  # install mise/asdf dependencies
55
55
  echo "installing required plugins with mise install.."
56
- mise plugins update
56
+ mise plugins update -q
57
57
  mise install
58
+
59
+ # set PROMPT_COMMAND to empty value for mise if unset
60
+ : "${PROMPT_COMMAND:=}"
58
61
  eval "$(mise activate bash)"
59
62
 
60
63
  # pre-commit is optional
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: 1.0.0
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Newdigate
@@ -67,16 +67,22 @@ dependencies:
67
67
  name: google-protobuf
68
68
  requirement: !ruby/object:Gem::Requirement
69
69
  requirements:
70
- - - "~>"
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '3.25'
73
+ - - "<"
71
74
  - !ruby/object:Gem::Version
72
- version: '3'
75
+ version: '5.0'
73
76
  type: :runtime
74
77
  prerelease: false
75
78
  version_requirements: !ruby/object:Gem::Requirement
76
79
  requirements:
77
- - - "~>"
80
+ - - ">="
78
81
  - !ruby/object:Gem::Version
79
- version: '3'
82
+ version: '3.25'
83
+ - - "<"
84
+ - !ruby/object:Gem::Version
85
+ version: '5.0'
80
86
  - !ruby/object:Gem::Dependency
81
87
  name: jaeger-client
82
88
  requirement: !ruby/object:Gem::Requirement
@@ -92,19 +98,39 @@ dependencies:
92
98
  - !ruby/object:Gem::Version
93
99
  version: 1.1.0
94
100
  - !ruby/object:Gem::Dependency
95
- name: json-schema
101
+ name: json_schemer
102
+ requirement: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: 2.3.0
107
+ - - "<"
108
+ - !ruby/object:Gem::Version
109
+ version: '3.0'
110
+ type: :runtime
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: 2.3.0
117
+ - - "<"
118
+ - !ruby/object:Gem::Version
119
+ version: '3.0'
120
+ - !ruby/object:Gem::Dependency
121
+ name: openssl
96
122
  requirement: !ruby/object:Gem::Requirement
97
123
  requirements:
98
124
  - - "~>"
99
125
  - !ruby/object:Gem::Version
100
- version: '5.1'
126
+ version: 3.3.2
101
127
  type: :runtime
102
128
  prerelease: false
103
129
  version_requirements: !ruby/object:Gem::Requirement
104
130
  requirements:
105
131
  - - "~>"
106
132
  - !ruby/object:Gem::Version
107
- version: '5.1'
133
+ version: 3.3.2
108
134
  - !ruby/object:Gem::Dependency
109
135
  name: opentracing
110
136
  requirement: !ruby/object:Gem::Requirement
@@ -221,14 +247,14 @@ dependencies:
221
247
  requirements:
222
248
  - - "~>"
223
249
  - !ruby/object:Gem::Version
224
- version: 13.0.2
250
+ version: '13.1'
225
251
  type: :development
226
252
  prerelease: false
227
253
  version_requirements: !ruby/object:Gem::Requirement
228
254
  requirements:
229
255
  - - "~>"
230
256
  - !ruby/object:Gem::Version
231
- version: 13.0.2
257
+ version: '13.1'
232
258
  - !ruby/object:Gem::Dependency
233
259
  name: grpc-tools
234
260
  requirement: !ruby/object:Gem::Requirement
@@ -462,6 +488,8 @@ files:
462
488
  - lib/labkit/fields.rb
463
489
  - lib/labkit/fips.rb
464
490
  - lib/labkit/httpclient_publisher.rb
491
+ - lib/labkit/json_schema/README.md
492
+ - lib/labkit/json_schema/ref_resolver.rb
465
493
  - lib/labkit/logging.rb
466
494
  - lib/labkit/logging/grpc.rb
467
495
  - lib/labkit/logging/grpc/server_interceptor.rb
@@ -533,7 +561,6 @@ files:
533
561
  - lib/labkit/user_experience_sli/null.rb
534
562
  - lib/labkit/user_experience_sli/registry.rb
535
563
  - renovate.json
536
- - scripts/install-asdf-plugins.sh
537
564
  - scripts/prepare-dev-env.sh
538
565
  - scripts/update-asdf-version-variables.sh
539
566
  homepage: https://gitlab.com/gitlab-org/labkit-ruby
@@ -1,13 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Vendored from https://gitlab.com/gitlab-com/gl-infra/common-template-copier
3
- # Consider contributing upstream when updating this file
4
-
5
- # This file is deprecated: going forward running `mise install` should be sufficient.
6
-
7
- set -euo pipefail
8
- IFS=$'\n\t'
9
-
10
- echo >&2 -e "2024-08-07: this file is deprecated: going forward, simply run 'mise install' to install plugins."
11
- echo >&2 -e "Recommended reading: https://gitlab.com/gitlab-com/gl-infra/common-ci-tasks/-/blob/main/docs/developer-setup.md"
12
-
13
- mise install