Class: Bruh::Bottle

Inherits:
Object
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/bruh/bottle.rb

Overview

Builds and manages Homebrew bottles

Instance Method Summary collapse

Constructor Details

#initialize(interactive: true) ⇒ Bottle

Returns a new instance of Bottle.



14
15
16
17
# File 'lib/bruh/bottle.rb', line 14

def initialize(interactive: true)
  @interactive = interactive
  @tap_dir = T.let(find_homebrew_tap, T.nilable(String))
end

Instance Method Details

#build(version) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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
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
# File 'lib/bruh/bottle.rb', line 20

def build(version)
  return nil unless @tap_dir

  return nil if @interactive && !yes_no_prompt('Do you want to build a Homebrew bottle for this release?')

  puts "Building bottle for #{package_name} formula..."

  Dir.chdir(@tap_dir) do
    # Clean environment - uninstall any existing version
    system("brew uninstall --force #{package_name} 2>/dev/null || true")

    # Ensure tap is properly set up
    tap_name = "#{repo_owner}/tap"
    system("brew untap #{tap_name} 2>/dev/null || true")
    system("brew tap #{tap_name} \"$(pwd)\"")

    # Install with build-bottle flag
    unless system("brew install --build-bottle #{tap_name}/#{package_name}")
      puts 'Failed to install formula with --build-bottle flag'
      return nil
    end

    # Create bottle with JSON output
    bottle_cmd = 'brew bottle --json '
    bottle_cmd += "--root-url=\"https://github.com/#{repo_owner}/#{repo_name}/releases/download/v#{version}\" "
    bottle_cmd += "#{tap_name}/#{package_name}"
    unless system(bottle_cmd)
      puts 'Failed to create bottle'
      return nil
    end

    # Find the JSON file created by brew bottle
    bottle_json = Dir['*.json'].max_by { |f| File.mtime(f) }

    unless bottle_json && File.exist?(bottle_json)
      puts 'Could not find bottle JSON file'
      return nil
    end

    # Parse the JSON file
    bottle_data = JSON.parse(File.read(bottle_json))

    # Extract filenames and other data
    first_entry = bottle_data.values.first
    first_tag = first_entry['bottle']['tags'].values.first

    bottle_info = {
      version: version,
      expected_filename: first_tag['filename'],
      local_filename: first_tag['local_filename'],
      sha256: first_tag['sha256'],
      macos_version: first_entry['bottle']['tags'].keys.first.to_s.split('_')[1]
    }

    # Extract rebuild number from filename if present
    bottle_info[:rebuild] = ::Regexp.last_match(1).to_i if bottle_info[:local_filename] =~ /bottle\.(\d+)/

    # Verify the bottle file exists
    unless File.exist?(bottle_info[:local_filename])
      puts "Bottle file not found: #{bottle_info[:local_filename]}"
      return nil
    end

    # Create bottles directory and move the file
    FileUtils.mkdir_p('bottles')
    FileUtils.mv(bottle_info[:local_filename], 'bottles/')

    puts "Bottle created successfully: bottles/#{bottle_info[:local_filename]}"
    bottle_info
  end
end

#upload_to_github(version, bottle_info) ⇒ Object



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
# File 'lib/bruh/bottle.rb', line 93

def upload_to_github(version, bottle_info)
  # Check for GitHub CLI
  unless system('which gh > /dev/null 2>&1')
    puts 'GitHub CLI (gh) not found. Please install it to automate bottle uploads.'
    return false
  end

  return false if @interactive && !yes_no_prompt('Do you want to upload bottle to GitHub?')

  # Remember current directory
  original_dir = Dir.pwd

  # Change to the tap directory
  Dir.chdir(T.must(@tap_dir)) do
    # Check if release exists
    release_exists = system("gh release view \"v#{version}\" &>/dev/null")

    unless release_exists
      puts "Release v#{version} doesn't exist. Creating it now..."
      release_cmd = "gh release create \"v#{version}\" --title \"Release v#{version}\" "
      release_cmd += "--notes \"Release v#{version} with Homebrew bottle support.\""
      unless system(release_cmd)
        puts 'Failed to create GitHub release'
        return false
      end
    end

    # Rename the bottle file to expected filename
    bottle_src = File.join('bottles', bottle_info[:local_filename])
    bottle_dst = File.join('bottles', bottle_info[:expected_filename])

    FileUtils.mv(bottle_src, bottle_dst) unless bottle_src == bottle_dst

    # Upload to GitHub release
    puts "Uploading bottle to GitHub release v#{version}..."
    unless system("gh release upload \"v#{version}\" \"#{bottle_dst}\" --clobber")
      puts 'Failed to upload bottle to GitHub'
      Dir.chdir(original_dir)
      return false
    end

    puts 'Bottle uploaded successfully to GitHub release!'
  end

  # Change back to original directory
  Dir.chdir(original_dir)
  true
end