class Dependabot::Hex::UpdateChecker::VersionResolver
Attributes
credentials[R]
dependency[R]
original_dependency_files[R]
prepared_dependency_files[R]
Public Class Methods
new(dependency:, credentials:, original_dependency_files:, prepared_dependency_files:)
click to toggle source
# File lib/dependabot/hex/update_checker/version_resolver.rb, line 14 def initialize(dependency:, credentials:, original_dependency_files:, prepared_dependency_files:) @dependency = dependency @original_dependency_files = original_dependency_files @prepared_dependency_files = prepared_dependency_files @credentials = credentials end
Public Instance Methods
latest_resolvable_version()
click to toggle source
# File lib/dependabot/hex/update_checker/version_resolver.rb, line 22 def latest_resolvable_version @latest_resolvable_version ||= fetch_latest_resolvable_version end
Private Instance Methods
check_original_requirements_resolvable()
click to toggle source
# File lib/dependabot/hex/update_checker/version_resolver.rb, line 111 def check_original_requirements_resolvable SharedHelpers.in_a_temporary_directory do write_temporary_sanitized_dependency_files(prepared: false) FileUtils.cp( elixir_helper_check_update_path, "check_update.exs" ) SharedHelpers.with_git_configured(credentials: credentials) do run_elixir_update_checker end end true rescue SharedHelpers::HelperSubprocessFailed => e # TODO: Catch the warnings as part of the Elixir module. This happens # when elixir throws warnings from the manifest files that end up in # stdout and cause run_helper_subprocess to fail parsing the result as # JSON. return error_result(e) if includes_result?(e) raise Dependabot::DependencyFileNotResolvable, e.message end
elixir_helper_check_update_path()
click to toggle source
# File lib/dependabot/hex/update_checker/version_resolver.rb, line 170 def elixir_helper_check_update_path File.join(NativeHelpers.hex_helpers_dir, "lib/check_update.exs") end
elixir_helper_path()
click to toggle source
# File lib/dependabot/hex/update_checker/version_resolver.rb, line 166 def elixir_helper_path File.join(NativeHelpers.hex_helpers_dir, "lib/run.exs") end
error_result(error)
click to toggle source
# File lib/dependabot/hex/update_checker/version_resolver.rb, line 92 def error_result(error) return false unless includes_result?(error) result_json = error.message&.split("\n")&.last result = JSON.parse(result_json)["result"] return version_class.new(result) if version_class.correct?(result) result end
fetch_latest_resolvable_version()
click to toggle source
# File lib/dependabot/hex/update_checker/version_resolver.rb, line 31 def fetch_latest_resolvable_version latest_resolvable_version = SharedHelpers.in_a_temporary_directory do write_temporary_sanitized_dependency_files FileUtils.cp( elixir_helper_check_update_path, "check_update.exs" ) SharedHelpers.with_git_configured(credentials: credentials) do run_elixir_update_checker end end return if latest_resolvable_version.nil? return latest_resolvable_version if latest_resolvable_version.match?(/^[0-9a-f]{40}$/) version_class.new(latest_resolvable_version) rescue SharedHelpers::HelperSubprocessFailed => e handle_hex_errors(e) end
handle_hex_errors(error)
click to toggle source
# File lib/dependabot/hex/update_checker/version_resolver.rb, line 65 def handle_hex_errors(error) if error.message.include?("No authenticated organization found") org = error.message.match(/found for ([a-z_]+)\./).captures.first raise Dependabot::PrivateSourceAuthenticationFailure, org end if error.message.include?("Failed to fetch record for") org_match = error.message.match(%r{for 'hexpm:([a-z_]+)/}) org = org_match&.captures&.first raise Dependabot::PrivateSourceAuthenticationFailure, org if org end # TODO: Catch the warnings as part of the Elixir module. This happens # when elixir throws warnings from the manifest files that end up in # stdout and cause run_helper_subprocess to fail parsing the result as # JSON. return error_result(error) if includes_result?(error) # Ignore dependencies which don't resolve due to mis-matching # environment specifications. # TODO: Update the environment specifications instead return if error.message.include?("Dependencies have diverged") check_original_requirements_resolvable raise error end
includes_result?(error)
click to toggle source
# File lib/dependabot/hex/update_checker/version_resolver.rb, line 102 def includes_result?(error) result = error.message&.split("\n")&.last return false unless result JSON.parse(error.message&.split("\n")&.last).key?("result") rescue JSON::ParserError false end
mix_env()
click to toggle source
# File lib/dependabot/hex/update_checker/version_resolver.rb, line 157 def mix_env { "MIX_EXS" => File.join(NativeHelpers.hex_helpers_dir, "mix.exs"), "MIX_LOCK" => File.join(NativeHelpers.hex_helpers_dir, "mix.lock"), "MIX_DEPS" => File.join(NativeHelpers.hex_helpers_dir, "deps"), "MIX_QUIET" => "1" } end
organization_credentials()
click to toggle source
# File lib/dependabot/hex/update_checker/version_resolver.rb, line 174 def organization_credentials credentials. select { |cred| cred["type"] == "hex_organization" }. flat_map { |cred| [cred["organization"], cred.fetch("token", "")] } end
run_elixir_update_checker()
click to toggle source
# File lib/dependabot/hex/update_checker/version_resolver.rb, line 53 def run_elixir_update_checker SharedHelpers.run_helper_subprocess( env: mix_env, command: "mix run #{elixir_helper_path}", function: "get_latest_resolvable_version", args: [Dir.pwd, dependency.name, organization_credentials], stderr_to_stdout: true ) end
sanitize_mixfile(content)
click to toggle source
# File lib/dependabot/hex/update_checker/version_resolver.rb, line 147 def sanitize_mixfile(content) Hex::FileUpdater::MixfileSanitizer.new( mixfile_content: content ).sanitized_content end
version_class()
click to toggle source
# File lib/dependabot/hex/update_checker/version_resolver.rb, line 153 def version_class Hex::Version end
write_temporary_sanitized_dependency_files(prepared: true)
click to toggle source
# File lib/dependabot/hex/update_checker/version_resolver.rb, line 135 def write_temporary_sanitized_dependency_files(prepared: true) files = if prepared then prepared_dependency_files else original_dependency_files end files.each do |file| path = file.name FileUtils.mkdir_p(Pathname.new(path).dirname) File.write(path, sanitize_mixfile(file.content)) end end