Class: BottleTransition Private

Inherits:
Object show all
Defined in:
bottle_transition.rb

Overview

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

TODO:

remove this class and its callers when HOMEBREW_MACOS_NEWEST_SUPPORTED is 27.

Preserve bottles while bootstrapping a macOS release.

Constant Summary collapse

MACOS =

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.

:golden_gate

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(base_ref: nil) ⇒ void

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:

  • base_ref (String, nil) (defaults to: nil)


24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'bottle_transition.rb', line 24

def initialize(base_ref: nil)
  if ENV.fetch("GITHUB_EVENT_NAME", nil) == "merge_group"
    event = JSON.parse(File.read(ENV.fetch("GITHUB_EVENT_PATH")))
    base_ref = event.dig("merge_group", "base_sha")
    if !base_ref.is_a?(String) || !/\A[0-9a-f]{40}\z/.match?(base_ref)
      raise UsageError, "Missing immutable merge-group base SHA."
    end
  end
  base_branch = ENV.fetch("GITHUB_BASE_REF", nil).presence
  @base_ref = T.let(base_ref || (base_branch ? "origin/#{base_branch}" : "origin/HEAD"), String)
  @base_revision = T.let(nil, T.nilable(String))
  @required = T.let({}, T::Hash[String, T::Boolean])
end

Class Method Details

.active?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.

Returns:

  • (Boolean)


19
20
21
# File 'bottle_transition.rb', line 19

def self.active?
  MacOSVersion.from_symbol(MACOS) > HOMEBREW_MACOS_NEWEST_SUPPORTED
end

.tagUtils::Bottles::Tag

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:



14
15
16
# File 'bottle_transition.rb', line 14

def self.tag
  Utils::Bottles::Tag.new(system: MACOS, arch: :arm64)
end

Instance Method Details

#check!(formula, tags:) ⇒ void

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.

This method returns an undefined value.

Parameters:

Raises:



68
69
70
71
72
73
74
75
76
77
# File 'bottle_transition.rb', line 68

def check!(formula, tags:)
  return unless required?(formula)
  return if tags.include?(self.class.tag) || tags.include?(Utils::Bottles.tag(:all))

  raise UsageError, <<~EOS
    #{formula.full_name} already has #{self.class.tag} bottle coverage on #{@base_ref}.
    Build an #{self.class.tag} bottle for #{formula.pkg_version} before publishing or merging.
    Re-run CI against the updated base branch if mass bottling finished after CI started.
  EOS
end

#required?(formula) ⇒ 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)


39
40
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
# File 'bottle_transition.rb', line 39

def required?(formula)
  return false unless self.class.active?
  return false unless formula.tap&.core_tap?
  return false if formula.disabled?

  compatible = Homebrew::SimulateSystem.with(os: MACOS, arch: :arm) do
    candidate = TestRunnerFormula.new(Formulary.factory(formula.path))
    candidate.compatible?(platform: :macos, arch: :arm64, macos_version: MacOSVersion.from_symbol(MACOS))
  end
  return false unless compatible

  @required.fetch(formula.name) do
    repository = CoreTap.instance.path
    @base_revision ||= Utils.safe_popen_read("git", "-C", repository, "rev-parse", "--verify",
                                             "#{@base_ref}^{commit}").strip
    path = formula.tap_path.relative_path_from(repository)
    files = Utils.safe_popen_read("git", "-C", repository, "ls-tree", "--name-only", "-z",
                                  @base_revision, "--", path)
    return @required[formula.name] = false if files.empty?

    contents = Utils.safe_popen_read("git", "-C", repository, "show", "#{@base_revision}:#{path}")
    @required[formula.name] = Homebrew::SimulateSystem.with(os: MACOS, arch: :arm) do
      previous = Formulary.from_contents(formula.name, formula.tap_path, contents)
      previous.bottle_specification.collector.tags.include?(self.class.tag)
    end
  end
end