From 36681e932d72be0a6e8d0873fcc0b375c1f65d2a Mon Sep 17 00:00:00 2001 From: Douglas Eichelberger Date: Fri, 29 May 2026 16:02:24 -0700 Subject: [PATCH 1/4] Migrate tests off sorbet-runtime and trim gemspec sorbet deps The migration in #68 left the test suite using Sorbet's runtime DSL (extend T::Sig, sig, T.must, T.unsafe, T.bind), which only worked because packwerk transitively loaded sorbet-runtime. packwerk 3.3.0 drops sorbet-runtime, so the suite fails with 'uninitialized constant T'. Rather than re-add a sorbet-runtime dependency, finish the migration in test/ the same way as lib/: - Translate sig blocks to #: RBS comments and drop extend T::Sig - Replace requires_ancestor/T.bind with a Minitest::Runnable @requires_ancestor annotation in the fixture helper - Convert T.must to '#: as !nil' and T.unsafe to '#: as untyped' casts Also drop the redundant 'sorbet-static' dev dependency (the 'sorbet' gem already depends on it). --- Gemfile.lock | 1 - packwerk-extensions.gemspec | 1 - test/integration/extension_test.rb | 5 ++--- .../extension_with_unrecognized_config_test.rb | 5 ++--- test/support/application_fixture_helper.rb | 10 +++------- test/unit/folder_privacy/checker_test.rb | 3 +-- test/unit/folder_privacy/validator_test.rb | 3 +-- test/unit/layer/checker_architecture_test.rb | 3 +-- test/unit/layer/checker_test.rb | 3 +-- test/unit/layer/config_test.rb | 3 +-- test/unit/layer/layers_test.rb | 3 +-- test/unit/layer/validator_test.rb | 3 +-- test/unit/privacy/checker_test.rb | 3 +-- test/unit/privacy/package_test.rb | 4 +--- test/unit/privacy/validator_test.rb | 3 +-- test/unit/visibility/checker_test.rb | 3 +-- test/unit/visibility/validator_test.rb | 3 +-- 17 files changed, 19 insertions(+), 40 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 64a5019..a5c353b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -268,7 +268,6 @@ DEPENDENCIES rubocop-gusto rubocop-sorbet! sorbet - sorbet-static tapioca BUNDLED WITH diff --git a/packwerk-extensions.gemspec b/packwerk-extensions.gemspec index d85451a..379b70f 100644 --- a/packwerk-extensions.gemspec +++ b/packwerk-extensions.gemspec @@ -34,6 +34,5 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'rubocop' spec.add_development_dependency 'rubocop-gusto' spec.add_development_dependency 'sorbet' - spec.add_development_dependency 'sorbet-static' spec.add_development_dependency 'tapioca' end diff --git a/test/integration/extension_test.rb b/test/integration/extension_test.rb index 2ddfbd2..cc2ab51 100644 --- a/test/integration/extension_test.rb +++ b/test/integration/extension_test.rb @@ -6,8 +6,6 @@ module Packwerk module Privacy class ExtensionTest < Minitest::Test - extend T::Sig - include ApplicationFixtureHelper setup do @@ -23,7 +21,8 @@ class ExtensionTest < Minitest::Test Packwerk::Checker.all assert_equal(Packwerk::Checker.all.count, 5) found_checker = Packwerk::Checker.all.any? do |checker| - T.unsafe(checker).is_a?(Packwerk::Privacy::Checker) + untyped_checker = checker #: as untyped + untyped_checker.is_a?(Packwerk::Privacy::Checker) end assert found_checker end diff --git a/test/integration/extension_with_unrecognized_config_test.rb b/test/integration/extension_with_unrecognized_config_test.rb index 6cdb55a..6a98d4a 100644 --- a/test/integration/extension_with_unrecognized_config_test.rb +++ b/test/integration/extension_with_unrecognized_config_test.rb @@ -6,8 +6,6 @@ module Packwerk module Privacy class ExtensionWithUnrecognizedConfigTest < Minitest::Test - extend T::Sig - include ApplicationFixtureHelper setup do @@ -23,7 +21,8 @@ class ExtensionWithUnrecognizedConfigTest < Minitest::Test Packwerk::Checker.all assert_equal(Packwerk::Checker.all.count, 5) found_checker = Packwerk::Checker.all.any? do |checker| - T.unsafe(checker).is_a?(Packwerk::Privacy::Checker) + untyped_checker = checker #: as untyped + untyped_checker.is_a?(Packwerk::Privacy::Checker) end assert found_checker end diff --git a/test/support/application_fixture_helper.rb b/test/support/application_fixture_helper.rb index 2db5166..4cae58d 100644 --- a/test/support/application_fixture_helper.rb +++ b/test/support/application_fixture_helper.rb @@ -1,14 +1,11 @@ # typed: true # frozen_string_literal: true +# @requires_ancestor: Minitest::Runnable module ApplicationFixtureHelper TEMP_FIXTURE_DIR = ROOT.join('tmp', 'fixtures').to_s DEFAULT_TEMPLATE = :minimal - extend T::Helpers - - requires_ancestor { Kernel } - def setup_application_fixture @old_working_dir = Dir.pwd end @@ -80,13 +77,12 @@ def using_template? end def copy_dir(path) - root = FileUtils.mkdir_p(fixture_path).last - FileUtils.cp_r("#{path}/.", T.must(root)) + root = FileUtils.mkdir_p(fixture_path).last #: as !nil + FileUtils.cp_r("#{path}/.", root) @app_dir = root end def fixture_path - T.bind(self, Minitest::Runnable) File.join(TEMP_FIXTURE_DIR, "#{name}-#{Time.now.strftime('%Y_%m_%d_%H_%M_%S')}") end end diff --git a/test/unit/folder_privacy/checker_test.rb b/test/unit/folder_privacy/checker_test.rb index 65dbab7..f24e27b 100644 --- a/test/unit/folder_privacy/checker_test.rb +++ b/test/unit/folder_privacy/checker_test.rb @@ -6,7 +6,6 @@ module Packwerk module FolderPrivacy class CheckerTest < Minitest::Test - extend T::Sig include FactoryHelper include RailsApplicationFixtureHelper @@ -61,7 +60,7 @@ class CheckerTest < Minitest::Test private - sig { returns(Checker) } + #: -> Checker def folder_privacy_checker FolderPrivacy::Checker.new end diff --git a/test/unit/folder_privacy/validator_test.rb b/test/unit/folder_privacy/validator_test.rb index 8173610..f0c8f10 100644 --- a/test/unit/folder_privacy/validator_test.rb +++ b/test/unit/folder_privacy/validator_test.rb @@ -9,7 +9,6 @@ module Packwerk module FolderPrivacy class ValidatorTest < Minitest::Test - extend T::Sig include ApplicationFixtureHelper include RailsApplicationFixtureHelper @@ -40,7 +39,7 @@ class ValidatorTest < Minitest::Test assert result.ok? end - sig { returns(Packwerk::FolderPrivacy::Validator) } + #: -> Packwerk::FolderPrivacy::Validator def validator @validator ||= Packwerk::FolderPrivacy::Validator.new end diff --git a/test/unit/layer/checker_architecture_test.rb b/test/unit/layer/checker_architecture_test.rb index 0aaa2aa..6c2d190 100644 --- a/test/unit/layer/checker_architecture_test.rb +++ b/test/unit/layer/checker_architecture_test.rb @@ -6,7 +6,6 @@ module Packwerk module Layer class CheckerTest < Minitest::Test - extend T::Sig include FactoryHelper include RailsApplicationFixtureHelper @@ -120,7 +119,7 @@ def utility_pack(enforce: false) private - sig { returns(Checker) } + #: -> Checker def layer_checker Packwerk::Layer::Checker.new end diff --git a/test/unit/layer/checker_test.rb b/test/unit/layer/checker_test.rb index 8478229..48c8871 100644 --- a/test/unit/layer/checker_test.rb +++ b/test/unit/layer/checker_test.rb @@ -6,7 +6,6 @@ module Packwerk module Layer class CheckerTest < Minitest::Test - extend T::Sig include FactoryHelper include RailsApplicationFixtureHelper @@ -124,7 +123,7 @@ def utility_pack(enforce: false) private - sig { returns(Checker) } + #: -> Checker def layer_checker Packwerk::Layer::Checker.new end diff --git a/test/unit/layer/config_test.rb b/test/unit/layer/config_test.rb index 6360f60..bebe606 100644 --- a/test/unit/layer/config_test.rb +++ b/test/unit/layer/config_test.rb @@ -6,7 +6,6 @@ module Packwerk module Layer class ConfigTest < Minitest::Test - extend T::Sig include FactoryHelper include RailsApplicationFixtureHelper @@ -58,7 +57,7 @@ def write_architecture_config private - sig { returns(Config) } + #: -> Config def config_instance Packwerk::Layer::Config.new end diff --git a/test/unit/layer/layers_test.rb b/test/unit/layer/layers_test.rb index a7130a6..7f1aa38 100644 --- a/test/unit/layer/layers_test.rb +++ b/test/unit/layer/layers_test.rb @@ -6,7 +6,6 @@ module Packwerk module Layer class LayersTest < Minitest::Test - extend T::Sig include FactoryHelper include RailsApplicationFixtureHelper @@ -34,7 +33,7 @@ def write_config private - sig { returns(Layers) } + #: -> Layers def layers_class Packwerk::Layer::Layers.new end diff --git a/test/unit/layer/validator_test.rb b/test/unit/layer/validator_test.rb index 1b4c3c3..8fc8736 100644 --- a/test/unit/layer/validator_test.rb +++ b/test/unit/layer/validator_test.rb @@ -6,7 +6,6 @@ module Packwerk module Layer class ValidatorTest < Minitest::Test - extend T::Sig include ApplicationFixtureHelper include RailsApplicationFixtureHelper @@ -175,7 +174,7 @@ def write_architecture_config assert_equal validator.permitted_keys, %w(enforce_architecture layer) end - sig { returns(Packwerk::Layer::Validator) } + #: -> Packwerk::Layer::Validator def validator @validator ||= Packwerk::Layer::Validator.new end diff --git a/test/unit/privacy/checker_test.rb b/test/unit/privacy/checker_test.rb index 3cd33a0..4195506 100644 --- a/test/unit/privacy/checker_test.rb +++ b/test/unit/privacy/checker_test.rb @@ -6,7 +6,6 @@ module Packwerk module Privacy class CheckerTest < Minitest::Test - extend T::Sig include FactoryHelper include RailsApplicationFixtureHelper @@ -169,7 +168,7 @@ class CheckerTest < Minitest::Test private - sig { returns(Checker) } + #: -> Checker def privacy_checker Privacy::Checker.new end diff --git a/test/unit/privacy/package_test.rb b/test/unit/privacy/package_test.rb index 427adee..a463d0f 100644 --- a/test/unit/privacy/package_test.rb +++ b/test/unit/privacy/package_test.rb @@ -6,8 +6,6 @@ module Packwerk module Privacy class PackageTest < Minitest::Test - extend T::Sig - include RailsApplicationFixtureHelper setup do @@ -19,7 +17,7 @@ class PackageTest < Minitest::Test teardown_application_fixture end - sig { returns(Package) } + #: -> Package def privacy_package Package.from(@package) end diff --git a/test/unit/privacy/validator_test.rb b/test/unit/privacy/validator_test.rb index 753b7d4..904dd9e 100644 --- a/test/unit/privacy/validator_test.rb +++ b/test/unit/privacy/validator_test.rb @@ -9,7 +9,6 @@ module Packwerk module Privacy class ValidatorTest < Minitest::Test - extend T::Sig include ApplicationFixtureHelper include RailsApplicationFixtureHelper @@ -128,7 +127,7 @@ class ValidatorTest < Minitest::Test private - sig { returns(ApplicationValidator) } + #: -> ApplicationValidator def validator @validator ||= ApplicationValidator.new end diff --git a/test/unit/visibility/checker_test.rb b/test/unit/visibility/checker_test.rb index ac9b48f..f018563 100644 --- a/test/unit/visibility/checker_test.rb +++ b/test/unit/visibility/checker_test.rb @@ -6,7 +6,6 @@ module Packwerk module Visibility class CheckerTest < Minitest::Test - extend T::Sig include FactoryHelper include RailsApplicationFixtureHelper @@ -59,7 +58,7 @@ class CheckerTest < Minitest::Test private - sig { returns(Checker) } + #: -> Checker def visibility_checker Visibility::Checker.new end diff --git a/test/unit/visibility/validator_test.rb b/test/unit/visibility/validator_test.rb index a3f80b8..de459bb 100644 --- a/test/unit/visibility/validator_test.rb +++ b/test/unit/visibility/validator_test.rb @@ -9,7 +9,6 @@ module Packwerk module Visibility class ValidatorTest < Minitest::Test - extend T::Sig include ApplicationFixtureHelper include RailsApplicationFixtureHelper @@ -69,7 +68,7 @@ class ValidatorTest < Minitest::Test assert result.ok? end - sig { returns(Packwerk::Visibility::Validator) } + #: -> Packwerk::Visibility::Validator def validator @validator ||= Packwerk::Visibility::Validator.new end From 5be2778fb2a867dc70e79933be318e74b92aa33e Mon Sep 17 00:00:00 2001 From: Douglas Eichelberger Date: Fri, 29 May 2026 16:06:07 -0700 Subject: [PATCH 2/4] Avoid untyped cast in integration specs Use Enumerable#any? with the class as a === pattern instead of casting the abstract Packwerk::Checker element to untyped to call is_a?. This keeps the check fully typed (no type erasure). --- test/integration/extension_test.rb | 6 +----- test/integration/extension_with_unrecognized_config_test.rb | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/test/integration/extension_test.rb b/test/integration/extension_test.rb index cc2ab51..59fcb28 100644 --- a/test/integration/extension_test.rb +++ b/test/integration/extension_test.rb @@ -20,11 +20,7 @@ class ExtensionTest < Minitest::Test use_template(:extended) Packwerk::Checker.all assert_equal(Packwerk::Checker.all.count, 5) - found_checker = Packwerk::Checker.all.any? do |checker| - untyped_checker = checker #: as untyped - untyped_checker.is_a?(Packwerk::Privacy::Checker) - end - assert found_checker + assert(Packwerk::Checker.all.any?(Packwerk::Privacy::Checker)) end end end diff --git a/test/integration/extension_with_unrecognized_config_test.rb b/test/integration/extension_with_unrecognized_config_test.rb index 6a98d4a..ca9e4f5 100644 --- a/test/integration/extension_with_unrecognized_config_test.rb +++ b/test/integration/extension_with_unrecognized_config_test.rb @@ -20,11 +20,7 @@ class ExtensionWithUnrecognizedConfigTest < Minitest::Test use_template(:with_unrecognized_config) Packwerk::Checker.all assert_equal(Packwerk::Checker.all.count, 5) - found_checker = Packwerk::Checker.all.any? do |checker| - untyped_checker = checker #: as untyped - untyped_checker.is_a?(Packwerk::Privacy::Checker) - end - assert found_checker + assert(Packwerk::Checker.all.any?(Packwerk::Privacy::Checker)) end end end From 696643913ad87f1bb75770fc4dcafcf0c63fdec6 Mon Sep 17 00:00:00 2001 From: Douglas Eichelberger Date: Fri, 29 May 2026 16:10:34 -0700 Subject: [PATCH 3/4] Use Array#fetch(-1) instead of last with a non-nil cast fetch(-1) returns a non-nil element type, so no '#: as !nil' cast is needed (and it raises IndexError rather than silently returning nil). --- test/support/application_fixture_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/support/application_fixture_helper.rb b/test/support/application_fixture_helper.rb index 4cae58d..2b04ecd 100644 --- a/test/support/application_fixture_helper.rb +++ b/test/support/application_fixture_helper.rb @@ -77,7 +77,7 @@ def using_template? end def copy_dir(path) - root = FileUtils.mkdir_p(fixture_path).last #: as !nil + root = FileUtils.mkdir_p(fixture_path).fetch(-1) FileUtils.cp_r("#{path}/.", root) @app_dir = root end From f2ef19d5fa3ba9252b21767d67541c5643f5b6f7 Mon Sep 17 00:00:00 2001 From: Douglas Eichelberger Date: Fri, 29 May 2026 16:13:24 -0700 Subject: [PATCH 4/4] Use total methods instead of non-nil casts in privacy checker - publicized_locations.fetch(location) instead of [] with '#: as !nil' (the key is guaranteed present by the preceding key? guard) - lines.first(5) instead of lines[0..4] with '#: as !nil' (first(n) returns a non-nil Array) --- lib/packwerk/privacy/checker.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/packwerk/privacy/checker.rb b/lib/packwerk/privacy/checker.rb index 050c854..bf1f78e 100644 --- a/lib/packwerk/privacy/checker.rb +++ b/lib/packwerk/privacy/checker.rb @@ -25,7 +25,7 @@ def publicized_location?(location) publicized_locations[location] = check_for_publicized_sigil(location) end - publicized_locations[location] #: as !nil + publicized_locations.fetch(location) end #: (String location) -> bool @@ -35,8 +35,7 @@ def check_for_publicized_sigil(location) #: (Array[String] lines) -> bool def content_contains_sigil?(lines) - first_lines = lines[0..4] #: as !nil - first_lines.any? { |l| l =~ PUBLICIZED_SIGIL_REGEX } + lines.first(5).any? { |l| l =~ PUBLICIZED_SIGIL_REGEX } end end