Module: SharedAudits Private

Defined in:
utils/shared_audits.rb

Overview

This module is part of a private API. This module may only be used in the Homebrew/brew repository. Third parties should avoid using this module if possible, as it may be removed or changed without warning.

Auditing functions for rules common to both casks and formulae.

Constant Summary collapse

URL_TYPE_HOMEPAGE =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

"homepage URL"
SELF_SUBMISSION_THRESHOLD_MULTIPLIER =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

3
GITHUB_NOTABILITY_THRESHOLDS =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

T.let({ forks: 30, watchers: 30, stars: 75 }.freeze, T::Hash[Symbol, Integer])
GITLAB_NOTABILITY_THRESHOLDS =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

T.let({ forks: 30, stars: 75 }.freeze, T::Hash[Symbol, Integer])
BITBUCKET_NOTABILITY_THRESHOLDS =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

T.let({ forks: 30, watchers: 75 }.freeze, T::Hash[Symbol, Integer])
FORGEJO_NOTABILITY_THRESHOLDS =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

T.let({ forks: 30, watchers: 30, stars: 75 }.freeze, T::Hash[Symbol, Integer])
NEW_DOMAIN_THRESHOLD_DAYS =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

30
GIT_FORGE_DOMAINS =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

%w[
  bitbucket.org
  codeberg.org
  github.com
  github.io
  gitlab.com
  gitlab.io
  sr.ht
].freeze
WHOIS_TIMEOUT_SECONDS =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

5
WHOIS_CREATION_DATE_REGEX =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

/^\s*(?:creation\s+date|created(?:\s+on)?|registered(?:\s+on)?|
registration\s+(?:date|time))\s*:\s*(\S+)/ix
RDAP_BOOTSTRAP_URL =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

RDAP is the IETF successor to WHOIS: ICANN requires every gTLD registry to serve it and IANA's bootstrap file lists the server for each TLD (gTLD or ccTLD) that does.

"https://data.iana.org/rdap/dns.json"
RDAP_TIMEOUT_SECONDS =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

10
RdapServices =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

T.type_alias { T::Array[[T::Array[String], T::Array[String]]] }

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.rdap_services=(value) ⇒ RdapServices? (writeonly)

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



41
42
43
# File 'utils/shared_audits.rb', line 41

def rdap_services=(value)
  @rdap_services = value
end

Class Method Details

.bitbucket(user, repo, self_submission: false) ⇒ String?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

  • user (String)
  • repo (String)
  • self_submission (Boolean) (defaults to: false)

Returns:



400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
# File 'utils/shared_audits.rb', line 400

def self.bitbucket(user, repo, self_submission: false)
  api_url = "https://api.bitbucket.org/2.0/repositories/#{user}/#{repo}"
  result = Utils::Curl.curl_output("--request", "GET", api_url)
  return unless result.status.success?

   = JSON.parse(result.stdout)
  return if .nil?

  return "Uses deprecated Mercurial support in Bitbucket" if ["scm"] == "hg"

  return "Bitbucket fork (not canonical repository)" unless ["parent"].nil?

  age_days = (Date.today - Date.parse(["created_on"])).to_i
  return "Bitbucket repository too new (#{age_days} days old, 30 days required)" if age_days < 30

  forks_result = Utils::Curl.curl_output("--request", "GET", "#{api_url}/forks")
  return unless forks_result.status.success?

  watcher_result = Utils::Curl.curl_output("--request", "GET", "#{api_url}/watchers")
  return unless watcher_result.status.success?

   = JSON.parse(forks_result.stdout)
  return if .nil?

   = JSON.parse(watcher_result.stdout)
  return if .nil?

  notability_thresholds = notability_thresholds_for(BITBUCKET_NOTABILITY_THRESHOLDS, self_submission)
  return if ["size"] >= notability_thresholds.fetch(:forks) ||
            ["size"] >= notability_thresholds.fetch(:watchers)

  notability_prefix = if self_submission
    "Self-submitted Bitbucket repository not notable enough"
  else
    "Bitbucket repository not notable enough"
  end
  "#{notability_prefix} (<#{notability_thresholds.fetch(:forks)} forks and " \
    "<#{notability_thresholds.fetch(:watchers)} watchers)"
