github_runner_matrix: filter incompatible testing formulae
`brew test-bot` can occasionally spend a long time doing nothing when testing dependents.[^1] This is because it takes a long time to work out that there is nothing to do. To fix this, let's adjust `brew determine-test-runners` to pass on only the list of formulae for which there is work to be done so that `brew test-bot` doesn't need to waste time working this out. [^1]: For example, it spends about 15 minutes doing nothing at https://github.com/Homebrew/homebrew-core/actions/runs/10500178069/job/29133091332?pr=180185
This commit is contained in:
parent
17e3bee3da
commit
3588f1b8c5
@ -10,7 +10,15 @@ class GitHubRunnerMatrix
|
|||||||
RunnerSpec = T.type_alias { T.any(LinuxRunnerSpec, MacOSRunnerSpec) }
|
RunnerSpec = T.type_alias { T.any(LinuxRunnerSpec, MacOSRunnerSpec) }
|
||||||
private_constant :RunnerSpec
|
private_constant :RunnerSpec
|
||||||
|
|
||||||
MacOSRunnerSpecHash = T.type_alias { { name: String, runner: String, timeout: Integer, cleanup: T::Boolean } }
|
MacOSRunnerSpecHash = T.type_alias do
|
||||||
|
{
|
||||||
|
name: String,
|
||||||
|
runner: String,
|
||||||
|
timeout: Integer,
|
||||||
|
cleanup: T::Boolean,
|
||||||
|
testing_formulae: String,
|
||||||
|
}
|
||||||
|
end
|
||||||
private_constant :MacOSRunnerSpecHash
|
private_constant :MacOSRunnerSpecHash
|
||||||
|
|
||||||
LinuxRunnerSpecHash = T.type_alias do
|
LinuxRunnerSpecHash = T.type_alias do
|
||||||
@ -21,6 +29,7 @@ class GitHubRunnerMatrix
|
|||||||
workdir: String,
|
workdir: String,
|
||||||
timeout: Integer,
|
timeout: Integer,
|
||||||
cleanup: T::Boolean,
|
cleanup: T::Boolean,
|
||||||
|
testing_formulae: String,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
private_constant :LinuxRunnerSpecHash
|
private_constant :LinuxRunnerSpecHash
|
||||||
@ -49,6 +58,8 @@ class GitHubRunnerMatrix
|
|||||||
@deleted_formulae = T.let(deleted_formulae, T::Array[String])
|
@deleted_formulae = T.let(deleted_formulae, T::Array[String])
|
||||||
@all_supported = T.let(all_supported, T::Boolean)
|
@all_supported = T.let(all_supported, T::Boolean)
|
||||||
@dependent_matrix = T.let(dependent_matrix, T::Boolean)
|
@dependent_matrix = T.let(dependent_matrix, T::Boolean)
|
||||||
|
@compatible_testing_formulae = T.let({}, T::Hash[GitHubRunner, T::Array[TestRunnerFormula]])
|
||||||
|
@formulae_with_untested_dependents = T.let({}, T::Hash[GitHubRunner, T::Array[TestRunnerFormula]])
|
||||||
|
|
||||||
@runners = T.let([], T::Array[GitHubRunner])
|
@runners = T.let([], T::Array[GitHubRunner])
|
||||||
generate_runners!
|
generate_runners!
|
||||||
@ -102,6 +113,7 @@ class GitHubRunnerMatrix
|
|||||||
raise "Unexpected arch: #{arch}" if VALID_ARCHES.exclude?(arch)
|
raise "Unexpected arch: #{arch}" if VALID_ARCHES.exclude?(arch)
|
||||||
|
|
||||||
runner = GitHubRunner.new(platform:, arch:, spec:, macos_version:)
|
runner = GitHubRunner.new(platform:, arch:, spec:, macos_version:)
|
||||||
|
runner.spec.testing_formulae += testable_formulae(runner)
|
||||||
runner.active = active_runner?(runner)
|
runner.active = active_runner?(runner)
|
||||||
runner.freeze
|
runner.freeze
|
||||||
end
|
end
|
||||||
@ -185,47 +197,50 @@ class GitHubRunnerMatrix
|
|||||||
@runners.freeze
|
@runners.freeze
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(runner: GitHubRunner).returns(T::Array[String]) }
|
||||||
|
def testable_formulae(runner)
|
||||||
|
formulae = if @dependent_matrix
|
||||||
|
formulae_with_untested_dependents(runner)
|
||||||
|
else
|
||||||
|
compatible_testing_formulae(runner)
|
||||||
|
end
|
||||||
|
|
||||||
|
formulae.map(&:name)
|
||||||
|
end
|
||||||
|
|
||||||
sig { params(runner: GitHubRunner).returns(T::Boolean) }
|
sig { params(runner: GitHubRunner).returns(T::Boolean) }
|
||||||
def active_runner?(runner)
|
def active_runner?(runner)
|
||||||
if @dependent_matrix
|
return true if @all_supported || @deleted_formulae.present?
|
||||||
formulae_have_untested_dependents?(runner)
|
|
||||||
elsif !@all_supported && @deleted_formulae.empty?
|
|
||||||
compatible_formulae = @testing_formulae.dup
|
|
||||||
|
|
||||||
|
testable_formulae(runner).present?
|
||||||
|
end
|
||||||
|
|
||||||
|
sig { params(runner: GitHubRunner).returns(T::Array[TestRunnerFormula]) }
|
||||||
|
def compatible_testing_formulae(runner)
|
||||||
|
@compatible_testing_formulae[runner] ||= begin
|
||||||
platform = runner.platform
|
platform = runner.platform
|
||||||
arch = runner.arch
|
arch = runner.arch
|
||||||
macos_version = runner.macos_version
|
macos_version = runner.macos_version
|
||||||
|
|
||||||
compatible_formulae.select! do |formula|
|
@testing_formulae.select do |formula|
|
||||||
next false if macos_version && !formula.compatible_with?(macos_version)
|
next false if macos_version && !formula.compatible_with?(macos_version)
|
||||||
|
|
||||||
formula.public_send(:"#{platform}_compatible?") &&
|
formula.public_send(:"#{platform}_compatible?") &&
|
||||||
formula.public_send(:"#{arch}_compatible?")
|
formula.public_send(:"#{arch}_compatible?")
|
||||||
end
|
end
|
||||||
|
|
||||||
compatible_formulae.present?
|
|
||||||
else
|
|
||||||
true
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(runner: GitHubRunner).returns(T::Boolean) }
|
sig { params(runner: GitHubRunner).returns(T::Array[TestRunnerFormula]) }
|
||||||
def formulae_have_untested_dependents?(runner)
|
def formulae_with_untested_dependents(runner)
|
||||||
|
@formulae_with_untested_dependents[runner] ||= begin
|
||||||
platform = runner.platform
|
platform = runner.platform
|
||||||
arch = runner.arch
|
arch = runner.arch
|
||||||
macos_version = runner.macos_version
|
macos_version = runner.macos_version
|
||||||
|
|
||||||
@testing_formulae.any? do |formula|
|
compatible_testing_formulae(runner).select do |formula|
|
||||||
# If the formula has a platform/arch/macOS version requirement, then its
|
|
||||||
# dependents don't need to be tested if these requirements are not satisfied.
|
|
||||||
next false unless formula.public_send(:"#{platform}_compatible?")
|
|
||||||
next false unless formula.public_send(:"#{arch}_compatible?")
|
|
||||||
next false if macos_version.present? && !formula.compatible_with?(macos_version)
|
|
||||||
|
|
||||||
compatible_dependents = formula.dependents(platform:, arch:, macos_version: macos_version&.to_sym)
|
compatible_dependents = formula.dependents(platform:, arch:, macos_version: macos_version&.to_sym)
|
||||||
.dup
|
.select do |dependent_f|
|
||||||
|
|
||||||
compatible_dependents.select! do |dependent_f|
|
|
||||||
next false if macos_version && !dependent_f.compatible_with?(macos_version)
|
next false if macos_version && !dependent_f.compatible_with?(macos_version)
|
||||||
|
|
||||||
dependent_f.public_send(:"#{platform}_compatible?") &&
|
dependent_f.public_send(:"#{platform}_compatible?") &&
|
||||||
@ -238,3 +253,4 @@ class GitHubRunnerMatrix
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
@ -8,6 +8,7 @@ class LinuxRunnerSpec < T::Struct
|
|||||||
const :workdir, String
|
const :workdir, String
|
||||||
const :timeout, Integer
|
const :timeout, Integer
|
||||||
const :cleanup, T::Boolean
|
const :cleanup, T::Boolean
|
||||||
|
prop :testing_formulae, T::Array[String], default: []
|
||||||
|
|
||||||
sig {
|
sig {
|
||||||
returns({
|
returns({
|
||||||
@ -17,6 +18,7 @@ class LinuxRunnerSpec < T::Struct
|
|||||||
workdir: String,
|
workdir: String,
|
||||||
timeout: Integer,
|
timeout: Integer,
|
||||||
cleanup: T::Boolean,
|
cleanup: T::Boolean,
|
||||||
|
testing_formulae: String,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
def to_h
|
def to_h
|
||||||
@ -27,6 +29,7 @@ class LinuxRunnerSpec < T::Struct
|
|||||||
workdir:,
|
workdir:,
|
||||||
timeout:,
|
timeout:,
|
||||||
cleanup:,
|
cleanup:,
|
||||||
|
testing_formulae: testing_formulae.join(","),
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -6,14 +6,24 @@ class MacOSRunnerSpec < T::Struct
|
|||||||
const :runner, String
|
const :runner, String
|
||||||
const :timeout, Integer
|
const :timeout, Integer
|
||||||
const :cleanup, T::Boolean
|
const :cleanup, T::Boolean
|
||||||
|
prop :testing_formulae, T::Array[String], default: []
|
||||||
|
|
||||||
sig { returns({ name: String, runner: String, timeout: Integer, cleanup: T::Boolean }) }
|
sig {
|
||||||
|
returns({
|
||||||
|
name: String,
|
||||||
|
runner: String,
|
||||||
|
timeout: Integer,
|
||||||
|
cleanup: T::Boolean,
|
||||||
|
testing_formulae: String,
|
||||||
|
})
|
||||||
|
}
|
||||||
def to_h
|
def to_h
|
||||||
{
|
{
|
||||||
name:,
|
name:,
|
||||||
runner:,
|
runner:,
|
||||||
timeout:,
|
timeout:,
|
||||||
cleanup:,
|
cleanup:,
|
||||||
|
testing_formulae: testing_formulae.join(","),
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user