Skip to content

Commit 5c981df

Browse files
committed
generate-cask-ci-matrix: respect on_linux architecture constraints
Refactor the architecture filtering logic in `generate-cask-ci-matrix` to correctly inspect `on_linux` blocks using `Homebrew::SimulateSystem`. This ensures that architecture dependencies defined within `on_linux` (e.g., `depends_on arch: :intel`) are respected when generating the CI matrix.
1 parent 8f67192 commit 5c981df

File tree

3 files changed

+87
-13
lines changed

3 files changed

+87
-13
lines changed

Library/Homebrew/dev-cmd/generate-cask-ci-matrix.rb

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
module Homebrew
1111
module DevCmd
12+
# Generates a GitHub Actions CI matrix for Casks.
13+
# @api private
1214
class GenerateCaskCiMatrix < AbstractCommand
1315
MAX_JOBS = 256
1416

@@ -127,33 +129,71 @@ def run
127129

128130
sig { params(cask: Cask::Cask).returns(T::Hash[T::Hash[Symbol, T.any(Symbol, String)], Float]) }
129131
def filter_runners(cask)
130-
filtered_macos_runners = RUNNERS.select do |runner, _|
131-
runner[:symbol] != :linux &&
132+
filtered_runners = if cask.supports_macos?
133+
filtered_macos_runners = MACOS_RUNNERS.select do |runner, _|
132134
cask.depends_on.macos.present? &&
133-
cask.depends_on.macos.allows?(MacOSVersion.from_symbol(T.must(runner[:symbol]).to_sym))
134-
end
135+
cask.depends_on.macos.allows?(MacOSVersion.from_symbol(T.must(runner[:symbol]).to_sym))
136+
end
137+
138+
return MACOS_RUNNERS.dup if filtered_macos_runners.none?
135139

136-
filtered_runners = if filtered_macos_runners.any?
137140
filtered_macos_runners
138-
else
139-
RUNNERS.dup
140141
end
141142

142-
filtered_runners = filtered_runners.merge(LINUX_RUNNERS) if cask.supports_linux?
143+
filtered_runners = T.must(filtered_runners)
143144

144145
archs = architectures(cask:)
146+
odebug "Architectures macOS: #{archs}" if archs.any?
145147
filtered_runners.select! do |runner, _|
146148
archs.include?(runner.fetch(:arch))
147149
end
148150

151+
odebug "Filtered runners: #{filtered_runners.keys.map { |r| r[:name] }}" if filtered_runners.any?
152+
if cask.supports_linux?
153+
filtered_linux_runners = LINUX_RUNNERS.dup
154+
155+
archs = architectures(cask:, os: :linux, arch: :intel)
156+
filtered_linux_runners.select! do |runner, _|
157+
archs.include?(runner.fetch(:arch))
158+
end
159+
160+
filtered_runners.merge!(filtered_linux_runners)
161+
end
162+
163+
odebug "Architectures linux: #{archs}" if archs.any?
164+
odebug "Filtered runners: #{filtered_runners.keys.map { |r| r[:name] }}" if filtered_runners.any?
165+
149166
filtered_runners
150167
end
151168

152-
sig { params(cask: Cask::Cask).returns(T::Array[Symbol]) }
153-
def architectures(cask:)
154-
return RUNNERS.keys.map { |r| r.fetch(:arch).to_sym }.uniq.sort if cask.depends_on.arch.blank?
169+
sig { params(cask: Cask::Cask, os: Symbol, arch: Symbol).returns(T::Array[Symbol]) }
170+
def architectures(cask:, os: :macos, arch: :arm)
171+
architectures = T.let([], T.untyped)
172+
begin
173+
tag = Utils::Bottles::Tag.new(system: os, arch: arch)
174+
Homebrew::SimulateSystem.with_tag(tag) do
175+
cask.refresh
176+
177+
if cask.depends_on.arch.blank?
178+
# If the Cask does not define a general architecture requirement,
179+
# check if there is one specific to Linux.
180+
architectures = if (linux_archs = Homebrew::SimulateSystem.with(os: :linux) do
181+
Cask::CaskLoader.load(cask.sourcefile_path).depends_on.arch
182+
end)
183+
linux_archs.map { |a| a[:type] }.uniq.sort
184+
else
185+
RUNNERS.keys.map { |r| r.fetch(:arch).to_sym }.uniq.sort
186+
end
187+
next
188+
end
189+
190+
architectures = cask.depends_on.arch.map { |arch| arch[:type] }
191+
end
192+
rescue ::Cask::CaskInvalidError
193+
# Can't read cask for this system-arch combination.
194+
end
155195

156-
cask.depends_on.arch.map { |arch| arch[:type] }.uniq.sort
196+
architectures
157197
end
158198

159199
sig {
@@ -255,7 +295,7 @@ def generate_matrix(tap, labels: [], cask_names: [], skip_install: false, new_ca
255295
native_runner_arch = arch == runner.fetch(:arch)
256296
# we don't need to run simulated archs on Linux
257297
next if runner.fetch(:symbol) == :linux && !native_runner_arch
258-
# we don't need to run simulated archs on macOS
298+
# we don't need to run simulated archs on macOS Sequoia
259299
next if runner.fetch(:symbol) == :sequoia && !native_runner_arch
260300

261301
# If it's just a single OS test then we can just use the two real arch runners.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,27 @@
1+
# typed: strict
12
# frozen_string_literal: true
23

34
require "cmd/shared_examples/args_parse"
45
require "dev-cmd/generate-cask-ci-matrix"
56

67
RSpec.describe Homebrew::DevCmd::GenerateCaskCiMatrix do
78
it_behaves_like "parseable arguments"
9+
10+
describe "#architectures" do
11+
let(:cmd) { described_class.new }
12+
let(:linux_arch_cask) { Cask::CaskLoader.load(TEST_FIXTURE_DIR/"cask/Casks/on-linux-arch.rb") }
13+
let(:standard_cask) { Cask::CaskLoader.load(TEST_FIXTURE_DIR/"cask/Casks/basic-cask.rb") }
14+
15+
it "returns only [:intel] for Casks with an on_linux arch dependency" do
16+
expect(cmd.architectures(cask: linux_arch_cask)).to eq([:intel])
17+
end
18+
19+
it "returns all runners for standard Casks" do
20+
# Assuming standard behavior is to return all archs from RUNNERS
21+
expected_archs = Homebrew::DevCmd::GenerateCaskCiMatrix::RUNNERS.keys.map do |r|
22+
r.fetch(:arch).to_sym
23+
end.uniq.sort
24+
expect(cmd.architectures(cask: standard_cask)).to eq(expected_archs)
25+
end
26+
end
827
end
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
cask "on-linux-arch" do
2+
version "1.0.0"
3+
sha256 :no_check
4+
5+
url "https://brew.sh/"
6+
name "On Linux Arch"
7+
desc "Cask with on_linux architecture dependency"
8+
homepage "https://brew.sh/"
9+
10+
on_linux do
11+
depends_on arch: :intel
12+
end
13+
14+
app "On Linux Arch.app"
15+
end

0 commit comments

Comments
 (0)