Class: Dependabot::Docker::Tag
- Inherits:
-
Object
- Object
- Dependabot::Docker::Tag
- Extended by:
- T::Sig
- Defined in:
- lib/dependabot/docker/tag.rb
Constant Summary collapse
- WORDS_WITH_BUILD =
/(?:(?:-[a-z]+)+-[0-9]+)+/- VERSION_REGEX =
/v?(?<version>[0-9]+(?:[_.][0-9]+)*(?:\.[a-z0-9]+|#{WORDS_WITH_BUILD}|-(?:kb)?[0-9]+)*)/i- VERSION_WITH_SFX =
/^(?<operator>[~^<>=]*)#{VERSION_REGEX}(?<suffix>-[a-z][a-z0-9.\-]*)?$/i- VERSION_WITH_PFX =
/^(?<prefix>[a-z][a-z0-9.\-_]*-)?#{VERSION_REGEX}$/i- VERSION_WITH_PFX_AND_SFX =
/^(?<prefix>[a-z\-_]+-)?#{VERSION_REGEX}(?<suffix>-[a-z\-]+)?$/i- NAME_WITH_VERSION =
/ #{VERSION_WITH_PFX}| #{VERSION_WITH_SFX}| #{VERSION_WITH_PFX_AND_SFX} /x
Instance Attribute Summary collapse
-
#name ⇒ Object
readonly
Returns the value of attribute name.
Instance Method Summary collapse
- #canonical? ⇒ Boolean
- #comparable? ⇒ Boolean
- #comparable_formats(other_format, other_prefix, other_suffix) ⇒ Object
- #comparable_to?(other) ⇒ Boolean
- #dated_version? ⇒ Boolean
- #digest? ⇒ Boolean
- #format ⇒ Object
-
#initialize(name) ⇒ Tag
constructor
A new instance of Tag.
- #looks_like_prerelease? ⇒ Boolean
- #numeric_version ⇒ Object
- #precision ⇒ Object
- #prefix ⇒ Object
- #same_but_less_precise?(other) ⇒ Boolean
- #same_precision?(other) ⇒ Boolean
- #segments ⇒ Object
- #suffix ⇒ Object
- #to_s ⇒ Object
- #version ⇒ Object
Constructor Details
#initialize(name) ⇒ Tag
Returns a new instance of Tag.
28 29 30 |
# File 'lib/dependabot/docker/tag.rb', line 28 def initialize(name) @name = name end |
Instance Attribute Details
#name ⇒ Object (readonly)
Returns the value of attribute name.
25 26 27 |
# File 'lib/dependabot/docker/tag.rb', line 25 def name @name end |
Instance Method Details
#canonical? ⇒ Boolean
131 132 133 134 135 136 137 138 139 |
# File 'lib/dependabot/docker/tag.rb', line 131 def canonical? return false unless numeric_version return true if name == numeric_version # .NET tags are suffixed with -sdk return true if numeric_version && name == numeric_version.to_s + "-sdk" numeric_version && name == "jdk-" + T.must(numeric_version) end |
#comparable? ⇒ Boolean
114 115 116 |
# File 'lib/dependabot/docker/tag.rb', line 114 def comparable? name.match?(NAME_WITH_VERSION) end |
#comparable_formats(other_format, other_prefix, other_suffix) ⇒ Object
83 84 85 86 87 88 |
# File 'lib/dependabot/docker/tag.rb', line 83 def comparable_formats(other_format, other_prefix, other_suffix) return false unless prefix.nil? && suffix.nil? && other_prefix.nil? && other_suffix.nil? formats = %i(year_month year_month_day) (format == :build_num && formats.include?(other_format)) || (formats.include?(format) && other_format == :build_num) # rubocop:disable Layout/LineLength end |
#comparable_to?(other) ⇒ Boolean
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/dependabot/docker/tag.rb', line 91 def comparable_to?(other) return false unless comparable? other_prefix = other.prefix other_suffix = other.suffix other_format = other.format equal_prefix = prefix == other_prefix equal_format = format == other_format comparable_format = comparable_formats(other.format, other.prefix, other.suffix) return equal_prefix && equal_format if other_format == :sha_suffixed # When timestamp validation is enabled, dated and non-dated versions are # not comparable — prevents updating from 4.8-windowsservercore-ltsc2022 # to 4.8-20250909-windowsservercore-ltsc2022 and vice versa return false if Dependabot::Experiments.enabled?(:docker_created_timestamp_validation) && dated_version? != other.dated_version? equal_suffix = suffix == other_suffix (equal_prefix && equal_format && equal_suffix) || comparable_format end |
#dated_version? ⇒ Boolean
199 200 201 202 203 204 |
# File 'lib/dependabot/docker/tag.rb', line 199 def dated_version? return false unless version # Match 8-digit date-like segments (YYYYMMDD) within the version part !!T.must(version).match?(/-\d{8}(?:\b|$)/) end |
#digest? ⇒ Boolean
38 39 40 |
# File 'lib/dependabot/docker/tag.rb', line 38 def digest? name.match?(FileParser::DIGEST) end |
#format ⇒ Object
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/dependabot/docker/tag.rb', line 157 def format return :sha_suffixed if name.match?(/(^|\-g?)[0-9a-f]{7,}$/) return :year_month if version&.match?(/^[12]\d{3}(?:[.\-]|$)/) return :year_month_day if version&.match?(/^[12](?:\d{5}|\d{7})(?:[.\-]|$)/) return :build_num if version&.match?(/^\d+$/) # As an example, "21-ea-32", "22-ea-7", and "22-ea-jdk-nanoserver-1809" # are mapped to "<version>-ea-<build_num>", "<version>-ea-<build_num>", # and "<version>-ea-jdk-nanoserver-<build_num>" respectively. # # That means only "22-ea-7" will be considered as a viable update # candidate for "21-ea-32", since it's the only one that respects that # format. if version&.match?(WORDS_WITH_BUILD) return :"<version>#{T.must(version).match(WORDS_WITH_BUILD).to_s.gsub(/-[0-9]+/, '-<build_num>')}" end :normal end |
#looks_like_prerelease? ⇒ Boolean
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/dependabot/docker/tag.rb', line 43 def looks_like_prerelease? return false unless comparable? # Don't treat SHA-suffixed tags as prereleases (e.g., v3.10.0-169-gfe040d3) return false if format == :sha_suffixed # Check for common prerelease patterns in the tag name # The version regex splits things like "1.0.0-alpha" into version="1.0.0" and suffix="-alpha" # So we need to check the full name or the combination of version and suffix prerelease_patterns = [ /alpha/i, # matches: alpha, ALPHA /beta/i, # matches: beta, BETA /rc\d*/i, # matches: rc, RC, RC1, rc2, etc. /dev/i, # matches: dev, DEV /preview/i, # matches: preview, PREVIEW /\bpre\b/i, # matches: pre, PRE as a whole word /nightly/i, # matches: nightly, NIGHTLY /snapshot/i, # matches: snapshot, SNAPSHOT /canary/i, # matches: canary, CANARY /unstable/i, # matches: unstable, UNSTABLE /\d+[a-z]\d*/, # matches: 3.15.0a2, 1.0b1 (version followed by letter and optional number) /[a-z]+\d+$/, # matches: alpha1, beta2, rc3 at the end /\.post\d+/i, # matches: .post1, .POST2 (Python PEP 440 post-release) /\.dev\d+/i # matches: .dev0, .DEV1 (Python PEP 440 development release) ] # Check both the version part and the suffix part version_matches = version && prerelease_patterns.any? { |pattern| T.must(version).match?(pattern) } suffix_matches = suffix && prerelease_patterns.any? { |pattern| T.must(suffix).match?(pattern) } !!(version_matches || suffix_matches) end |
#numeric_version ⇒ Object
178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/dependabot/docker/tag.rb', line 178 def numeric_version return unless comparable? result = version&.gsub(/kb/i, "")&.gsub(/-[a-z]+/, "")&.downcase # When timestamp validation is enabled, strip date components from the # version so they don't inflate semver comparison. "4.8-20250909" should # compare as "4.8", not "4.8.20250909". The date is metadata — actual # recency is determined by config blob timestamps. if Dependabot::Experiments.enabled?(:docker_created_timestamp_validation) result = result&.gsub(/-\d{8}(?:\b|$)/, "") end result end |
#precision ⇒ Object
207 208 209 |
# File 'lib/dependabot/docker/tag.rb', line 207 def precision segments.length end |
#prefix ⇒ Object
142 143 144 |
# File 'lib/dependabot/docker/tag.rb', line 142 def prefix name.match(NAME_WITH_VERSION)&.named_captures&.fetch("prefix") end |
#same_but_less_precise?(other) ⇒ Boolean
124 125 126 127 128 |
# File 'lib/dependabot/docker/tag.rb', line 124 def same_but_less_precise?(other) other.segments.zip(segments).all? do |segment, other_segment| segment == other_segment || other_segment.nil? end end |
#same_precision?(other) ⇒ Boolean
119 120 121 |
# File 'lib/dependabot/docker/tag.rb', line 119 def same_precision?(other) other.precision == precision end |
#segments ⇒ Object
212 213 214 |
# File 'lib/dependabot/docker/tag.rb', line 212 def segments T.must(numeric_version).split(/[.-]/) end |
#suffix ⇒ Object
147 148 149 |
# File 'lib/dependabot/docker/tag.rb', line 147 def suffix name.match(NAME_WITH_VERSION)&.named_captures&.fetch("suffix") end |
#to_s ⇒ Object
33 34 35 |
# File 'lib/dependabot/docker/tag.rb', line 33 def to_s name end |
#version ⇒ Object
152 153 154 |
# File 'lib/dependabot/docker/tag.rb', line 152 def version name.match(NAME_WITH_VERSION)&.named_captures&.fetch("version") end |