dependabot-helm 0.323.0 → 0.324.1
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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 109e220f0d5461102ca48999b9c0c8e8829fa81cd4fbb3e98f013ee36bd0014d
|
|
4
|
+
data.tar.gz: 16e970e8fd14f1563898e9ade684a155820287ffe37e3e069ee95c768205f26b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8900634a48b88074240e35b088f6d9613edbd1a1e928725ea7d936a23f355d329a09374c35ecbb0fa5f406f70d6786aef120c3b446421c69cfeaca4d333cac75
|
|
7
|
+
data.tar.gz: 1e41b94ab1cc9272fbe025601dddc66fbc35e575bfe6dc6775cacab1bac737c834d1a39d1e9462d8267308339a82153faecf7cae4880f8ad76d0975213ae6ffd
|
|
@@ -52,36 +52,6 @@ module Dependabot
|
|
|
52
52
|
)
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
sig { params(username: String, password: String, repository_url: String).returns(String) }
|
|
56
|
-
def self.registry_login(username, password, repository_url)
|
|
57
|
-
Dependabot.logger.info("Logging into Helm registry \"#{repository_url}\"")
|
|
58
|
-
|
|
59
|
-
Dependabot::SharedHelpers.run_shell_command(
|
|
60
|
-
"helm registry login --username #{username} --password #{password} #{repository_url}",
|
|
61
|
-
fingerprint: "helm registry login --username <username> --password <password> <repository_url>"
|
|
62
|
-
)
|
|
63
|
-
rescue StandardError => e
|
|
64
|
-
Dependabot.logger.error(
|
|
65
|
-
"Failed to authenticate for #{repository_url}: #{e.message}"
|
|
66
|
-
)
|
|
67
|
-
raise
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
sig { params(username: String, password: String, repository_url: String).returns(String) }
|
|
71
|
-
def self.oci_registry_login(username, password, repository_url)
|
|
72
|
-
Dependabot.logger.info("Logging into OCI registry \"#{repository_url}\"")
|
|
73
|
-
|
|
74
|
-
Dependabot::SharedHelpers.run_shell_command(
|
|
75
|
-
"oras login --username #{username} --password #{password} #{repository_url}",
|
|
76
|
-
fingerprint: "oras login --username <username> --password <password> <repository_url>"
|
|
77
|
-
)
|
|
78
|
-
rescue StandardError => e
|
|
79
|
-
Dependabot.logger.error(
|
|
80
|
-
"Failed to authenticate for #{repository_url}: #{e.message}"
|
|
81
|
-
)
|
|
82
|
-
raise
|
|
83
|
-
end
|
|
84
|
-
|
|
85
55
|
sig { params(name: String).returns(String) }
|
|
86
56
|
def self.fetch_oci_tags(name)
|
|
87
57
|
Dependabot.logger.info("Searching OCI tags for: #{name}")
|
|
@@ -91,6 +61,14 @@ module Dependabot
|
|
|
91
61
|
fingerprint: "oras repo tags <name>"
|
|
92
62
|
).strip
|
|
93
63
|
end
|
|
64
|
+
|
|
65
|
+
sig { params(repo_url: String, tag: String).returns(String) }
|
|
66
|
+
def self.fetch_tags_with_release_date_using_oci(repo_url, tag)
|
|
67
|
+
Dependabot::SharedHelpers.run_shell_command(
|
|
68
|
+
"oras manifest fetch #{repo_url}:#{tag}",
|
|
69
|
+
fingerprint: "oras manifest fetch <repo_url>:<tag>"
|
|
70
|
+
).strip
|
|
71
|
+
end
|
|
94
72
|
end
|
|
95
73
|
end
|
|
96
74
|
end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "json"
|
|
5
|
+
require "time"
|
|
6
|
+
require "cgi"
|
|
7
|
+
require "excon"
|
|
8
|
+
require "sorbet-runtime"
|
|
9
|
+
require "dependabot/helm"
|
|
10
|
+
require "dependabot/helm/helpers"
|
|
11
|
+
|
|
12
|
+
module Dependabot
|
|
13
|
+
module Helm
|
|
14
|
+
module Package
|
|
15
|
+
class PackageDetailsFetcher
|
|
16
|
+
extend T::Sig
|
|
17
|
+
# https://api.github.com/repos/prometheus-community/helm-charts/releases
|
|
18
|
+
RELEASES_URL_GIT = "https://api.github.com/repos/"
|
|
19
|
+
HELM_CHART_RELEASE = "/helm-charts/releases"
|
|
20
|
+
HELM_CHART_INDEX_URL = "https://repo.broadcom.com/bitnami-files/index.yaml"
|
|
21
|
+
|
|
22
|
+
sig do
|
|
23
|
+
params(
|
|
24
|
+
dependency: Dependency,
|
|
25
|
+
credentials: T::Array[Dependabot::Credential]
|
|
26
|
+
).void
|
|
27
|
+
end
|
|
28
|
+
def initialize(dependency:, credentials:)
|
|
29
|
+
@dependency = dependency
|
|
30
|
+
@credentials = credentials
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
|
34
|
+
attr_reader :credentials
|
|
35
|
+
|
|
36
|
+
sig { returns(Dependabot::Dependency) }
|
|
37
|
+
attr_reader :dependency
|
|
38
|
+
|
|
39
|
+
sig { params(repo_name: String).returns(T::Array[GitTagWithDetail]) }
|
|
40
|
+
def fetch_tag_and_release_date_from_chart(repo_name)
|
|
41
|
+
return [] if repo_name.empty?
|
|
42
|
+
|
|
43
|
+
url = RELEASES_URL_GIT + repo_name + HELM_CHART_RELEASE
|
|
44
|
+
Dependabot.logger.info("Fetching graph release details from URL: #{url}")
|
|
45
|
+
|
|
46
|
+
begin
|
|
47
|
+
response = Excon.get(url, headers: { "Accept" => "application/vnd.github.v3+json" })
|
|
48
|
+
rescue Excon::Error => e
|
|
49
|
+
Dependabot.logger.error("Failed to fetch releases from #{url}: #{e.message} ")
|
|
50
|
+
return []
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
Dependabot.logger.error("Failed call details: #{response.body}") unless response.status == 200
|
|
54
|
+
return [] if response.status != 200
|
|
55
|
+
|
|
56
|
+
parse_github_response(response)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
sig { params(response: Excon::Response).returns(T::Array[GitTagWithDetail]) }
|
|
60
|
+
def parse_github_response(response)
|
|
61
|
+
releases = JSON.parse(response.body)
|
|
62
|
+
result_lines = releases.map do |release|
|
|
63
|
+
GitTagWithDetail.new(
|
|
64
|
+
tag: release["tag_name"],
|
|
65
|
+
release_date: release["published_at"]
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
result_lines.sort_by(&:tag).reverse
|
|
69
|
+
rescue JSON::ParserError => e
|
|
70
|
+
Dependabot.logger.error("Failed to parse JSON response: #{e.message} response body #{response.body}")
|
|
71
|
+
[]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
sig { params(index_url: T.nilable(String), chart_name: String).returns(T::Array[GitTagWithDetail]) }
|
|
75
|
+
def fetch_tag_and_release_date_helm_chart_index(index_url, chart_name)
|
|
76
|
+
Dependabot.logger.info("Fetching fetch_tag_and_release_date_helm_chart_index:: #{index_url}")
|
|
77
|
+
index_url = HELM_CHART_INDEX_URL if index_url.nil? || index_url.empty?
|
|
78
|
+
result_lines = T.let([], T::Array[GitTagWithDetail])
|
|
79
|
+
begin
|
|
80
|
+
response = Excon.get(
|
|
81
|
+
index_url,
|
|
82
|
+
idempotent: true,
|
|
83
|
+
middlewares: Excon.defaults[:middlewares] + [Excon::Middleware::RedirectFollower]
|
|
84
|
+
)
|
|
85
|
+
rescue Excon::Error => e
|
|
86
|
+
Dependabot.logger.error("Error fetching Helm index from #{index_url}: #{e.message}")
|
|
87
|
+
return result_lines
|
|
88
|
+
end
|
|
89
|
+
Dependabot.logger.info("Received response from #{index_url} with status #{response.status}")
|
|
90
|
+
begin
|
|
91
|
+
parsed_result = YAML.safe_load(response.body)
|
|
92
|
+
rescue Psych::SyntaxError => e
|
|
93
|
+
Dependabot.logger.error("Error parsing Helm index: #{e.message}")
|
|
94
|
+
return result_lines
|
|
95
|
+
end
|
|
96
|
+
return result_lines unless parsed_result && parsed_result["entries"] && parsed_result["entries"][chart_name]
|
|
97
|
+
|
|
98
|
+
parsed_result["entries"][chart_name].map do |release|
|
|
99
|
+
result_lines << GitTagWithDetail.new(
|
|
100
|
+
tag: release["version"], # Extract the version field
|
|
101
|
+
release_date: release["created"] # Extract the created field
|
|
102
|
+
)
|
|
103
|
+
end
|
|
104
|
+
result_lines
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "dependabot/helm/package/package_details_fetcher"
|
|
5
|
+
require "sorbet-runtime"
|
|
6
|
+
require "dependabot/git_commit_checker"
|
|
7
|
+
require "dependabot/helm/version"
|
|
8
|
+
|
|
9
|
+
module Dependabot
|
|
10
|
+
module Helm
|
|
11
|
+
class LatestVersionResolver
|
|
12
|
+
extend T::Sig
|
|
13
|
+
|
|
14
|
+
DAY_IN_SECONDS = T.let(24 * 60 * 60, Integer)
|
|
15
|
+
|
|
16
|
+
sig do
|
|
17
|
+
params(
|
|
18
|
+
dependency: Dependabot::Dependency,
|
|
19
|
+
credentials: T::Array[Dependabot::Credential],
|
|
20
|
+
cooldown_options: T.nilable(Dependabot::Package::ReleaseCooldownOptions)
|
|
21
|
+
).void
|
|
22
|
+
end
|
|
23
|
+
def initialize(dependency:, credentials:, cooldown_options:)
|
|
24
|
+
@dependency = dependency
|
|
25
|
+
@credentials = credentials
|
|
26
|
+
@cooldown_options = cooldown_options
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
sig { returns(Dependabot::Dependency) }
|
|
30
|
+
attr_reader :dependency
|
|
31
|
+
|
|
32
|
+
# To filter versions in cooldown period based on version tags from registry call
|
|
33
|
+
sig do
|
|
34
|
+
params(tags: T::Array[String], tags_with_release_date: T::Array[GitTagWithDetail])
|
|
35
|
+
.returns(T::Array[String])
|
|
36
|
+
end
|
|
37
|
+
def filter_versions_in_cooldown_period_using_oci(tags, tags_with_release_date)
|
|
38
|
+
select_tags_which_in_cooldown_using_oci(tags_with_release_date)&.each do |tag_name|
|
|
39
|
+
# Iterate through versions and filter out those matching the tag_name
|
|
40
|
+
tags.reject! do |version|
|
|
41
|
+
version == tag_name
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
tags
|
|
45
|
+
rescue StandardError => e
|
|
46
|
+
Dependabot.logger.error("Error filter_versions_in_cooldown_period_for_oci:: #{e.message}")
|
|
47
|
+
tags
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
sig do
|
|
51
|
+
params(
|
|
52
|
+
versions: T::Array[T::Hash[String, T.untyped]],
|
|
53
|
+
repo_name: T.nilable(String),
|
|
54
|
+
chart_name: T.nilable(String)
|
|
55
|
+
)
|
|
56
|
+
.returns(T::Array[T::Hash[String, T.untyped]])
|
|
57
|
+
end
|
|
58
|
+
def fetch_tag_and_release_date_helm_chart(versions, repo_name, chart_name)
|
|
59
|
+
Dependabot.logger.info("Filtering versions in cooldown period from chart: #{repo_name}")
|
|
60
|
+
# Using index URL to fetch tags in cooldown period"
|
|
61
|
+
tags = select_tags_which_in_cooldown_from_chart_index("", T.must(chart_name))
|
|
62
|
+
# If no tags in result then check from github api.
|
|
63
|
+
tags = select_tags_which_in_cooldown_from_chart(T.must(repo_name)) if tags.nil? || tags.empty?
|
|
64
|
+
|
|
65
|
+
return versions if tags.nil? || tags.empty?
|
|
66
|
+
|
|
67
|
+
versions.reject! do |release|
|
|
68
|
+
tags.any?(release["version"])
|
|
69
|
+
end
|
|
70
|
+
versions
|
|
71
|
+
rescue StandardError => e
|
|
72
|
+
Dependabot.logger.error("Error fetch_tag_and_release_date_helm_chart(versions): #{e.message}")
|
|
73
|
+
versions
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
sig { params(repo_name: String).returns(T.nilable(T::Array[String])) }
|
|
77
|
+
def select_tags_which_in_cooldown_from_chart(repo_name)
|
|
78
|
+
version_tags_in_cooldown_from_chart = T.let([], T::Array[String])
|
|
79
|
+
|
|
80
|
+
begin
|
|
81
|
+
package_details_fetcher.fetch_tag_and_release_date_from_chart(repo_name).each do |git_tag_with_detail|
|
|
82
|
+
if check_if_version_in_cooldown_period?(T.must(git_tag_with_detail.release_date))
|
|
83
|
+
version_tags_in_cooldown_from_chart << git_tag_with_detail.tag
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
version_tags_in_cooldown_from_chart
|
|
87
|
+
rescue StandardError => e
|
|
88
|
+
Dependabot.logger.error("Error checking if version is in cooldown: #{e.message}")
|
|
89
|
+
version_tags_in_cooldown_from_chart
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
sig { params(index_url: String, versions: T::Array[String], chart_name: String).returns(T::Array[String]) }
|
|
94
|
+
def fetch_tag_and_release_date_helm_chart_index(index_url, versions, chart_name)
|
|
95
|
+
Dependabot.logger.info("Filtering versions in cooldown period from chart: #{index_url}")
|
|
96
|
+
return versions if select_tags_which_in_cooldown_from_chart_index(index_url, chart_name).nil?
|
|
97
|
+
|
|
98
|
+
select_tags_which_in_cooldown_from_chart_index(index_url, chart_name)&.each do |tag_name|
|
|
99
|
+
# Iterate through versions and filter out those matching the tag_name
|
|
100
|
+
versions.reject! do |version|
|
|
101
|
+
version == tag_name
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
Dependabot.logger.info("Allowed version tags after filtering versions in cooldown:
|
|
105
|
+
#{versions.map(&:to_s).join(', ')}")
|
|
106
|
+
versions
|
|
107
|
+
rescue StandardError => e
|
|
108
|
+
Dependabot.logger.error("Error fetch_tag_and_release_date_helm_chart_index : #{e.message}")
|
|
109
|
+
versions
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
sig { params(index_url: String, chart_name: String).returns(T.nilable(T::Array[String])) }
|
|
113
|
+
def select_tags_which_in_cooldown_from_chart_index(index_url, chart_name)
|
|
114
|
+
fetch_tag_and_release_date_helm_chart_index = T.let([], T::Array[String])
|
|
115
|
+
|
|
116
|
+
begin
|
|
117
|
+
package_details_fetcher.fetch_tag_and_release_date_helm_chart_index(index_url, chart_name).each do |git_tag|
|
|
118
|
+
if check_if_version_in_cooldown_period?(T.must(git_tag.release_date))
|
|
119
|
+
fetch_tag_and_release_date_helm_chart_index << git_tag.tag
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
fetch_tag_and_release_date_helm_chart_index
|
|
123
|
+
rescue StandardError => e
|
|
124
|
+
Dependabot.logger.error("Error checking if version is in cooldown: #{e.message}")
|
|
125
|
+
fetch_tag_and_release_date_helm_chart_index
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
sig { params(release_date: String).returns(T::Boolean) }
|
|
130
|
+
def check_if_version_in_cooldown_period?(release_date)
|
|
131
|
+
return false unless release_date.length.positive?
|
|
132
|
+
|
|
133
|
+
cooldown = @cooldown_options
|
|
134
|
+
return false unless cooldown
|
|
135
|
+
|
|
136
|
+
return false if cooldown.nil?
|
|
137
|
+
|
|
138
|
+
# Calculate the number of seconds passed since the release
|
|
139
|
+
passed_seconds = Time.now.to_i - release_date_to_seconds(release_date)
|
|
140
|
+
# Check if the release is within the cooldown period
|
|
141
|
+
passed_seconds < cooldown.default_days * DAY_IN_SECONDS
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
sig { params(release_date: String).returns(Integer) }
|
|
145
|
+
def release_date_to_seconds(release_date)
|
|
146
|
+
Time.parse(release_date).to_i
|
|
147
|
+
rescue ArgumentError => e
|
|
148
|
+
Dependabot.logger.error("Invalid release date format: #{release_date} and error: #{e.message}")
|
|
149
|
+
0 # Default to 360 days in seconds if parsing fails, so that it will not be in cooldown
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
sig { params(tags_with_release_date: T::Array[GitTagWithDetail]).returns(T.nilable(T::Array[String])) }
|
|
153
|
+
def select_tags_which_in_cooldown_using_oci(tags_with_release_date)
|
|
154
|
+
fetch_tag_and_release_date_helm_using_oci = T.let([], T::Array[String])
|
|
155
|
+
|
|
156
|
+
begin
|
|
157
|
+
tags_with_release_date.each do |git_tag_with_detail|
|
|
158
|
+
if check_if_version_in_cooldown_period?(T.must(git_tag_with_detail.release_date))
|
|
159
|
+
fetch_tag_and_release_date_helm_using_oci << git_tag_with_detail.tag
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
fetch_tag_and_release_date_helm_using_oci
|
|
163
|
+
rescue StandardError => e
|
|
164
|
+
Dependabot.logger.error("Error checking if version is in cooldown: #{e.message}")
|
|
165
|
+
fetch_tag_and_release_date_helm_using_oci
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
sig { returns(Package::PackageDetailsFetcher) }
|
|
170
|
+
def package_details_fetcher
|
|
171
|
+
@package_details_fetcher ||= T.let(
|
|
172
|
+
Package::PackageDetailsFetcher.new(
|
|
173
|
+
dependency: dependency,
|
|
174
|
+
credentials: credentials
|
|
175
|
+
), T.nilable(Package::PackageDetailsFetcher)
|
|
176
|
+
)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
sig { returns(T::Boolean) }
|
|
180
|
+
def cooldown_enabled?
|
|
181
|
+
Dependabot::Experiments.enabled?(:enable_cooldown_for_helm)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
|
185
|
+
attr_reader :credentials
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
@@ -19,6 +19,8 @@ module Dependabot
|
|
|
19
19
|
class UpdateChecker < Dependabot::UpdateCheckers::Base
|
|
20
20
|
extend T::Sig
|
|
21
21
|
|
|
22
|
+
require_relative "update_checker/latest_version_resolver"
|
|
23
|
+
|
|
22
24
|
sig { override.returns(T.nilable(T.any(String, Gem::Version))) }
|
|
23
25
|
def latest_version
|
|
24
26
|
@latest_version ||= T.let(fetch_latest_version, T.nilable(T.any(String, Gem::Version)))
|
|
@@ -67,6 +69,10 @@ module Dependabot
|
|
|
67
69
|
valid_releases = filter_valid_releases(releases)
|
|
68
70
|
return nil if valid_releases.empty?
|
|
69
71
|
|
|
72
|
+
if cooldown_enabled?
|
|
73
|
+
valid_releases = latest_version_resolver
|
|
74
|
+
.fetch_tag_and_release_date_helm_chart(valid_releases, repo_name, chart_name)
|
|
75
|
+
end
|
|
70
76
|
highest_release = valid_releases.max_by { |release| version_class.new(release["version"]) }
|
|
71
77
|
Dependabot.logger.info(
|
|
72
78
|
"Found latest version #{T.must(highest_release)['version']} for #{chart_name} using helm search"
|
|
@@ -87,6 +93,14 @@ module Dependabot
|
|
|
87
93
|
Dependabot.logger.info("Found #{all_versions.length} versions for #{chart_name} in index.yaml")
|
|
88
94
|
|
|
89
95
|
valid_versions = filter_valid_versions(all_versions)
|
|
96
|
+
if cooldown_enabled?
|
|
97
|
+
# Filter out versions that are in cooldown period
|
|
98
|
+
valid_versions = latest_version_resolver.fetch_tag_and_release_date_helm_chart_index(
|
|
99
|
+
index_url,
|
|
100
|
+
valid_versions,
|
|
101
|
+
chart_name
|
|
102
|
+
)
|
|
103
|
+
end
|
|
90
104
|
Dependabot.logger.info("After filtering, found #{valid_versions.length} valid versions for #{chart_name}")
|
|
91
105
|
|
|
92
106
|
return nil if valid_versions.empty?
|
|
@@ -153,7 +167,6 @@ module Dependabot
|
|
|
153
167
|
Dependabot.logger.info("Fetching releases for Helm chart: #{chart_name}")
|
|
154
168
|
|
|
155
169
|
if repo_name && repo_url
|
|
156
|
-
authenticate_registry_source(repo_url)
|
|
157
170
|
begin
|
|
158
171
|
Helpers.add_repo(repo_name, repo_url)
|
|
159
172
|
Helpers.update_repo
|
|
@@ -178,39 +191,12 @@ module Dependabot
|
|
|
178
191
|
end
|
|
179
192
|
end
|
|
180
193
|
|
|
181
|
-
sig { params(repo_url: T.nilable(String)).returns(T.nilable(String)) }
|
|
182
|
-
def authenticate_registry_source(repo_url)
|
|
183
|
-
return unless repo_url
|
|
184
|
-
|
|
185
|
-
repo_creds = Shared::Utils::CredentialsFinder.new(@credentials, private_repository_type: "helm_registry")
|
|
186
|
-
.credentials_for_registry(repo_url)
|
|
187
|
-
return unless repo_creds
|
|
188
|
-
|
|
189
|
-
Helpers.registry_login(T.must(repo_creds["username"]), T.must(repo_creds["password"]), repo_url)
|
|
190
|
-
rescue StandardError
|
|
191
|
-
raise PrivateSourceAuthenticationFailure, repo_url
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
sig { params(repo_url: T.nilable(String)).returns(T.nilable(String)) }
|
|
195
|
-
def authenticate_oci_registry_source(repo_url)
|
|
196
|
-
return unless repo_url
|
|
197
|
-
|
|
198
|
-
repo_creds = Shared::Utils::CredentialsFinder.new(@credentials, private_repository_type: "helm_registry")
|
|
199
|
-
.credentials_for_registry(repo_url)
|
|
200
|
-
return unless repo_creds
|
|
201
|
-
|
|
202
|
-
Helpers.oci_registry_login(T.must(repo_creds["username"]), T.must(repo_creds["password"]), repo_url)
|
|
203
|
-
rescue StandardError
|
|
204
|
-
raise PrivateSourceAuthenticationFailure, repo_url
|
|
205
|
-
end
|
|
206
|
-
|
|
207
194
|
sig { returns(T.nilable(Gem::Version)) }
|
|
208
195
|
def fetch_latest_chart_version
|
|
209
196
|
chart_name = dependency.name
|
|
210
197
|
source = dependency.requirements.first&.dig(:source)
|
|
211
198
|
repo_url = source&.dig(:registry)
|
|
212
199
|
repo_name = extract_repo_name(repo_url)
|
|
213
|
-
|
|
214
200
|
releases = fetch_releases_with_helm_cli(chart_name, repo_name, repo_url)
|
|
215
201
|
return releases if releases
|
|
216
202
|
|
|
@@ -226,6 +212,16 @@ module Dependabot
|
|
|
226
212
|
return nil unless tags && !tags.empty?
|
|
227
213
|
|
|
228
214
|
valid_tags = filter_valid_versions(tags)
|
|
215
|
+
if cooldown_enabled?
|
|
216
|
+
# Filter out versions that are in cooldown period
|
|
217
|
+
repo_url = repo_url.gsub("oci://", "")
|
|
218
|
+
repo_url = repo_url + "/" + chart_name
|
|
219
|
+
tags_with_release_date = fetch_tags_with_release_date_using_oci(valid_tags, repo_url)
|
|
220
|
+
valid_tags = latest_version_resolver.filter_versions_in_cooldown_period_using_oci(
|
|
221
|
+
valid_tags,
|
|
222
|
+
tags_with_release_date
|
|
223
|
+
)
|
|
224
|
+
end
|
|
229
225
|
return nil if valid_tags.empty?
|
|
230
226
|
|
|
231
227
|
highest_tag = valid_tags.map { |v| version_class.new(v) }.max
|
|
@@ -237,7 +233,6 @@ module Dependabot
|
|
|
237
233
|
def fetch_oci_tags(chart_name, repo_url)
|
|
238
234
|
Dependabot.logger.info("Fetching OCI tags for #{repo_url}")
|
|
239
235
|
oci_registry = repo_url.gsub("oci://", "")
|
|
240
|
-
authenticate_oci_registry_source(repo_url)
|
|
241
236
|
|
|
242
237
|
release_tags = Helpers.fetch_oci_tags("#{oci_registry}/#{chart_name}").split("\n")
|
|
243
238
|
release_tags.map { |tag| tag.tr("_", "+") }
|
|
@@ -295,14 +290,26 @@ module Dependabot
|
|
|
295
290
|
|
|
296
291
|
Dependabot.logger.info("Delegating to Docker UpdateChecker for image: #{docker_dependency.name}")
|
|
297
292
|
|
|
298
|
-
docker_checker =
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
293
|
+
docker_checker = if cooldown_enabled?
|
|
294
|
+
Dependabot::UpdateCheckers.for_package_manager("docker").new(
|
|
295
|
+
dependency: docker_dependency,
|
|
296
|
+
dependency_files: dependency_files,
|
|
297
|
+
credentials: credentials,
|
|
298
|
+
ignored_versions: ignored_versions,
|
|
299
|
+
security_advisories: security_advisories,
|
|
300
|
+
raise_on_ignored: raise_on_ignored,
|
|
301
|
+
update_cooldown: update_cooldown
|
|
302
|
+
)
|
|
303
|
+
else
|
|
304
|
+
Dependabot::UpdateCheckers.for_package_manager("docker").new(
|
|
305
|
+
dependency: docker_dependency,
|
|
306
|
+
dependency_files: dependency_files,
|
|
307
|
+
credentials: credentials,
|
|
308
|
+
ignored_versions: ignored_versions,
|
|
309
|
+
security_advisories: security_advisories,
|
|
310
|
+
raise_on_ignored: raise_on_ignored
|
|
311
|
+
)
|
|
312
|
+
end
|
|
306
313
|
|
|
307
314
|
latest_version = docker_checker.latest_version
|
|
308
315
|
|
|
@@ -313,6 +320,36 @@ module Dependabot
|
|
|
313
320
|
version_class.new(latest_version)
|
|
314
321
|
end
|
|
315
322
|
|
|
323
|
+
sig { params(tags: T::Array[String], repo_url: String).returns(T::Array[GitTagWithDetail]) }
|
|
324
|
+
def fetch_tags_with_release_date_using_oci(tags, repo_url)
|
|
325
|
+
git_tag_with_release_date = T.let([], T::Array[GitTagWithDetail])
|
|
326
|
+
return git_tag_with_release_date if tags.empty?
|
|
327
|
+
|
|
328
|
+
tags = tags.sort.reverse.take(150) # Limit to 150 tags for performance
|
|
329
|
+
tags.each do |tag|
|
|
330
|
+
# Since the oras registry uses "_" instead of "+", this is a workaround
|
|
331
|
+
# to ensure the tag is correctly formatted for the OCI registry.
|
|
332
|
+
# This is necessary because some tags may contain "+" which is not valid in OCI tags.
|
|
333
|
+
|
|
334
|
+
temp_tag = tag.tr("+", "_")
|
|
335
|
+
response = Helpers.fetch_tags_with_release_date_using_oci(repo_url, temp_tag)
|
|
336
|
+
|
|
337
|
+
begin
|
|
338
|
+
parsed_response = JSON.parse(response)
|
|
339
|
+
rescue JSON::ParserError => e
|
|
340
|
+
Dependabot.logger.error("Failed to parse JSON response for tag #{tag}: #{e.message}")
|
|
341
|
+
next
|
|
342
|
+
end
|
|
343
|
+
git_tag_with_release_date << GitTagWithDetail.new(
|
|
344
|
+
tag: tag,
|
|
345
|
+
release_date: parsed_response.dig("annotations", "org.opencontainers.image.created")
|
|
346
|
+
)
|
|
347
|
+
rescue StandardError => e
|
|
348
|
+
Dependabot.logger.error("Error in fetching details for tag #{tag}: #{e.message}")
|
|
349
|
+
end
|
|
350
|
+
git_tag_with_release_date
|
|
351
|
+
end
|
|
352
|
+
|
|
316
353
|
sig { returns(Dependabot::Dependency) }
|
|
317
354
|
def build_docker_dependency
|
|
318
355
|
source = T.must(dependency.requirements.first)[:source]
|
|
@@ -344,8 +381,27 @@ module Dependabot
|
|
|
344
381
|
package_manager: "helm"
|
|
345
382
|
)
|
|
346
383
|
end
|
|
384
|
+
|
|
385
|
+
sig { returns(T::Boolean) }
|
|
386
|
+
def cooldown_enabled?
|
|
387
|
+
# This is a simple check to see if user has put cooldown days.
|
|
388
|
+
# If not set, then we aassume user does not want cooldown.
|
|
389
|
+
# Since Helm does not support Semver versioning, So option left
|
|
390
|
+
# for the user is to set cooldown default days.
|
|
391
|
+
return false if update_cooldown.nil?
|
|
392
|
+
|
|
393
|
+
T.must(update_cooldown&.default_days).positive?
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
sig { returns(LatestVersionResolver) }
|
|
397
|
+
def latest_version_resolver
|
|
398
|
+
LatestVersionResolver.new(
|
|
399
|
+
dependency: dependency,
|
|
400
|
+
credentials: credentials,
|
|
401
|
+
cooldown_options: update_cooldown
|
|
402
|
+
)
|
|
403
|
+
end
|
|
347
404
|
end
|
|
348
405
|
end
|
|
349
406
|
end
|
|
350
|
-
|
|
351
407
|
Dependabot::UpdateCheckers.register("helm", Dependabot::Helm::UpdateChecker)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dependabot-helm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.324.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dependabot
|
|
@@ -15,28 +15,28 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - '='
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.
|
|
18
|
+
version: 0.324.1
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - '='
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 0.
|
|
25
|
+
version: 0.324.1
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: dependabot-docker
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
30
|
- - '='
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 0.
|
|
32
|
+
version: 0.324.1
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - '='
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: 0.
|
|
39
|
+
version: 0.324.1
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: debug
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -263,15 +263,17 @@ files:
|
|
|
263
263
|
- lib/dependabot/helm/file_updater/image_updater.rb
|
|
264
264
|
- lib/dependabot/helm/file_updater/lock_file_generator.rb
|
|
265
265
|
- lib/dependabot/helm/helpers.rb
|
|
266
|
+
- lib/dependabot/helm/package/package_details_fetcher.rb
|
|
266
267
|
- lib/dependabot/helm/package_manager.rb
|
|
267
268
|
- lib/dependabot/helm/update_checker.rb
|
|
269
|
+
- lib/dependabot/helm/update_checker/latest_version_resolver.rb
|
|
268
270
|
- lib/dependabot/helm/version.rb
|
|
269
271
|
homepage: https://github.com/dependabot/dependabot-core
|
|
270
272
|
licenses:
|
|
271
273
|
- MIT
|
|
272
274
|
metadata:
|
|
273
275
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
|
274
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
|
276
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.324.1
|
|
275
277
|
rdoc_options: []
|
|
276
278
|
require_paths:
|
|
277
279
|
- lib
|