Class: Dependabot::GitCommitChecker

Inherits:
Object
  • Object
show all
Extended by:
T::Sig
Includes:
GitCooldownDateResolver
Defined in:
lib/dependabot/git_commit_checker.rb,
lib/dependabot/git_commit_checker/source_details.rb

Overview

rubocop:disable Metrics/ClassLength

Defined Under Namespace

Classes: SourceDetails

Constant Summary collapse

VERSION_REGEX =
/
  (?<version>
    (?<=^v)[0-9]+(?:\-[a-z0-9]+)?
    |
    [12][0-9]{3}(?:0[1-9]|1[0-2])(?:0[1-9]|[12][0-9]|3[01])
    |
    [0-9]+\.[0-9]+(?:\.[a-z0-9\-]+)*
  )$
/ix
VERSION_TAG_MATCH_PATTERN =

String pattern for matching version tags with optional prefixes (e.g., "v1.2.3" matches "1.2.3")

"(?:[^0-9\\.]|\\A)%s\\z"

Instance Method Summary collapse

Methods included from GitCooldownDateResolver

#cached_github_releases, #github_release_published_at, #normalize_tag_name, #resolve_candidate_date, #tag_creation_date

Constructor Details

#initialize(dependency:, credentials:, ignored_versions: [], raise_on_ignored: false, consider_version_branches_pinned: false, dependency_source_details: nil) ⇒ GitCommitChecker

Returns a new instance of GitCommitChecker.



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/dependabot/git_commit_checker.rb', line 55

def initialize(
  dependency:,
  credentials:,
  ignored_versions: [],
  raise_on_ignored: false,
  consider_version_branches_pinned: false,
  dependency_source_details: nil
)
  @dependency = dependency
  @credentials = credentials
  @ignored_versions = ignored_versions
  @raise_on_ignored = raise_on_ignored
  @consider_version_branches_pinned = consider_version_branches_pinned
  @dependency_source_details = T.let(
    dependency_source_details && SourceDetails.from_hash(dependency_source_details),
    T.nilable(SourceDetails)
  )
end

Instance Method Details

#all_version_tagsObject



322
323
324
# File 'lib/dependabot/git_commit_checker.rb', line 322

def all_version_tags
  allowed_versions(local_tags, filter_by_prefix: false)
end

#allowed_version_refsObject



233
234
235
# File 'lib/dependabot/git_commit_checker.rb', line 233

def allowed_version_refs
  allowed_versions(local_refs)
end

#allowed_version_tagsObject



228
229
230
# File 'lib/dependabot/git_commit_checker.rb', line 228

def allowed_version_tags
  allowed_versions(local_tags)
end

#allowed_version_tags_with_release_datesObject



330
331
332
333
334
335
336
337
338
# File 'lib/dependabot/git_commit_checker.rb', line 330

def allowed_version_tags_with_release_dates
  allowed_version_tags.map do |tag|
    Dependabot::Package::PackageRelease.new(
      version: T.cast(version_from_tag(tag), Dependabot::Version),
      tag: tag.name,
      released_at: release_date_for_tag_name(tag.name)
    )
  end
end

#branch_or_ref_in_release?(version) ⇒ Boolean

Returns:

  • (Boolean)


153
154
155
# File 'lib/dependabot/git_commit_checker.rb', line 153

def branch_or_ref_in_release?(version)
  pinned_ref_in_release?(version) || branch_behind_release?(version)
end

#cooldown_credentialsObject



346
347
348
# File 'lib/dependabot/git_commit_checker.rb', line 346

def cooldown_credentials
  credentials
end

#cooldown_source_urlObject



341
342
343
# File 'lib/dependabot/git_commit_checker.rb', line 341

def cooldown_source_url
  dependency_source_details&.url
end

#current_versionObject



238
239
240
241
242
# File 'lib/dependabot/git_commit_checker.rb', line 238

def current_version
  return unless dependency.version && version_tag?(T.must(dependency.version))

  version_from_ref(T.must(dependency.version))
end

#dependency_source_detailsObject



289
290
291
292
293
294
# File 'lib/dependabot/git_commit_checker.rb', line 289

def dependency_source_details
  @dependency_source_details ||= begin
    details = dependency.source_details(allowed_types: ["git"])
    SourceDetails.from_hash(details) if details
  end
