Skip to content

Commit

Permalink
Merge branch 'main' into markhallen/handle-uv-lock-file
Browse files Browse the repository at this point in the history
  • Loading branch information
markhallen authored Mar 6, 2025
2 parents e8ebb42 + f3b78cc commit f7f76c0
Show file tree
Hide file tree
Showing 8 changed files with 2,119 additions and 13 deletions.
2 changes: 1 addition & 1 deletion cargo/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM docker.io/library/rust:1.85.0-bookworm AS rust
FROM docker.io/library/rust:1.84.0-bookworm AS rust

FROM ghcr.io/dependabot/dependabot-updater-core

Expand Down
20 changes: 13 additions & 7 deletions common/lib/dependabot/shared_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
require "open3"
require "sorbet-runtime"
require "tmpdir"
require "securerandom"

require "dependabot/credential"
require "dependabot/simple_instrumentor"
Expand All @@ -22,7 +23,6 @@ module Dependabot
module SharedHelpers # rubocop:disable Metrics/ModuleLength
extend T::Sig

GIT_CONFIG_GLOBAL_PATH = T.let(File.expand_path(".gitconfig", Utils::BUMP_TMP_DIR_PATH), String)
USER_AGENT = T.let(
"dependabot-core/#{Dependabot::VERSION} " \
"#{Excon::USER_AGENT} ruby/#{RUBY_VERSION} " \
Expand Down Expand Up @@ -290,12 +290,15 @@ def self.with_git_configured(credentials:, &_block)
FileUtils.mkdir_p(Utils::BUMP_TMP_DIR_PATH)

previous_config = ENV.fetch("GIT_CONFIG_GLOBAL", nil)
# adding a random suffix to avoid conflicts when running in parallel
# some package managers like bundler will modify the global git config
git_config_global_path = File.expand_path("#{SecureRandom.hex(16)}.gitconfig", Utils::BUMP_TMP_DIR_PATH)
previous_terminal_prompt = ENV.fetch("GIT_TERMINAL_PROMPT", nil)

begin
ENV["GIT_CONFIG_GLOBAL"] = GIT_CONFIG_GLOBAL_PATH
ENV["GIT_CONFIG_GLOBAL"] = git_config_global_path
ENV["GIT_TERMINAL_PROMPT"] = "false"
configure_git_to_use_https_with_credentials(credentials, safe_directories)
configure_git_to_use_https_with_credentials(credentials, safe_directories, git_config_global_path)
yield
ensure
ENV["GIT_CONFIG_GLOBAL"] = previous_config
Expand All @@ -304,7 +307,7 @@ def self.with_git_configured(credentials:, &_block)
rescue Errno::ENOSPC => e
raise Dependabot::OutOfDisk, e.message
ensure
FileUtils.rm_f(GIT_CONFIG_GLOBAL_PATH)
FileUtils.rm_f(T.must(git_config_global_path))
end

# Handle SCP-style git URIs
Expand All @@ -321,9 +324,12 @@ def self.credential_helper_path
end

# rubocop:disable Metrics/PerceivedComplexity
sig { params(credentials: T::Array[Dependabot::Credential], safe_directories: T::Array[String]).void }
def self.configure_git_to_use_https_with_credentials(credentials, safe_directories)
File.open(GIT_CONFIG_GLOBAL_PATH, "w") do |file|
sig do
params(credentials: T::Array[Dependabot::Credential], safe_directories: T::Array[String],
git_config_global_path: String).void
end
def self.configure_git_to_use_https_with_credentials(credentials, safe_directories, git_config_global_path)
File.open(git_config_global_path, "w") do |file|
file << "# Generated by dependabot/dependabot-core"
end

Expand Down
10 changes: 7 additions & 3 deletions common/spec/dependabot/shared_helpers_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -599,14 +599,18 @@ def alternatives(host)
end

let(:credentials) { [] }
let(:git_config_path) { File.expand_path(".gitconfig", tmp) }
let(:git_config_path) { File.expand_path("XXXXXXXXXXXXXXXX.gitconfig", tmp) }
let(:configured_git_config) { with_git_configured { `cat #{git_config_path}` } }
let(:configured_git_credentials) { with_git_configured { `cat #{Dir.pwd}/git.store` } }

def with_git_configured(&block)
Dependabot::SharedHelpers.with_git_configured(credentials: credentials, &block)
end

before do
allow(SecureRandom).to receive(:hex).and_return("XXXXXXXXXXXXXXXX")
end

context "when the global .gitconfig has a safe directory" do
before do
Open3.capture2("git config --global --add safe.directory /home/dependabot/dependabot-core/repo")
Expand Down Expand Up @@ -749,10 +753,10 @@ def with_git_configured(&block)
context "when the host has run out of disk space" do
before do
allow(File).to receive(:open)
.with(described_class::GIT_CONFIG_GLOBAL_PATH, anything)
.with(git_config_path, anything)
.and_raise(Errno::ENOSPC)
allow(FileUtils).to receive(:rm_f)
.with(described_class::GIT_CONFIG_GLOBAL_PATH)
.with(git_config_path)
end

specify { expect { configured_git_config }.to raise_error(Dependabot::OutOfDisk) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,9 @@ def normalised_name

sig { params(json_url: String).returns(Excon::Response) }
def registry_json_response_for_dependency(json_url)
url = "#{json_url.chomp('/')}/#{@dependency.name}/json"
Dependabot::RegistryClient.get(
url: "#{json_url.chomp('/')}/#{@dependency.name}/json",
url: url,
headers: { "Accept" => APPLICATION_JSON }
)
end
Expand Down
2 changes: 2 additions & 0 deletions python/lib/dependabot/python/update_checker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ def pip_version_resolver
dependency_files: dependency_files,
credentials: credentials,
ignored_versions: ignored_versions,
update_cooldown: @update_cooldown,
raise_on_ignored: @raise_on_ignored,
security_advisories: security_advisories
)
Expand Down Expand Up @@ -255,6 +256,7 @@ def latest_version_finder
credentials: credentials,
ignored_versions: ignored_versions,
raise_on_ignored: @raise_on_ignored,
cooldown_options: @update_cooldown,
security_advisories: security_advisories
)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ module Python
class UpdateChecker
class PipVersionResolver
def initialize(dependency:, dependency_files:, credentials:,
ignored_versions:, raise_on_ignored: false,
ignored_versions:, update_cooldown: nil, raise_on_ignored: false,
security_advisories:)
@dependency = dependency
@dependency_files = dependency_files
@credentials = credentials
@ignored_versions = ignored_versions
@update_cooldown = update_cooldown
@raise_on_ignored = raise_on_ignored
@security_advisories = security_advisories
end
Expand Down Expand Up @@ -50,8 +51,10 @@ def latest_version_finder
credentials: credentials,
ignored_versions: ignored_versions,
raise_on_ignored: @raise_on_ignored,
cooldown_options: @update_cooldown,
security_advisories: security_advisories
)
@latest_version_finder
end

