class Dependabot::Hex::UpdateChecker

Public Instance Methods

latest_resolvable_version() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 27
def latest_resolvable_version
  @latest_resolvable_version ||=
    if git_dependency?
      latest_resolvable_version_for_git_dependency
    else
      fetch_latest_resolvable_version(unlock_requirement: true)
    end
end
latest_resolvable_version_with_no_unlock() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 36
def latest_resolvable_version_with_no_unlock
  @latest_resolvable_version_with_no_unlock ||=
    if git_dependency?
      latest_resolvable_commit_with_unchanged_git_source
    else
      fetch_latest_resolvable_version(unlock_requirement: false)
    end
end
latest_version() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 18
def latest_version
  @latest_version ||=
    if git_dependency?
      latest_version_for_git_dependency
    else
      latest_release_from_hex_registry || latest_resolvable_version
    end
end
updated_requirements() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 45
def updated_requirements
  RequirementsUpdater.new(
    requirements: dependency.requirements,
    updated_source: updated_source,
    latest_resolvable_version: latest_resolvable_version&.to_s
  ).updated_requirements
end

Private Instance Methods

current_version() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 259
def current_version
  return unless dependency.version && version_class.correct?(dependency.version)

  version_class.new(dependency.version)
end
dependency_source_details() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 164
def dependency_source_details
  sources =
    dependency.requirements.map { |r| r.fetch(:source) }.uniq.compact

  raise "Multiple sources! #{sources.join(', ')}" if sources.count > 1

  sources.first
end
dependency_url() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 273
def dependency_url
  "https://hex.pm/api/packages/#{dependency.name}"
end
fetch_latest_resolvable_version(unlock_requirement:) click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 173
def fetch_latest_resolvable_version(unlock_requirement:)
  @latest_resolvable_version_hash ||= {}
  @latest_resolvable_version_hash[unlock_requirement] ||=
    version_resolver(unlock_requirement: unlock_requirement).
    latest_resolvable_version
end
filter_lower_versions(versions_array) click to toggle source

rubocop:enable Metrics/PerceivedComplexity

# File lib/dependabot/hex/update_checker.rb, line 233
def filter_lower_versions(versions_array)
  return versions_array unless current_version && version_class.correct?(current_version)

  versions_array.select do |version|
    version > current_version
  end
end
git_commit_checker() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 277
def git_commit_checker
  @git_commit_checker ||=
    GitCommitChecker.new(
      dependency: dependency,
      credentials: credentials
    )
end
git_dependency?() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 97
def git_dependency?
  git_commit_checker.git_dependency?
end
hex_registry_response() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 241
def hex_registry_response
  return @hex_registry_response if @hex_registry_requested

  @hex_registry_requested = true

  response = Excon.get(
    dependency_url,
    idempotent: true,
    **SharedHelpers.excon_defaults
  )

  return unless response.status == 200

  @hex_registry_response = JSON.parse(response.body)
rescue Excon::Error::Socket, Excon::Error::Timeout
  nil
end
latest_git_tag_is_resolvable?() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 119
def latest_git_tag_is_resolvable?
  return @git_tag_resolvable if @latest_git_tag_is_resolvable_checked

  @latest_git_tag_is_resolvable_checked = true

  return false if git_commit_checker.local_tag_for_latest_version.nil?

  replacement_tag = git_commit_checker.local_tag_for_latest_version

  prepared_files = FilePreparer.new(
    dependency: dependency,
    dependency_files: dependency_files,
    replacement_git_pin: replacement_tag.fetch(:tag)
  ).prepared_dependency_files

  resolver_result = VersionResolver.new(
    dependency: dependency,
    prepared_dependency_files: prepared_files,
    original_dependency_files: dependency_files,
    credentials: credentials
  ).latest_resolvable_version

  @git_tag_resolvable = !resolver_result.nil?
rescue SharedHelpers::HelperSubprocessFailed,
       Dependabot::DependencyFileNotResolvable => e
  raise e unless e.message.include?("resolution failed")

  @git_tag_resolvable = false
end
latest_git_version_sha() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 101
def latest_git_version_sha
  # If the gem isn't pinned, the latest version is just the latest
  # commit for the specified branch.
  return git_commit_checker.head_commit_for_current_branch unless git_commit_checker.pinned?

  # If the dependency is pinned to a tag that looks like a version then
  # we want to update that tag. The latest version will then be the SHA
  # of the latest tag that looks like a version.
  if git_commit_checker.pinned_ref_looks_like_version?
    latest_tag = git_commit_checker.local_tag_for_latest_version
    return latest_tag&.fetch(:commit_sha) || dependency.version
  end

  # If the dependency is pinned to a tag that doesn't look like a
  # version then there's nothing we can do.
  dependency.version