end

#filter_lower_versions(tags) ⇒ Object



245
246
247
248
249
250
251
252
253
254
255
# File 'lib/dependabot/git_commit_checker.rb', line 245

def filter_lower_versions(tags)
  return tags unless current_version

  versions = tags.map do |t|
    version_from_tag(t)
  end

  versions.select do |version|
    version > current_version
  end
end

#git_dependency?Boolean

Returns:

  • (Boolean)


75
76
77
# File 'lib/dependabot/git_commit_checker.rb', line 75

def git_dependency?
  dependency_source_details&.type == "git"
end

#git_repo_reachable?Boolean

Returns:

  • (Boolean)


281
282
283
284
285
286
# File 'lib/dependabot/git_commit_checker.rb', line 281

def git_repo_reachable?
  local_upload_pack
  true
rescue Dependabot::GitDependenciesNotReachable
  false
end

#head_commit_for_current_branchObject



158
159
160
161
162
163
164
165
# File 'lib/dependabot/git_commit_checker.rb', line 158

def head_commit_for_current_branch
  ref = ref_or_branch || "HEAD"

  sha = head_commit_for_local_branch(ref)
  return sha if pinned? || sha

  raise Dependabot::GitDependencyReferenceNotFound, dependency.name
end

#head_commit_for_local_branch(name) ⇒ Object



168
169
170
# File 'lib/dependabot/git_commit_checker.rb', line 168

def head_commit_for_local_branch(name)
  .head_commit_for_ref(name)
end

#head_commit_for_pinned_refObject



117
118
119
# File 'lib/dependabot/git_commit_checker.rb', line 117

def head_commit_for_pinned_ref
  .head_commit_for_ref_sha(T.must(ref))
end

#local_ref_for_latest_version_lower_precisionObject



180
181
182
183
184
# File 'lib/dependabot/git_commit_checker.rb', line 180

def local_ref_for_latest_version_lower_precision
  allowed_refs = local_tag_for_pinned_sha ? allowed_version_tags : allowed_version_refs

  max_local_tag_for_lower_precision(allowed_refs)
end

#local_ref_for_latest_version_matching_existing_precisionObject



173
174
175
176
177
# File 'lib/dependabot/git_commit_checker.rb', line 173

def local_ref_for_latest_version_matching_existing_precision
  allowed_refs = local_tag_for_pinned_sha ? allowed_version_tags : allowed_version_refs

  max_local_tag_for_current_precision(allowed_refs)
end

#local_tag_for_latest_version(cooldown_options = nil) ⇒ Object



194
195
196
197
198
199
# File 'lib/dependabot/git_commit_checker.rb', line 194

def local_tag_for_latest_version(cooldown_options = nil)
  filtered_tags = apply_cooldown(allowed_version_tags, cooldown_options)
  return nil if filtered_tags.nil?

  max_local_tag(filtered_tags)
end

#local_tag_for_pinned_shaObject



264
265
266
267
268
269
270
271
# File 'lib/dependabot/git_commit_checker.rb', line 264

def local_tag_for_pinned_sha
  return unless pinned_ref_looks_like_commit_sha?

  @local_tag_for_pinned_sha = T.let(
    most_specific_version_tag_for_sha(ref),
    T.nilable(String)
  )
end

#local_tag_for_pinned_version_ref(cooldown_options = nil) ⇒ Object



211
212
213
214
215
# File 'lib/dependabot/git_commit_checker.rb', line 211

def local_tag_for_pinned_version_ref(cooldown_options = nil)
  return nil unless pinned_ref_looks_like_version?

  local_tag_for_latest_version(cooldown_options)
end

#local_tags_for_allowed_versionsObject



223
224
225
# File 'lib/dependabot/git_commit_checker.rb', line 223

def local_tags_for_allowed_versions
  allowed_version_tags.filter_map { |t| to_local_tag(t) }
end

#local_tags_for_allowed_versions_matching_existing_precisionObject



218
219
220
# File 'lib/dependabot/git_commit_checker.rb', line 218

def local_tags_for_allowed_versions_matching_existing_precision
  select_matching_existing_precision(allowed_version_tags).filter_map { |t| to_local_tag(t) }
end

#max_local_tag(tags) ⇒ Object