def python_requirement_parser
Expand Down
85 changes: 85 additions & 0 deletions python/spec/dependabot/python/update_checker_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
let(:dependency_files) { [requirements_file] }
let(:requirements_update_strategy) { nil }
let(:security_advisories) { [] }
let(:cooldown_options) { nil }
let(:raise_on_ignored) { false }
let(:ignored_versions) { [] }
let(:credentials) do
Expand All @@ -68,16 +69,27 @@
dependency_files: dependency_files,
credentials: credentials,
ignored_versions: ignored_versions,
update_cooldown: cooldown_options,
raise_on_ignored: raise_on_ignored,
security_advisories: security_advisories,
requirements_update_strategy: requirements_update_strategy
)
end
let(:pypi_response) { fixture("pypi", "pypi_simple_response.html") }
let(:pypi_url) { "https://pypi.org/simple/luigi/" }
let(:enable_cooldown_for_python) { false }

before do
stub_request(:get, pypi_url).to_return(status: 200, body: pypi_response)
allow(Dependabot::Experiments).to receive(:enabled?)
.with(:enable_file_parser_python_local)
.and_return(false)
allow(Dependabot::Experiments).to receive(:enabled?)
.with(:enable_cooldown_for_python)
.and_return(true)
allow(Dependabot::Experiments).to receive(:enabled?)
.with(:enable_shared_helpers_command_timeout)
.and_return(true)
end

it_behaves_like "an update checker"
Expand Down Expand Up @@ -154,6 +166,7 @@
dependency_files: dependency_files,
credentials: credentials,
ignored_versions: ignored_versions,
cooldown_options: cooldown_options,
raise_on_ignored: raise_on_ignored,
security_advisories: security_advisories
).and_call_original
Expand Down Expand Up @@ -514,6 +527,7 @@
dependency_files: dependency_files,
credentials: credentials,
ignored_versions: ignored_versions,
cooldown_options: cooldown_options,
raise_on_ignored: raise_on_ignored,
security_advisories: security_advisories
).and_call_original
Expand Down Expand Up @@ -844,4 +858,75 @@
it { is_expected.to be(false) }
end
end

describe "with cooldown options" do
let(:pypi_url) { "https://pypi.org/pypi/luigi/json" }
let(:pypi_response) { fixture("pypi", "pypi_response_luigi.json") }

before do
# Move `stub_request` inside `before` block
stub_request(:get, pypi_url).to_return(status: 200, body: pypi_response)

# Package Name: luigi
# Current version: 2.0.0
# Release Versions:
# ...
# 2.0.0 => Date: 2015-10-23, Yanked: false
# 2.0.1 => Date: 2015-12-05, Yanked: false
# ...
# 3.3.0 => Date: 2023-05-04, Yanked: false
# 3.4.0 => Date: 2023-10-05, Yanked: false
# 3.5.0 => Date: 2024-01-15, Yanked: false
# 3.5.1 => Date: 2024-05-20, Yanked: false
# 3.5.2 => Date: 2024-09-04, Yanked: false
# 3.6.0 => Date: 2024-12-06, Yanked: false
allow(Time).to receive(:now).and_return(Time.parse("2024-12-08"))
end

describe "#latest_resolvable_version" do
subject(:latest_resolvable_version) { checker.latest_resolvable_version }

context "with a requirement file" do
let(:dependency_files) { [requirements_file] }

context "when cooldown is not set" do
let(:cooldown_options) { nil }

it { is_expected.to eq(Gem::Version.new("3.6.0")) }
end

context "when cooldown applies to patch updates" do
let(:cooldown_options) do
Dependabot::Package::ReleaseCooldownOptions.new(patch_days: 2)
end

it { is_expected.to eq(Gem::Version.new("3.6.0")) }
end

context "when cooldown applies to minor updates" do
let(:cooldown_options) do
Dependabot::Package::ReleaseCooldownOptions.new(minor_days: 5)
end

it { is_expected.to eq(Gem::Version.new("3.6.0")) }
end

context "when cooldown applies to major updates" do
let(:cooldown_options) do
Dependabot::Package::ReleaseCooldownOptions.new(major_days: 10)
end

it { is_expected.to eq(Gem::Version.new("3.5.2")) }
end

context "when cooldown applies to all updates" do
let(:cooldown_options) do
Dependabot::Package::ReleaseCooldownOptions.new(default_days: 10)
end

it { is_expected.to eq(Gem::Version.new("3.5.2")) }
end
end
end
end
end
Loading

0 comments on commit f7f76c0

Please sign in to comment.