Class: Dependabot::Bun::UpdateChecker

Inherits:
UpdateCheckers::Base
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/dependabot/bun/update_checker.rb,
lib/dependabot/bun/update_checker/library_detector.rb,
lib/dependabot/bun/update_checker/version_resolver.rb,
lib/dependabot/bun/update_checker/requirements_updater.rb,
lib/dependabot/bun/update_checker/latest_version_finder.rb,
lib/dependabot/bun/update_checker/vulnerability_auditor.rb,
lib/dependabot/bun/update_checker/dependency_files_builder.rb,
lib/dependabot/bun/update_checker/subdependency_version_resolver.rb,
lib/dependabot/bun/update_checker/conflicting_dependency_resolver.rb

Overview

rubocop:disable Metrics/ClassLength

Defined Under Namespace

Classes: ConflictingDependencyResolver, DependencyFilesBuilder, LibraryDetector, PackageLatestVersionFinder, RequirementsUpdater, SubdependencyVersionResolver, VersionResolver, VulnerabilityAuditor

Constant Summary collapse

Audit =
Dependabot::UpdateCheckers::VulnerabilityAudit

Instance Method Summary collapse

Constructor Details

#initialize(dependency:, dependency_files:, credentials:, repo_contents_path: nil, ignored_versions: [], raise_on_ignored: false, security_advisories: [], requirements_update_strategy: nil, dependency_group: nil, update_cooldown: nil, options: {}) ⇒ UpdateChecker

rubocop:disable Metrics/AbcSize



41
42
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
# File 'lib/dependabot/bun/update_checker.rb', line 41

def initialize( # rubocop:disable Metrics/AbcSize
  dependency:,
  dependency_files:,
  credentials:,
  repo_contents_path: nil,
  ignored_versions: [],
  raise_on_ignored: false,
  security_advisories: [],
  requirements_update_strategy: nil,
  dependency_group: nil,
  update_cooldown: nil,
  options: {}
)
  @latest_version = T.let(nil, T.nilable(T.any(String, Gem::Version)))
  @latest_resolvable_version = T.let(nil, T.nilable(T.any(String, Dependabot::Version)))
  @updated_requirements = T.let(nil, T.nilable(T::Array[Dependabot::DependencyRequirement]))
  @vulnerability_audit = T.let(nil, T.nilable(Audit))
  @vulnerable_versions = T.let(nil, T.nilable(T::Array[T.any(String, Gem::Version)]))

  @latest_version_for_git_dependency = T.let(nil, T.nilable(T.any(String, Gem::Version)))
  @latest_released_version = T.let(nil, T.nilable(Gem::Version))
  @latest_version_details = T.let(nil, T.nilable(T::Hash[Symbol, T.untyped]))
  @latest_version_finder = T.let(nil, T.nilable(PackageLatestVersionFinder))
  @version_resolver = T.let(nil, T.nilable(VersionResolver))
  @subdependency_version_resolver = T.let(nil, T.nilable(SubdependencyVersionResolver))
  @library = T.let(nil, T.nilable(T::Boolean))
  @package_json = T.let(nil, T.nilable(Dependabot::DependencyFile))
  @git_commit_checker = T.let(nil, T.nilable(Dependabot::GitCommitChecker))
  super
end

Instance Method Details

#conflicting_dependenciesObject



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/dependabot/bun/update_checker.rb', line 204

def conflicting_dependencies
  conflicts = ConflictingDependencyResolver.new(
    dependency_files: dependency_files,
    credentials: credentials
  ).conflicting_dependencies(
    dependency: dependency,
    target_version: lowest_security_fix_version
  )
  return conflicts unless vulnerability_audit_performed?

  audit = vulnerability_audit
  vulnerable = !audit.fix_available && audit.explanation ? [audit.to_h] : []

  conflicts + vulnerable
end

#latest_resolvable_previous_version(updated_version) ⇒ Object



162
163
164
# File 'lib/dependabot/bun/update_checker.rb', line 162

def latest_resolvable_previous_version(updated_version)
  version_resolver.latest_resolvable_previous_version(updated_version)
end

#latest_resolvable_versionObject



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/dependabot/bun/update_checker.rb', line 99

def latest_resolvable_version
  return unless latest_version

  @latest_resolvable_version ||=
    if dependency.top_level?
      T.cast(
        version_resolver.latest_resolvable_version,
        T.nilable(T.any(String, Dependabot::Version))
      )
    else
      # If the dependency is indirect its version is constrained  by the
      # requirements placed on it by dependencies lower down the tree
      T.cast(
        subdependency_version_resolver.latest_resolvable_version,
        T.nilable(T.any(String, Dependabot::Version))
      )
    end
