Class: Dependabot::NpmAndYarn::UpdateChecker

Inherits:
UpdateCheckers::Base
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/dependabot/npm_and_yarn/update_checker.rb,
lib/dependabot/npm_and_yarn/update_checker/library_detector.rb,
lib/dependabot/npm_and_yarn/update_checker/version_resolver.rb,
lib/dependabot/npm_and_yarn/update_checker/requirements_updater.rb,
lib/dependabot/npm_and_yarn/update_checker/latest_version_finder.rb,
lib/dependabot/npm_and_yarn/update_checker/vulnerability_auditor.rb,
lib/dependabot/npm_and_yarn/update_checker/dependency_files_builder.rb,
lib/dependabot/npm_and_yarn/update_checker/subdependency_version_resolver.rb,
lib/dependabot/npm_and_yarn/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
FixUpdate =
Dependabot::UpdateCheckers::VulnerabilityAudit::FixUpdate

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



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

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
  apply_npmrc_min_release_age
end

Instance Method Details

#conflicting_dependenciesObject



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

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



164
165
166
# File 'lib/dependabot/npm_and_yarn/update_checker.rb', line 164

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

#latest_resolvable_versionObject



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

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



150
151
152
153
154
155
156
157
158
# File 'lib/dependabot/npm_and_yarn/update_checker.rb', line 150

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



91
92
93
94
95
96
97
98
# File 'lib/dependabot/npm_and_yarn/update_checker.rb', line 91

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



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

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



121
122
123
124
125
126
# File 'lib/dependabot/npm_and_yarn/update_checker.rb', line 121

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)


192
193
194
# File 'lib/dependabot/npm_and_yarn/update_checker.rb', line 192

def requirements_unlocked_or_can_be?
  !requirements_update_strategy&.lockfile_only?
end

#requirements_update_strategyObject



197
198
199
200
201
202
203
# File 'lib/dependabot/npm_and_yarn/update_checker.rb', line 197

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)


75
76
77
78
79
80
81
82
83
# File 'lib/dependabot/npm_and_yarn/update_checker.rb', line 75

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



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

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)


86
87
88
# File 'lib/dependabot/npm_and_yarn/update_checker.rb', line 86

def vulnerable?
  super || vulnerable_versions.any?
end