Skip to content

Commit 9b25148

Browse files
committed
test-bot: inline portable-ruby validation into portable_formula!
After `brew bottle portable-ruby` succeeds, stage the just-built bottle into `HOMEBREW_CACHE`, swap in the vendored portable-ruby, and run the Homebrew/brew PR CI surface against it so issues are caught in the homebrew-core PR rather than the follow-up brew bump PR. Shared bundler-syncing logic lives in a small `Utils::PortableRuby` helper for reuse with the new `bump-portable-ruby` workflow.
1 parent df39236 commit 9b25148

3 files changed

Lines changed: 93 additions & 3 deletions

File tree

Library/Homebrew/test_bot.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
require "tap"
1616
require "utils"
1717
require "utils/bottles"
18+
require "utils/portable_ruby"
1819

1920
module Homebrew
2021
module TestBot

Library/Homebrew/test_bot/formulae.rb

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def run!(args:)
6969
sorted_formulae.each do |f|
7070
verify_local_bottles
7171
if testing_portable_ruby?
72-
portable_formula!(f)
72+
portable_formula!(f, args:)
7373
else
7474
formula!(f, args:)
7575
end
@@ -754,8 +754,8 @@ def formula!(formula_name, args:)
754754
end
755755
end
756756

757-
sig { params(formula_name: String).void }
758-
def portable_formula!(formula_name)
757+
sig { params(formula_name: String, args: Homebrew::Cmd::TestBotCmd::Args).void }
758+
def portable_formula!(formula_name, args:)
759759
test_header(:Formulae, method: "portable_formula!(#{formula_name})")
760760

761761
install_ca_certificates_if_needed
@@ -788,6 +788,66 @@ def portable_formula!(formula_name)
788788
test "brew", "test", formula_name
789789
test "brew", "linkage", formula_name
790790
test "brew", "bottle", "--skip-relocation", "--json", "--no-rebuild", formula_name
791+
792+
# We only do full testing on `portable-ruby` itself.
793+
return if formula_name != "portable-ruby"
794+
return if args.dry_run?
795+
796+
bottle_file = bottle_glob(formula_name).first
797+
if bottle_file.nil?
798+
failed formula_name, "no bottle file found for portable-ruby validation"
799+
return
800+
end
801+
802+
filename = bottle_file.basename.to_s
803+
_, tag_string, = Utils::Bottles.extname_tag_rebuild(filename)
804+
if tag_string.blank?
805+
failed formula_name, "could not parse bottle filename #{filename}"
806+
return
807+
end
808+
809+
pkg_version = filename.delete_prefix("portable-ruby--")
810+
.sub(/\.#{Regexp.escape(tag_string)}\.bottle.*\.tar\.gz\z/, "")
811+
if pkg_version.empty?
812+
failed formula_name, "could not parse portable-ruby version from #{filename}"
813+
return
814+
end
815+
816+
tag_symbol = tag_string.to_sym
817+
bottle_tag = Utils::Bottles::Tag.from_symbol(tag_symbol)
818+
sha256 = bottle_file.sha256
819+
version = pkg_version.split("_").first.to_s
820+
821+
vendor_dir = HOMEBREW_LIBRARY_PATH/"vendor"
822+
(vendor_dir/"portable-ruby-version").atomic_write("#{pkg_version}\n")
823+
(HOMEBREW_LIBRARY_PATH/".ruby-version").atomic_write("#{version}\n")
824+
os = bottle_tag.linux? ? "linux" : "darwin"
825+
platform_file = vendor_dir/"portable-ruby-#{bottle_tag.standardized_arch}-#{os}"
826+
platform_file.atomic_write("ruby_TAG=#{tag_symbol}\nruby_SHA=#{sha256}\n")
827+
828+
# Seed `HOMEBREW_CACHE` so `brew vendor-install ruby` finds the just-built
829+
# bottle locally instead of trying to download it.
830+
HOMEBREW_CACHE.mkpath
831+
FileUtils.cp(bottle_file, HOMEBREW_CACHE/"portable-ruby-#{pkg_version}.#{tag_symbol}.bottle.tar.gz")
832+
833+
test "brew", "vendor-install", "ruby"
834+
835+
bundler_version = Utils::PortableRuby.sync_bundler_version!(pkg_version)
836+
test "brew", "vendor-gems", "--no-commit", "--update=--ruby,--bundler=#{bundler_version}"
837+
test "brew", "typecheck", "--update"
838+
839+
# Run the checks that gate a Homebrew/brew pull request.
840+
test "brew", "style"
841+
test "brew", "typecheck"
842+
test "brew", "install-bundler-gems", "--groups=all"
843+
test "brew", "vendor-gems", "--non-bundler-gems", "--no-commit"
844+
test "brew", "tests", "--online", "--coverage"
845+
test "brew", "tests", "--generic", "--coverage"
846+
test "brew", "update-test"
847+
test "brew", "update-test", "--to-tag"
848+
test "brew", "update-test", "--commit=HEAD"
849+
test "brew", "test-bot", "--only-formulae", "--only-json-tab", "--test-default-formula",
850+
env: { "GITHUB_ACTIONS" => nil }
791851
end
792852

793853
sig { params(formula_name: String).void }
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# typed: strict
2+
# frozen_string_literal: true
3+
4+
require "utils/output"
5+
6+
module Utils
7+
# Helper functions for the vendored portable-ruby.
8+
module PortableRuby
9+
extend Utils::Output::Mixin
10+
11+
# Syncs `HOMEBREW_BUNDLER_VERSION` in `utils/ruby.sh` with the bundler shipped
12+
# by the portable-ruby unpacked at `pkg_version`.
13+
sig { params(pkg_version: String).returns(String) }
14+
def self.sync_bundler_version!(pkg_version)
15+
unpacked = HOMEBREW_LIBRARY_PATH/"vendor/portable-ruby/#{pkg_version}"
16+
bundler_dir = Pathname.glob(unpacked/"lib/ruby/gems/*/gems/bundler-*").first
17+
odie "Cannot find vendored bundler for portable-ruby #{pkg_version}." if bundler_dir.nil?
18+
19+
bundler_version = bundler_dir.basename.to_s.delete_prefix("bundler-")
20+
21+
ruby_sh = HOMEBREW_LIBRARY_PATH/"utils/ruby.sh"
22+
original = ruby_sh.read
23+
updated = original.sub(/(?<=^export HOMEBREW_BUNDLER_VERSION=")[^"]+/, bundler_version)
24+
ruby_sh.atomic_write(updated) if original != updated
25+
26+
bundler_version
27+
end
28+
end
29+
end

0 commit comments

Comments
 (0)