dependabot-docker_compose 0.298.0 → 0.299.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/lib/dependabot/docker_compose/file_fetcher.rb +1 -1
- data/lib/dependabot/docker_compose/file_parser.rb +44 -3
- data/lib/dependabot/docker_compose/file_updater.rb +2 -44
- data/lib/dependabot/docker_compose/package_manager.rb +0 -2
- data/lib/dependabot/docker_compose.rb +8 -4
- metadata +19 -15
- data/lib/dependabot/docker_compose/metadata_finder.rb +0 -39
- data/lib/dependabot/docker_compose/requirement.rb +0 -43
- data/lib/dependabot/docker_compose/tag.rb +0 -144
- data/lib/dependabot/docker_compose/update_checker.rb +0 -479
- data/lib/dependabot/docker_compose/version.rb +0 -84
- data/lib/dependabot/shared/shared_file_fetcher.rb +0 -99
- data/lib/dependabot/shared/shared_file_parser.rb +0 -80
- data/lib/dependabot/shared/shared_file_updater.rb +0 -261
- data/lib/dependabot/shared/utils/credentials_finder.rb +0 -101
- data/lib/dependabot/shared/utils/helpers.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 861d5c42bba5e0e574cfafdf438e749b62be2948c015641006cc24484f600089
|
4
|
+
data.tar.gz: 458e5b67bc719d3d38f353049098acf6770895e864695a9da763cc20a551b9bf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9c01ed28d5c74d401305cc5a0476adf12b476467f145631f49ce7dd480f6d578e31d9378bc87e9e05ebbfc0467c2ca1d12f8acdd39c0913a72293af1ee8fa8a
|
7
|
+
data.tar.gz: 07326f38f060f039037f14fe307a3c36e65f31f37299f322be6a64f5d66fa272875f8942e54e3499c18acbfa7d34137bb7ae3f53887ece99d7013e04a235f29a
|
@@ -11,7 +11,7 @@ module Dependabot
|
|
11
11
|
sig { override.returns(T::Array[DependencyFile]) }
|
12
12
|
def fetch_files
|
13
13
|
fetched_files = []
|
14
|
-
fetched_files += correctly_encoded_docker_compose_files
|
14
|
+
fetched_files += correctly_encoded_docker_compose_files
|
15
15
|
|
16
16
|
return fetched_files if fetched_files.any?
|
17
17
|
|
@@ -10,7 +10,16 @@ module Dependabot
|
|
10
10
|
class FileParser < Dependabot::Shared::SharedFileParser
|
11
11
|
extend T::Sig
|
12
12
|
|
13
|
-
|
13
|
+
ENV_VAR = /\${[^}]+}/
|
14
|
+
DIGEST = /(?<digest>[0-9a-f]{64})/
|
15
|
+
IMAGE_REGEX = %r{^(#{REGISTRY}/)?#{IMAGE}#{TAG}?(?:@sha256:#{DIGEST})?#{NAME}?}x
|
16
|
+
|
17
|
+
FROM = /FROM/i
|
18
|
+
PLATFORM = /--platform\=(?<platform>\S+)/
|
19
|
+
|
20
|
+
FROM_LINE =
|
21
|
+
%r{^#{FROM}\s+(#{PLATFORM}\s+)?(#{REGISTRY}/)?
|
22
|
+
#{IMAGE}#{TAG}?(?:@sha256:#{DIGEST})?#{NAME}?}x
|
14
23
|
|
15
24
|
sig { returns(Ecosystem) }
|
16
25
|
def ecosystem
|
@@ -28,9 +37,15 @@ module Dependabot
|
|
28
37
|
dependency_set = DependencySet.new
|
29
38
|
|
30
39
|
composefiles.each do |composefile|
|
31
|
-
yaml = YAML.safe_load(T.must(composefile.content))
|
40
|
+
yaml = YAML.safe_load(T.must(composefile.content), aliases: true)
|
41
|
+
next unless yaml["services"].is_a?(Hash)
|
42
|
+
|
32
43
|
yaml["services"].each do |_, service|
|
33
|
-
|
44
|
+
next unless service.is_a?(Hash)
|
45
|
+
|
46
|
+
parsed_from_image = parse_image_spec(service)
|
47
|
+
next unless parsed_from_image
|
48
|
+
|
34
49
|
parsed_from_image["registry"] = nil if parsed_from_image["registry"] == "docker.io"
|
35
50
|
|
36
51
|
version = version_from(parsed_from_image)
|
@@ -45,6 +60,32 @@ module Dependabot
|
|
45
60
|
|
46
61
|
private
|
47
62
|
|
63
|
+
sig { params(service: T.untyped).returns(T.nilable(T::Hash[String, T.nilable(String)])) }
|
64
|
+
def parse_image_spec(service)
|
65
|
+
return nil unless service
|
66
|
+
|
67
|
+
if service["image"]
|
68
|
+
return nil if service["image"].match?(/^\${[^}]+}$/)
|
69
|
+
|
70
|
+
match = IMAGE_REGEX.match(service["image"])
|
71
|
+
return match&.named_captures
|
72
|
+
elsif service["build"].is_a?(Hash) && service["build"]["dockerfile_inline"]
|
73
|
+
return nil if service["build"]["dockerfile_inline"].match?(/^FROM\s+\${[^}]+}$/)
|
74
|
+
|
75
|
+
match = FROM_LINE.match(service["build"]["dockerfile_inline"])
|
76
|
+
return match&.named_captures
|
77
|
+
end
|
78
|
+
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
|
82
|
+
sig { params(parsed_image: T::Hash[String, T.nilable(String)]).returns(T.nilable(String)) }
|
83
|
+
def version_from(parsed_image)
|
84
|
+
return nil if parsed_image["tag"]&.match?(ENV_VAR)
|
85
|
+
|
86
|
+
super
|
87
|
+
end
|
88
|
+
|
48
89
|
sig { override.returns(String) }
|
49
90
|
def package_manager
|
50
91
|
"docker_compose"
|
@@ -10,7 +10,7 @@ module Dependabot
|
|
10
10
|
extend T::Helpers
|
11
11
|
|
12
12
|
YAML_REGEXP = /(docker-)?compose(?>\.[\w-]+)?\.ya?ml/i
|
13
|
-
IMAGE_REGEX = /image:\s
|
13
|
+
IMAGE_REGEX = /(?:from|image:\s*)/i
|
14
14
|
|
15
15
|
sig { override.returns(T::Array[Regexp]) }
|
16
16
|
def self.updated_files_regex
|
@@ -34,7 +34,7 @@ module Dependabot
|
|
34
34
|
|
35
35
|
sig { override.params(escaped_declaration: String).returns(Regexp) }
|
36
36
|
def build_old_declaration_regex(escaped_declaration)
|
37
|
-
%r{#{IMAGE_REGEX}\s+(docker\.io/)?#{escaped_declaration}(?=\s|$)}
|
37
|
+
%r{#{IMAGE_REGEX}\s+["']?(docker\.io/)?#{escaped_declaration}["']?(?=\s|$)}
|
38
38
|
end
|
39
39
|
|
40
40
|
sig { override.returns(T::Array[Dependabot::DependencyFile]) }
|
@@ -54,48 +54,6 @@ module Dependabot
|
|
54
54
|
|
55
55
|
updated_files
|
56
56
|
end
|
57
|
-
|
58
|
-
sig do
|
59
|
-
override.params(previous_content: String, old_source: T::Hash[Symbol, T.nilable(String)],
|
60
|
-
new_source: T::Hash[Symbol, T.nilable(String)]).returns(String)
|
61
|
-
end
|
62
|
-
def update_digest_and_tag(previous_content, old_source, new_source)
|
63
|
-
old_digest = old_source[:digest]
|
64
|
-
new_digest = new_source[:digest]
|
65
|
-
|
66
|
-
old_tag = old_source[:tag]
|
67
|
-
new_tag = new_source[:tag]
|
68
|
-
|
69
|
-
old_declaration =
|
70
|
-
if private_registry_url(old_source)
|
71
|
-
"#{private_registry_url(old_source)}/"
|
72
|
-
else
|
73
|
-
""
|
74
|
-
end
|
75
|
-
old_declaration += T.must(dependency).name
|
76
|
-
old_declaration +=
|
77
|
-
if specified_with_tag?(old_source)
|
78
|
-
":#{old_tag}"
|
79
|
-
else
|
80
|
-
""
|
81
|
-
end
|
82
|
-
old_declaration +=
|
83
|
-
if old_digest&.start_with?("sha256:")
|
84
|
-
"@#{old_digest}"
|
85
|
-
else
|
86
|
-
""
|
87
|
-
end
|
88
|
-
|
89
|
-
escaped_declaration = Regexp.escape(old_declaration)
|
90
|
-
|
91
|
-
old_declaration_regex = build_old_declaration_regex(escaped_declaration)
|
92
|
-
|
93
|
-
previous_content.gsub(old_declaration_regex) do |old_dec|
|
94
|
-
old_dec
|
95
|
-
.gsub(":#{old_tag}", ":#{new_tag}")
|
96
|
-
.gsub(old_digest.to_s, new_digest.to_s)
|
97
|
-
end
|
98
|
-
end
|
99
57
|
end
|
100
58
|
end
|
101
59
|
end
|
@@ -3,13 +3,17 @@
|
|
3
3
|
|
4
4
|
# These all need to be required so the various classes can be registered in a
|
5
5
|
# lookup table of package manager names to concrete classes.
|
6
|
+
|
7
|
+
require "dependabot/docker"
|
8
|
+
|
6
9
|
require "dependabot/docker_compose/file_fetcher"
|
7
10
|
require "dependabot/docker_compose/file_parser"
|
8
|
-
require "dependabot/docker_compose/update_checker"
|
9
11
|
require "dependabot/docker_compose/file_updater"
|
10
|
-
|
11
|
-
|
12
|
-
|
12
|
+
|
13
|
+
Dependabot::Utils.register_version_class("docker_compose", Dependabot::Docker::Version)
|
14
|
+
Dependabot::UpdateCheckers.register("docker_compose", Dependabot::Docker::UpdateChecker)
|
15
|
+
Dependabot::Utils.register_requirement_class("docker_compose", Dependabot::Docker::Requirement)
|
16
|
+
Dependabot::MetadataFinders.register("docker_compose", Dependabot::Docker::MetadataFinder)
|
13
17
|
|
14
18
|
require "dependabot/pull_request_creator/labeler"
|
15
19
|
Dependabot::PullRequestCreator::Labeler
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dependabot-docker_compose
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.299.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dependabot
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-02-
|
11
|
+
date: 2025-02-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dependabot-common
|
@@ -16,14 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.299.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.299.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dependabot-docker
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.299.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.299.0
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: debug
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -246,23 +260,13 @@ files:
|
|
246
260
|
- lib/dependabot/docker_compose/file_fetcher.rb
|
247
261
|
- lib/dependabot/docker_compose/file_parser.rb
|
248
262
|
- lib/dependabot/docker_compose/file_updater.rb
|
249
|
-
- lib/dependabot/docker_compose/metadata_finder.rb
|
250
263
|
- lib/dependabot/docker_compose/package_manager.rb
|
251
|
-
- lib/dependabot/docker_compose/requirement.rb
|
252
|
-
- lib/dependabot/docker_compose/tag.rb
|
253
|
-
- lib/dependabot/docker_compose/update_checker.rb
|
254
|
-
- lib/dependabot/docker_compose/version.rb
|
255
|
-
- lib/dependabot/shared/shared_file_fetcher.rb
|
256
|
-
- lib/dependabot/shared/shared_file_parser.rb
|
257
|
-
- lib/dependabot/shared/shared_file_updater.rb
|
258
|
-
- lib/dependabot/shared/utils/credentials_finder.rb
|
259
|
-
- lib/dependabot/shared/utils/helpers.rb
|
260
264
|
homepage: https://github.com/dependabot/dependabot-core
|
261
265
|
licenses:
|
262
266
|
- MIT
|
263
267
|
metadata:
|
264
268
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
265
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
269
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.299.0
|
266
270
|
post_install_message:
|
267
271
|
rdoc_options: []
|
268
272
|
require_paths:
|
@@ -1,39 +0,0 @@
|
|
1
|
-
# typed: strict
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require "dependabot/metadata_finders"
|
5
|
-
require "dependabot/metadata_finders/base"
|
6
|
-
require "dependabot/shared_helpers"
|
7
|
-
require "sorbet-runtime"
|
8
|
-
|
9
|
-
module Dependabot
|
10
|
-
module DockerCompose
|
11
|
-
class MetadataFinder < Dependabot::MetadataFinders::Base
|
12
|
-
extend T::Sig
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
sig { override.returns(T.nilable(Dependabot::Source)) }
|
17
|
-
def look_up_source
|
18
|
-
return if dependency.requirements.empty?
|
19
|
-
|
20
|
-
new_source = dependency.requirements.first&.fetch(:source)
|
21
|
-
return unless new_source && new_source[:registry] && new_source[:tag]
|
22
|
-
|
23
|
-
image_ref = "#{new_source[:registry]}/#{dependency.name}:#{new_source[:tag]}"
|
24
|
-
image_details_output = SharedHelpers.run_shell_command("regctl image inspect #{image_ref}")
|
25
|
-
image_details = JSON.parse(image_details_output)
|
26
|
-
image_source = image_details.dig("config", "Labels", "org.opencontainers.image.source")
|
27
|
-
return unless image_source
|
28
|
-
|
29
|
-
Dependabot::Source.from_url(image_source)
|
30
|
-
rescue StandardError => e
|
31
|
-
Dependabot.logger.warn("Error looking up Docker Compose source: #{e.message}")
|
32
|
-
nil
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
Dependabot::MetadataFinders
|
39
|
-
.register("docker_compose", Dependabot::DockerCompose::MetadataFinder)
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# typed: strict
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require "sorbet-runtime"
|
5
|
-
|
6
|
-
require "dependabot/requirement"
|
7
|
-
require "dependabot/utils"
|
8
|
-
|
9
|
-
module Dependabot
|
10
|
-
module DockerCompose
|
11
|
-
# Lifted from the bundler package manager
|
12
|
-
class Requirement < Dependabot::Requirement
|
13
|
-
extend T::Sig
|
14
|
-
|
15
|
-
# For consistency with other languages, we define a requirements array.
|
16
|
-
# Ruby doesn't have an `OR` separator for requirements, so it always
|
17
|
-
# contains a single element.
|
18
|
-
sig { override.params(requirement_string: T.nilable(String)).returns(T::Array[Requirement]) }
|
19
|
-
def self.requirements_array(requirement_string)
|
20
|
-
[new(T.must(requirement_string))]
|
21
|
-
end
|
22
|
-
|
23
|
-
sig { override.params(version: Version).returns(T::Boolean) }
|
24
|
-
def satisfied_by?(version)
|
25
|
-
super(version.release_part)
|
26
|
-
end
|
27
|
-
|
28
|
-
# Patches Gem::Requirement to make it accept requirement strings like
|
29
|
-
# "~> 4.2.5, >= 4.2.5.1" without first needing to split them.
|
30
|
-
sig { params(requirements: T.any(T.nilable(String), T::Array[T.nilable(String)])).void }
|
31
|
-
def initialize(*requirements)
|
32
|
-
requirements = requirements.flatten.flat_map do |req_string|
|
33
|
-
req_string.to_s.split(",").map(&:strip)
|
34
|
-
end
|
35
|
-
|
36
|
-
super(requirements)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
Dependabot::Utils
|
43
|
-
.register_requirement_class("docker_compose", Dependabot::DockerCompose::Requirement)
|
@@ -1,144 +0,0 @@
|
|
1
|
-
# typed: strong
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require "sorbet-runtime"
|
5
|
-
|
6
|
-
module Dependabot
|
7
|
-
module DockerCompose
|
8
|
-
class Tag
|
9
|
-
extend T::Sig
|
10
|
-
WORDS_WITH_BUILD = /(?:(?:-[a-z]+)+-[0-9]+)+/
|
11
|
-
VERSION_REGEX = /v?(?<version>[0-9]+(?:[_.][0-9]+)*(?:\.[a-z0-9]+|#{WORDS_WITH_BUILD}|-(?:kb)?[0-9]+)*)/i
|
12
|
-
VERSION_WITH_SFX = /^#{VERSION_REGEX}(?<suffix>-[a-z][a-z0-9.\-]*)?$/i
|
13
|
-
VERSION_WITH_PFX = /^(?<prefix>[a-z][a-z0-9.\-_]*-)?#{VERSION_REGEX}$/i
|
14
|
-
VERSION_WITH_PFX_AND_SFX = /^(?<prefix>[a-z\-_]+-)?#{VERSION_REGEX}(?<suffix>-[a-z\-]+)?$/i
|
15
|
-
NAME_WITH_VERSION =
|
16
|
-
/
|
17
|
-
#{VERSION_WITH_PFX}|
|
18
|
-
#{VERSION_WITH_SFX}|
|
19
|
-
#{VERSION_WITH_PFX_AND_SFX}
|
20
|
-
/x
|
21
|
-
DIGEST = /@(?<digest>[^\s]+)/
|
22
|
-
|
23
|
-
sig { returns(String) }
|
24
|
-
attr_reader :name
|
25
|
-
|
26
|
-
sig { params(name: String).void }
|
27
|
-
def initialize(name)
|
28
|
-
@name = name
|
29
|
-
end
|
30
|
-
|
31
|
-
sig { returns(String) }
|
32
|
-
def to_s
|
33
|
-
name
|
34
|
-
end
|
35
|
-
|
36
|
-
sig { returns(T::Boolean) }
|
37
|
-
def digest?
|
38
|
-
name.match?(DIGEST)
|
39
|
-
end
|
40
|
-
|
41
|
-
sig { returns(T.nilable(T::Boolean)) }
|
42
|
-
def looks_like_prerelease?
|
43
|
-
numeric_version&.match?(/[a-zA-Z]/)
|
44
|
-
end
|
45
|
-
|
46
|
-
sig { params(other: Tag).returns(T::Boolean) }
|
47
|
-
def comparable_to?(other)
|
48
|
-
return false unless comparable?
|
49
|
-
|
50
|
-
other_prefix = other.prefix
|
51
|
-
other_suffix = other.suffix
|
52
|
-
other_format = other.format
|
53
|
-
|
54
|
-
equal_prefix = prefix == other_prefix
|
55
|
-
equal_format = format == other_format
|
56
|
-
return equal_prefix && equal_format if other_format == :sha_suffixed
|
57
|
-
|
58
|
-
equal_suffix = suffix == other_suffix
|
59
|
-
equal_prefix && equal_format && equal_suffix
|
60
|
-
end
|
61
|
-
|
62
|
-
sig { returns(T::Boolean) }
|
63
|
-
def comparable?
|
64
|
-
name.match?(NAME_WITH_VERSION)
|
65
|
-
end
|
66
|
-
|
67
|
-
sig { params(other: Tag).returns(T::Boolean) }
|
68
|
-
def same_precision?(other)
|
69
|
-
other.precision == precision
|
70
|
-
end
|
71
|
-
|
72
|
-
sig { params(other: Tag).returns(T::Boolean) }
|
73
|
-
def same_but_less_precise?(other)
|
74
|
-
other.segments.zip(segments).all? do |segment, other_segment|
|
75
|
-
segment == other_segment || other_segment.nil?
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
sig { returns(T.nilable(T::Boolean)) }
|
80
|
-
def canonical?
|
81
|
-
return false unless numeric_version
|
82
|
-
return true if name == numeric_version
|
83
|
-
|
84
|
-
# .NET tags are suffixed with -sdk
|
85
|
-
return true if numeric_version && name == numeric_version.to_s + "-sdk"
|
86
|
-
|
87
|
-
numeric_version && name == "jdk-" + T.must(numeric_version)
|
88
|
-
end
|
89
|
-
|
90
|
-
sig { returns T.nilable(String) }
|
91
|
-
def prefix
|
92
|
-
name.match(NAME_WITH_VERSION)&.named_captures&.fetch("prefix")
|
93
|
-
end
|
94
|
-
|
95
|
-
sig { returns T.nilable(String) }
|
96
|
-
def suffix
|
97
|
-
name.match(NAME_WITH_VERSION)&.named_captures&.fetch("suffix")
|
98
|
-
end
|
99
|
-
|
100
|
-
sig { returns T.nilable(String) }
|
101
|
-
def version
|
102
|
-
name.match(NAME_WITH_VERSION)&.named_captures&.fetch("version")
|
103
|
-
end
|
104
|
-
|
105
|
-
sig { returns(Symbol) }
|
106
|
-
def format
|
107
|
-
return :sha_suffixed if name.match?(/(^|\-g?)[0-9a-f]{7,}$/)
|
108
|
-
return :year_month if version&.match?(/^[12]\d{3}(?:[.\-]|$)/)
|
109
|
-
return :year_month_day if version&.match?(/^[12](?:\d{5}|\d{7})(?:[.\-]|$)/)
|
110
|
-
return :build_num if version&.match?(/^\d+$/)
|
111
|
-
|
112
|
-
# As an example, "21-ea-32", "22-ea-7", and "22-ea-jdk-nanoserver-1809"
|
113
|
-
# are mapped to "<version>-ea-<build_num>", "<version>-ea-<build_num>",
|
114
|
-
# and "<version>-ea-jdk-nanoserver-<build_num>" respectively.
|
115
|
-
#
|
116
|
-
# That means only "22-ea-7" will be considered as a viable update
|
117
|
-
# candidate for "21-ea-32", since it's the only one that respects that
|
118
|
-
# format.
|
119
|
-
if version&.match?(WORDS_WITH_BUILD)
|
120
|
-
return :"<version>#{T.must(version).match(WORDS_WITH_BUILD).to_s.gsub(/-[0-9]+/, '-<build_num>')}"
|
121
|
-
end
|
122
|
-
|
123
|
-
:normal
|
124
|
-
end
|
125
|
-
|
126
|
-
sig { returns(T.nilable(String)) }
|
127
|
-
def numeric_version
|
128
|
-
return unless comparable?
|
129
|
-
|
130
|
-
version&.gsub(/kb/i, "")&.gsub(/-[a-z]+/, "")&.downcase
|
131
|
-
end
|
132
|
-
|
133
|
-
sig { returns(Integer) }
|
134
|
-
def precision
|
135
|
-
segments.length
|
136
|
-
end
|
137
|
-
|
138
|
-
sig { returns(T::Array[String]) }
|
139
|
-
def segments
|
140
|
-
T.must(numeric_version).split(/[.-]/)
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|