end

#latest_resolvable_version_with_no_unlockObject



148
149
150
151
152
153
154
155
156
# File 'lib/dependabot/bun/update_checker.rb', line 148

def latest_resolvable_version_with_no_unlock
  unless dependency.top_level?
    return T.cast(latest_resolvable_version, T.nilable(T.any(String, Dependabot::Version)))
  end

  return latest_resolvable_version_with_no_unlock_for_git_dependency if git_dependency?

  latest_version_finder.latest_version_with_no_unlock
end

#latest_versionObject



89
90
91
92
93
94
95
96
# File 'lib/dependabot/bun/update_checker.rb', line 89

def latest_version
  @latest_version ||=
    if git_dependency?
      latest_version_for_git_dependency
    else
      latest_version_details&.fetch(:version)
    end
end

#lowest_resolvable_security_fix_versionObject



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/dependabot/bun/update_checker.rb', line 127

def lowest_resolvable_security_fix_version
  raise "Dependency not vulnerable!" unless vulnerable?

  # NOTE: Currently, we don't resolve transitive/sub-dependencies as
  # npm/yarn don't provide any control over updating to a specific
  # sub-dependency version.

  # Return nil for vulnerable transitive dependencies if there are conflicting dependencies.
  # This helps catch errors in such cases.
  return nil if !dependency.top_level? && conflicting_dependencies.any?

  # For transitive dependencies without conflicts, return the latest resolvable transitive
  # security fix version that does not require unlocking other dependencies.
  return latest_resolvable_transitive_security_fix_version_with_no_unlock unless dependency.top_level?

  # For top-level dependencies, return the lowest security fix version.
  # TODO: Consider checking resolvability here in the future.
  lowest_security_fix_version
end

#lowest_security_fix_versionObject



119
120
121
122
123
124
# File 'lib/dependabot/bun/update_checker.rb', line 119

def lowest_security_fix_version
  # This will require a full unlock to update multiple top level ancestors.
  return if vulnerability_audit.fix_available && vulnerability_audit.top_level_ancestors.count > 1

  latest_version_finder.lowest_security_fix_version
end

#requirements_unlocked_or_can_be?Boolean

Returns:

  • (Boolean)


190
191
192
# File 'lib/dependabot/bun/update_checker.rb', line 190

def requirements_unlocked_or_can_be?
  !requirements_update_strategy&.lockfile_only?
end

#requirements_update_strategyObject



195
196
197
198
199
200
201
# File 'lib/dependabot/bun/update_checker.rb', line 195

def requirements_update_strategy
  # If passed in as an option (in the base class) honour that option
  return @requirements_update_strategy if @requirements_update_strategy

  # Otherwise, widen ranges for libraries and bump versions for apps
  library? ? RequirementsUpdateStrategy::WidenRanges : RequirementsUpdateStrategy::BumpVersions
end

#up_to_date?Boolean

Returns:

  • (Boolean)


73
74
75
76
77
78
79
80
81
# File 'lib/dependabot/bun/update_checker.rb', line 73

def up_to_date?
  return false if security_update? &&
                  dependency.version &&
                  version_class.correct?(dependency.version) &&
                  vulnerable_versions.any? &&
                  !vulnerable_versions.include?(current_version)

  super
end

#updated_requirementsObject



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/dependabot/bun/update_checker.rb', line 167

def updated_requirements
  resolvable_version =
    if preferred_resolvable_version.is_a?(version_class)
      preferred_resolvable_version.to_s
    elsif preferred_resolvable_version.nil?
      nil
    else
      # If the preferred_resolvable_version came back as anything other
      # than a version class or `nil` it must be because this is a git
      # dependency, for which we don't check resolvability.
      latest_version_details&.fetch(:version, nil)&.to_s
    end

  @updated_requirements ||=
    RequirementsUpdater.new(
      requirements: dependency.requirements,
      updated_source: updated_source,
      latest_resolvable_version: resolvable_version,
      update_strategy: T.must(requirements_update_strategy)
    ).updated_requirements
end

#vulnerable?Boolean

Returns:

  • (Boolean)


84
85
86
# File 'lib/dependabot/bun/update_checker.rb', line 84

def vulnerable?
  super || vulnerable_versions.any?
end