315
316
317
318
319
# File 'lib/dependabot/git_commit_checker.rb', line 315

def max_local_tag(tags)
  max_version_tag = tags.max_by { |t| version_from_tag(t) }

  to_local_tag(max_version_tag)
end

#most_specific_tag_equivalent_to_pinned_refObject



258
259
260
261
# File 'lib/dependabot/git_commit_checker.rb', line 258

def most_specific_tag_equivalent_to_pinned_ref
  commit_sha = head_commit_for_local_branch(T.must(ref))
  most_specific_version_tag_for_sha(commit_sha)
end

#most_specific_version_tag_for_sha(commit_sha) ⇒ Object



302
303
304
305
306
307
# File 'lib/dependabot/git_commit_checker.rb', line 302

def most_specific_version_tag_for_sha(commit_sha)
  tags = local_tags_matching_sha(commit_sha)
  return if tags.empty?

  tags[-1]&.name
end

#most_specific_version_tags_for_sha(commit_sha) ⇒ Object



310
311
312
# File 'lib/dependabot/git_commit_checker.rb', line 310

def most_specific_version_tags_for_sha(commit_sha)
  local_tags_matching_sha(commit_sha).map(&:name)
end

#pinned?Boolean

Returns:

  • (Boolean)


81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/dependabot/git_commit_checker.rb', line 81

def pinned?
  raise "Not a git dependency!" unless git_dependency?

  branch = dependency_source_details&.branch

  return false if ref.nil?
  return false if branch == ref
  return true if branch
  return true if dependency.version&.start_with?(T.must(ref))
  return true if ref_matches_tag?

  # Assume we're pinned unless the specified `ref` is actually a branch
  return true unless local_upload_pack&.match?(%r{ refs/heads/#{ref}$})

  # TODO: Research whether considering branches that look like versions pinned makes sense for all ecosystems
  @consider_version_branches_pinned && version_tag?(T.must(ref))
end

#pinned_ref_looks_like_commit_sha?Boolean

Returns:

  • (Boolean)


108
109
110
111
112
113
114
# File 'lib/dependabot/git_commit_checker.rb', line 108

def pinned_ref_looks_like_commit_sha?
  return false unless ref && ref_looks_like_commit_sha?(T.must(ref))

  return false unless pinned?

  .head_commit_for_ref(T.must(ref)).nil?
end

#pinned_ref_looks_like_version?Boolean

Returns:

  • (Boolean)


101
102
103
104
105
# File 'lib/dependabot/git_commit_checker.rb', line 101

def pinned_ref_looks_like_version?
  return false unless pinned?

  version_tag?(T.must(ref))
end

#ref_details(ref) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
# File 'lib/dependabot/git_commit_checker.rb', line 130

def ref_details(ref)
  T.must(
    T.let(
      GitMetadataFetcher.new(
        url: T.must(source_details&.url),
        credentials: credentials
      ).ref_details_for_pinned_ref(ref),
      T.nilable(Excon::Response)
    )
  )
end

#ref_details_for_pinned_refObject



143
144
145
# File 'lib/dependabot/git_commit_checker.rb', line 143

def ref_details_for_pinned_ref
  ref_details(ref_pinned)
end

#ref_looks_like_commit_sha?(ref) ⇒ Boolean

Returns:

  • (Boolean)


148
149
150
# File 'lib/dependabot/git_commit_checker.rb', line 148

def ref_looks_like_commit_sha?(ref)
  ref.match?(/^[0-9a-f]{6,40}$/)
end

#refs_for_tag_with_detailObject



297
298
299
# File 'lib/dependabot/git_commit_checker.rb', line 297

def refs_for_tag_with_detail
  .refs_for_tag_with_detail
end

#tagsObject



122
123
124
125
126
127
# File 'lib/dependabot/git_commit_checker.rb', line 122

def tags
  GitMetadataFetcher.new(
    url: T.must(source_details&.url),
    credentials: credentials
  ).tags
end

#version_for_pinned_shaObject



274
275
276
277
278
# File 'lib/dependabot/git_commit_checker.rb', line 274

def version_for_pinned_sha
  return unless local_tag_for_pinned_sha && version_class.correct?(local_tag_for_pinned_sha)

  version_class.new(local_tag_for_pinned_sha)
end