end

.check_deprecate_disable_reason(formula_or_cask) ⇒ String?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:



484
485
486
487
488
489
490
491
492
493
494
495
496
497
# File 'utils/shared_audits.rb', line 484

def self.check_deprecate_disable_reason(formula_or_cask)
  return if !formula_or_cask.deprecated? && !formula_or_cask.disabled?

  reason = formula_or_cask.deprecated? ? formula_or_cask.deprecation_reason : formula_or_cask.disable_reason
  return unless reason.is_a?(Symbol)

  reasons = if formula_or_cask.is_a?(Formula)
    DeprecateDisable::FORMULA_DEPRECATE_DISABLE_REASONS
  else
    DeprecateDisable::CASK_DEPRECATE_DISABLE_REASONS
  end

  "#{reason} is not a valid deprecate! or disable! reason" unless reasons.include?(reason)
end

.eol_data(product, cycle) ⇒ Hash{String => T.untyped}?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'utils/shared_audits.rb', line 185

def self.eol_data(product, cycle)
  @eol_data ||= T.let({}, T.nilable(T::Hash[String, T.untyped]))
  key = "#{product}/#{cycle}"
  return @eol_data[key] if @eol_data.key?(key)

  result = Utils::Curl.curl_output(
    "--location",
    "https://endoflife.date/api/v1/products/#{product}/releases/#{cycle}",
  )
  return unless result.status.success?

  @eol_data[key] = begin
    JSON.parse(result.stdout)
  rescue JSON::ParserError
    nil
  end
end

.forgejo(user, repo, self_submission: false) ⇒ String?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

  • user (String)
  • repo (String)
  • self_submission (Boolean) (defaults to: false)

Returns:



441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
# File 'utils/shared_audits.rb', line 441

def self.forgejo(user, repo, self_submission: false)
   = forgejo_repo_data(user, repo)
  return if .nil?

  return "Forgejo fork (not canonical repository)" if ["fork"]

  notability_thresholds = notability_thresholds_for(FORGEJO_NOTABILITY_THRESHOLDS, self_submission)
  notability_prefix = if self_submission
    "Self-submitted Forgejo repository not notable enough"
  else
    "Forgejo repository not notable enough"
  end
  if (["forks_count"] < notability_thresholds.fetch(:forks)) &&
     (["watchers_count"] < notability_thresholds.fetch(:watchers)) &&
     (["stars_count"] < notability_thresholds.fetch(:stars))
    return "#{notability_prefix} (<#{notability_thresholds.fetch(:forks)} forks, " \
           "<#{notability_thresholds.fetch(:watchers)} watchers and " \
           "<#{notability_thresholds.fetch(:stars)} stars)"
  end

  age_days = (Date.today - Date.parse(["created_at"])).to_i
  return if age_days >= 30

  "Forgejo repository too new (#{age_days} days old, 30 days required)"
end

.forgejo_release(user, repo, tag, formula: nil, cask: nil) ⇒ String?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:



330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'utils/shared_audits.rb', line 330

def self.forgejo_release(user, repo, tag, formula: nil, cask: nil)
  release = forgejo_release_data(user, repo, tag)
  return unless release
  return unless release["prerelease"]

  exception, version = if formula
    [formula.tap&.audit_exception(:forgejo_prerelease_allowlist, formula.name), formula.version]
  elsif cask
    [cask.tap&.audit_exception(:forgejo_prerelease_allowlist, cask.token), cask.version]
  end
  return if [version, "all"].include?(exception)

  "#{tag} is a Forgejo pre-release."
end

.forgejo_repo_data(user, repo) ⇒ Hash{String => T.untyped}?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:



267
268
269
270
271
272
273
274
# File 'utils/shared_audits.rb', line 267

def self.forgejo_repo_data(user, repo)
  @forgejo_repo_data ||= T.let({}, T.nilable(T::Hash[String, T.untyped]))
  @forgejo_repo_data["#{user}/#{repo}"] ||= begin
    result = Utils::Curl.curl_output("https://codeberg.org/api/v1/repos/#{user}/#{repo}", "--fail")

    JSON.parse(result.stdout) if result.status.success?
  end