end
latest_release_from_hex_registry() click to toggle source

rubocop:disable Metrics/PerceivedComplexity

# File lib/dependabot/hex/update_checker.rb, line 209
def latest_release_from_hex_registry
  @latest_release_from_hex_registry ||=
    begin
      versions = hex_registry_response&.fetch("releases", []) || []
      versions =
        versions.
        select { |release| version_class.correct?(release["version"]) }.
        map { |release| version_class.new(release["version"]) }

      versions.reject!(&:prerelease?) unless wants_prerelease?

      filtered = versions.reject do |v|
        ignore_requirements.any? { |r| r.satisfied_by?(v) }
      end

      if @raise_on_ignored && filter_lower_versions(filtered).empty? && filter_lower_versions(versions).any?
        raise AllVersionsIgnored
      end

      filtered.max
    end
end
latest_resolvable_commit_with_unchanged_git_source() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 86
def latest_resolvable_commit_with_unchanged_git_source
  fetch_latest_resolvable_version(unlock_requirement: false)
rescue SharedHelpers::HelperSubprocessFailed,
       Dependabot::DependencyFileNotResolvable => e
  # Resolution may fail, as Elixir updates straight to the tip of the
  # branch. Just return `nil` if it does (so no update).
  return if e.message.include?("resolution failed")

  raise e
end
latest_resolvable_version_for_git_dependency() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 68
def latest_resolvable_version_for_git_dependency
  # If the gem isn't pinned, the latest version is just the latest
  # commit for the specified branch.
  return latest_resolvable_commit_with_unchanged_git_source unless git_commit_checker.pinned?

  # If the dependency is pinned to a tag that looks like a version then
  # we want to update that tag. The latest version will then be the SHA
  # of the latest tag that looks like a version.
  if git_commit_checker.pinned_ref_looks_like_version? &&
     latest_git_tag_is_resolvable?
    new_tag = git_commit_checker.local_tag_for_latest_version
    return new_tag.fetch(:commit_sha)
  end

  # If the dependency is pinned then there's nothing we can do.
  dependency.version
end
latest_version_for_git_dependency() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 64
def latest_version_for_git_dependency
  latest_git_version_sha
end
latest_version_resolvable_with_full_unlock?() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 55
def latest_version_resolvable_with_full_unlock?
  # Full unlock checks aren't implemented for Elixir (yet)
  false
end
prepared_dependency_files(unlock_requirement:, latest_allowable_version: nil) click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 198
def prepared_dependency_files(unlock_requirement:,
                              latest_allowable_version: nil)
  FilePreparer.new(
    dependency: dependency,
    dependency_files: dependency_files,
    unlock_requirement: unlock_requirement,
    latest_allowable_version: latest_allowable_version
  ).prepared_dependency_files
end
updated_dependencies_after_full_unlock() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 60
def updated_dependencies_after_full_unlock
  raise NotImplementedError
end
updated_source() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 149
def updated_source
  # Never need to update source, unless a git_dependency
  return dependency_source_details unless git_dependency?

  # Update the git tag if updating a pinned version
  if git_commit_checker.pinned_ref_looks_like_version? &&
     latest_git_tag_is_resolvable?
    new_tag = git_commit_checker.local_tag_for_latest_version
    return dependency_source_details.merge(ref: new_tag.fetch(:tag))
  end

  # Otherwise return the original source
  dependency_source_details
end
version_resolver(unlock_requirement:) click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 180
def version_resolver(unlock_requirement:)
  @version_resolver ||= {}
  @version_resolver[unlock_requirement] ||=
    begin
      prepared_dependency_files = prepared_dependency_files(
        unlock_requirement: unlock_requirement,
        latest_allowable_version: latest_release_from_hex_registry
      )

      VersionResolver.new(
        dependency: dependency,
        prepared_dependency_files: prepared_dependency_files,
        original_dependency_files: dependency_files,
        credentials: credentials
      )
    end
end
wants_prerelease?() click to toggle source
# File lib/dependabot/hex/update_checker.rb, line 265
def wants_prerelease?
  return true if current_version&.prerelease?

  dependency.requirements.any? do |req|
    req[:requirement]&.match?(/\d-[A-Za-z0-9]/)
  end
end