end

.forgejo_tag_from_url(url) ⇒ String?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:



479
480
481
# File 'utils/shared_audits.rb', line 479

def self.forgejo_tag_from_url(url)
  url[%r{^https://codeberg\.org/[\w-]+/[\w.-]+/archive/(.+)\.(?:tar\.gz|zip)$}, 1]
end

.github(user, repo, self_submission: false) ⇒ String?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

  • user (String)
  • repo (String)
  • self_submission (Boolean) (defaults to: false)

Returns:



346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
# File 'utils/shared_audits.rb', line 346

def self.github(user, repo, self_submission: false)
   = github_repo_data(user, repo)

  return if .nil?

  return "GitHub fork (not canonical repository)" if ["fork"]

  notability_thresholds = notability_thresholds_for(GITHUB_NOTABILITY_THRESHOLDS, self_submission)
  notability_prefix = if self_submission
    "Self-submitted GitHub repository not notable enough"
  else
    "GitHub repository not notable enough"
  end
  if (["forks_count"] < notability_thresholds.fetch(:forks)) &&
     (["subscribers_count"] < notability_thresholds.fetch(:watchers)) &&
     (["stargazers_count"] < notability_thresholds.fetch(:stars))
    return "#{notability_prefix} (<#{notability_thresholds.fetch(:forks)} forks, " \
           "<#{notability_thresholds.fetch(:watchers)} watchers and " \
           "<#{notability_thresholds.fetch(:stars)} stars)"
  end

  age_days = (Date.today - Date.parse(["created_at"])).to_i
  return if age_days >= 30

  "GitHub repository too new (#{age_days} days old, 30 days required)"
end

.github_release(user, repo, tag, formula: nil, cask: nil) ⇒ String?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:



236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'utils/shared_audits.rb', line 236

def self.github_release(user, repo, tag, formula: nil, cask: nil)
  release = github_release_data(user, repo, tag)
  return unless release

  exception, name, version = if formula
    [formula.tap&.audit_exception(:github_prerelease_allowlist, formula.name), formula.name, formula.version]
  elsif cask
    [cask.tap&.audit_exception(:github_prerelease_allowlist, cask.token), cask.token, cask.version]
  end

  return "#{tag} is a GitHub pre-release." if release["prerelease"] && [version, "all", "any"].exclude?(exception)

  if !release["prerelease"] && exception && [version, "any"].exclude?(exception)
    return "#{tag} is not a GitHub pre-release but '#{name}' is in the GitHub prerelease allowlist."
  end

  "#{tag} is a GitHub draft." if release["draft"]
end

.github_repo_data(user, repo) ⇒ Hash{String => T.untyped}?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:



204
205
206
207
208
209
210
211
212
213
# File 'utils/shared_audits.rb', line 204

def self.github_repo_data(user, repo)
  @github_repo_data ||= T.let({}, T.nilable(T::Hash[String, T.untyped]))
  @github_repo_data["#{user}/#{repo}"] ||= GitHub.repository(user, repo)

  @github_repo_data["#{user}/#{repo}"]
rescue GitHub::API::HTTPNotFoundError
  nil
rescue GitHub::API::AuthenticationFailedError => e
  raise unless e.message.match?(GitHub::API::GITHUB_IP_ALLOWLIST_ERROR)
end

.github_tag_from_url(url) ⇒ String?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:



468
469
470
471
# File 'utils/shared_audits.rb', line 468

def self.github_tag_from_url(url)
  tag = url[%r{^https://github\.com/[\w-]+/[\w.-]+/archive/refs/tags/(.+)\.(?:tar\.gz|zip)$}, 1]
  tag || url[%r{^https://github\.com/[\w-]+/[\w.-]+/releases/download/([^/]+)/}, 1]
end

.gitlab(user, repo, self_submission: false) ⇒ String?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

  • user (String)
  • repo (String)
  • self_submission (Boolean) (defaults to: false)

Returns:



374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
# File 'utils/shared_audits.rb', line 374

def self.gitlab(user, repo, self_submission: false)
   = gitlab_repo_data(user, repo)

  return if .nil?

  return "GitLab fork (not canonical repository)" if ["fork"]

  notability_thresholds = notability_thresholds_for(GITLAB_NOTABILITY_THRESHOLDS, self_submission)
  notability_prefix = if self_submission
    "Self-submitted GitLab repository not notable enough"
  else
    "GitLab repository not notable enough"
  end
  if (["forks_count"] < notability_thresholds.fetch(:forks)) &&
     (["star_count"] < notability_thresholds.fetch(:stars))
    return "#{notability_prefix} (<#{notability_thresholds.fetch(:forks)} forks and " \
           "<#{notability_thresholds.fetch(:stars)} stars)"
  end

  age_days = (Date.today - Date.parse(["created_at"])).to_i
  return if age_days >= 30

  "GitLab repository too new (#{age_days} days old, 30 days required)"
end

.gitlab_release(user, repo, tag, formula: nil, cask: nil) ⇒ String?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:



295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
# File 'utils/shared_audits.rb', line 295

def self.gitlab_release(user, repo, tag, formula: nil, cask: nil)
  release = gitlab_release_data(user, repo, tag)
  return unless release

  return if DateTime.parse(release["released_at"]) <= DateTime.now

  exception, version = if formula
    [formula.tap&.audit_exception(:gitlab_prerelease_allowlist, formula.name), formula.version]
  elsif cask
    [cask.tap&.audit_exception(:gitlab_prerelease_allowlist, cask.token), cask.version]
  end
  return if [version, "all"].include?(exception)

  "#{tag} is a GitLab pre-release."
end

.gitlab_repo_data(user, repo) ⇒ Hash{String => T.untyped}?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:



256
257
258
259
260
261
262
263
264
# File 'utils/shared_audits.rb', line 256

def self.gitlab_repo_data(user, repo)
  @gitlab_repo_data ||= T.let({}, T.nilable(T::Hash[String, T.untyped]))
  @gitlab_repo_data["#{user}/#{repo}"] ||= begin
    result = Utils::Curl.curl_output("https://gitlab.com/api/v4/projects/#{user}%2F#{repo}")
    json = JSON.parse(result.stdout) if result.status.success?
    json = nil if json&.dig("message")&.include?("404 Project Not Found")
    json
  end
end

.gitlab_tag_from_url(url) ⇒ String?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:



474
475
476
# File 'utils/shared_audits.rb', line 474

def self.gitlab_tag_from_url(url)
  url[%r{^https://gitlab\.com/(?:\w[\w.-]*/){2,}-/archive/([^/]+)/}, 1]
end

.homepage_browsed_recently?(browsed) ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

  • browsed (Date, nil)

Returns:

  • (Boolean)


45
46
47
48
49
50
# File 'utils/shared_audits.rb', line 45

def self.homepage_browsed_recently?(browsed)
  return false unless browsed

  today = Date.today
  browsed <= today && browsed.next_year > today
end

.new_domain_problem(homepage) ⇒ String?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'utils/shared_audits.rb', line 53

def self.new_domain_problem(homepage)
  host = begin
    URI(homepage).host
  rescue URI::InvalidURIError
    nil
  end
  return if host.blank?

  domain = host.downcase.delete_prefix("www.")
  return if GIT_FORGE_DOMAINS.any? { |forge| domain == forge || domain.end_with?(".#{forge}") }

  @rdap_services ||= begin
    result = Utils::Curl.curl_output(RDAP_BOOTSTRAP_URL, max_time: RDAP_TIMEOUT_SECONDS)
    (JSON.parse(result.stdout).fetch("services") if result.status.success?) || []
  rescue JSON::ParserError, KeyError, TypeError
    []
  end

  registered_domain = domain
  registered_on = T.let(nil, T.nilable(Date))
  tld = domain.split(".").last
  rdap_urls = @rdap_services.find { |tlds, _| tlds.include?(tld) }&.fetch(1)
  if rdap_urls.present?
    rdap_base_url = (rdap_urls.find { |url| url.start_with?("https://") } || rdap_urls.fetch(0)).delete_suffix("/")
    # Registries answer 4xx for subdomains, so walk up to the registered domain.
    labels = domain.split(".")
    while labels.length >= 2
      candidate = labels.join(".")
      result = Utils::Curl.curl_output(
        "--include", "--location", "#{rdap_base_url}/domain/#{candidate}",
        header: "Accept: application/rdap+json", max_time: RDAP_TIMEOUT_SECONDS
      )
      break unless result.status.success?

      parsed = Utils::Curl.parse_curl_output(result.stdout)
      case parsed.fetch(:responses).last&.fetch(:status_code).to_i
      when 200
        registered_on = begin
          events = JSON.parse(parsed.fetch(:body)).fetch("events", [])
          registration = events.find { |event| event["eventAction"] == "registration" }
          Date.parse(registration.fetch("eventDate")) unless registration.nil?
        rescue JSON::ParserError, KeyError, TypeError, Date::Error
          nil
        end
        registered_domain = candidate unless registered_on.nil?
        break
      when 400..499
        labels.shift
      else
        break
      end
    end
  end

  if registered_on.nil? && which("whois")
    whois = begin
      SystemCommand.run("whois", args: [domain], print_stderr: false, timeout: WHOIS_TIMEOUT_SECONDS)
    rescue Timeout::Error
      nil
    end
    lines = if whois.nil? || !whois.status.success?
      []
    else
      whois.stdout.scrub.lines
    end
    # `whois` may print the IANA record for the TLD (whose creation date is always ancient)
    # before following its referral to the registry, so only look after the referral marker:
    # `# whois.nic.sh` on macOS, `Found a referral to whois.nic.sh.` on Linux.
    if lines.first&.start_with?("% IANA WHOIS server")
      referral_index = lines.index { |line| line.start_with?("# whois.", "Found a referral to ") }
      lines = referral_index ? lines.drop(referral_index + 1) : []
    end

    lines.each do |line|
      value = line[WHOIS_CREATION_DATE_REGEX, 1]
      next if value.nil?

      registered_on = Date.parse(value)
      break
    rescue Date::Error
      nil
    end
  end
  return if registered_on.nil?
  return if (Date.today - registered_on) >= NEW_DOMAIN_THRESHOLD_DAYS

  "`homepage` domain `#{registered_domain}` was registered on #{registered_on}: " \
    "homepages should exist for at least #{NEW_DOMAIN_THRESHOLD_DAYS} days before inclusion"
end

.notability_thresholds_for(thresholds, self_submission) ⇒ Hash{Symbol => Integer}

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:



178
179
180
181
182
# File 'utils/shared_audits.rb', line 178

def self.notability_thresholds_for(thresholds, self_submission)
  return thresholds unless self_submission

  thresholds.transform_values { |value| value * SELF_SUBMISSION_THRESHOLD_MULTIPLIER }
end

.pull_request_authorString?

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



144
145
146
147
148
149
150
151
152
153
154
# File 'utils/shared_audits.rb', line 144

def self.pull_request_author
  return @pull_request_author if @pull_request_author_computed

  @pull_request_author_computed = true
  github_event_path = ENV.fetch("GITHUB_EVENT_PATH", nil)
  return @pull_request_author = nil if github_event_path.blank?

  @pull_request_author = JSON.parse(File.read(github_event_path)).dig("pull_request", "user", "login")
rescue Errno::ENOENT, JSON::ParserError
  @pull_request_author = nil
end

.self_submission?(submitter, repo_owner) ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:

  • (Boolean)


157
158
159
160
161
162
# File 'utils/shared_audits.rb', line 157

def self.self_submission?(submitter, repo_owner)
  return false if submitter.blank?
  return false if repo_owner.empty?

  submitter.casecmp?(repo_owner)
end

.self_submission_for_repo_owner?(repo_owner) ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:

  • (Boolean)


165
166
167
168
169
170
171
172
173
174
175
# File 'utils/shared_audits.rb', line 165

def self.self_submission_for_repo_owner?(repo_owner)
  return false if repo_owner.blank?

  submitter = pull_request_author
  return false if submitter.blank?

  key = repo_owner.downcase
  return @self_submission_cache.fetch(key) if @self_submission_cache.key?(key)

  @self_submission_cache[key] = self_submission?(submitter, repo_owner)
end