From c63b69b5b240a171ad8f40408e13b64f27234668 Mon Sep 17 00:00:00 2001 From: Martin Emde Date: Tue, 16 Dec 2025 11:19:19 -0800 Subject: [PATCH 1/3] Capture stdout/err from Packwerk CLI Also use the default Plain style. --- Gemfile.lock | 1 + danger-packwerk.gemspec | 1 + lib/danger-packwerk/packwerk_wrapper.rb | 5 +++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index ef758e2..eeac99a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -25,6 +25,7 @@ PATH packwerk parse_packwerk sorbet-runtime + stringio GEM remote: https://rubygems.org/ diff --git a/danger-packwerk.gemspec b/danger-packwerk.gemspec index 5dd2c5a..f6354cd 100644 --- a/danger-packwerk.gemspec +++ b/danger-packwerk.gemspec @@ -35,4 +35,5 @@ Gem::Specification.new do |spec| spec.add_dependency 'packwerk' spec.add_dependency 'parse_packwerk' spec.add_dependency 'sorbet-runtime' + spec.add_dependency 'stringio' end diff --git a/lib/danger-packwerk/packwerk_wrapper.rb b/lib/danger-packwerk/packwerk_wrapper.rb index 3c5f7c3..1778164 100644 --- a/lib/danger-packwerk/packwerk_wrapper.rb +++ b/lib/danger-packwerk/packwerk_wrapper.rb @@ -1,5 +1,7 @@ # typed: strict +require 'stringio' + module DangerPackwerk # This class wraps packwerk to give us precisely what we want, which is the `Packwerk::ReferenceOffense` from a set of files. # Note that statically packwerk returns `Packwerk::Offense` from running `bin/packwerk check`. The two types of `Packwerk::Offense` are @@ -19,8 +21,7 @@ def self.get_offenses_for_files(files) formatter = OffensesAggregatorFormatter.new # This is mostly copied from exe/packwerk within the packwerk gem, but we use our own formatters ENV['RAILS_ENV'] = 'test' - style = Packwerk::OutputStyles::Coloured.new - cli = Packwerk::Cli.new(style: style, offenses_formatter: formatter) + cli = Packwerk::Cli.new(offenses_formatter: formatter, out: StringIO.new) cli.execute_command(['check', *files]) reference_offenses = formatter.aggregated_offenses.compact.select { |offense| offense.is_a?(Packwerk::ReferenceOffense) } T.cast(reference_offenses, T::Array[Packwerk::ReferenceOffense]) From ed4fe44935e388438e9e3a01a75ba8b96d7b6623 Mon Sep 17 00:00:00 2001 From: Martin Emde Date: Tue, 16 Dec 2025 11:19:19 -0800 Subject: [PATCH 2/3] Add a beter explanation of how we call the packwerk cli --- lib/danger-packwerk/packwerk_wrapper.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/danger-packwerk/packwerk_wrapper.rb b/lib/danger-packwerk/packwerk_wrapper.rb index 1778164..6b38916 100644 --- a/lib/danger-packwerk/packwerk_wrapper.rb +++ b/lib/danger-packwerk/packwerk_wrapper.rb @@ -16,10 +16,15 @@ module DangerPackwerk class PackwerkWrapper extend T::Sig + # This code is partially copied from exe/packwerk within the packwerk gem. We're imitating the + # cli here but with our own offense formatter to collect the violating data directly. + # + # We capture and ignore the output of the Cli so that we don't leak it to the build system logs. + # When packwerk produces errors it can make the build system look like it's failing when really + # this is expected behavior. sig { params(files: T::Array[String]).returns(T::Array[Packwerk::ReferenceOffense]) } def self.get_offenses_for_files(files) formatter = OffensesAggregatorFormatter.new - # This is mostly copied from exe/packwerk within the packwerk gem, but we use our own formatters ENV['RAILS_ENV'] = 'test' cli = Packwerk::Cli.new(offenses_formatter: formatter, out: StringIO.new) cli.execute_command(['check', *files]) From 218860e5ce20a5df34663999278ae87a5b64bdfc Mon Sep 17 00:00:00 2001 From: Martin Emde Date: Tue, 16 Dec 2025 11:19:19 -0800 Subject: [PATCH 3/3] Remove unnecessary rescue in PackwerkWrapper This seems to be from a time when the CLI would exit. We don't use the CLI in a way where this can happen anymore. --- lib/danger-packwerk/packwerk_wrapper.rb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/danger-packwerk/packwerk_wrapper.rb b/lib/danger-packwerk/packwerk_wrapper.rb index 6b38916..9484fc8 100644 --- a/lib/danger-packwerk/packwerk_wrapper.rb +++ b/lib/danger-packwerk/packwerk_wrapper.rb @@ -30,14 +30,6 @@ def self.get_offenses_for_files(files) cli.execute_command(['check', *files]) reference_offenses = formatter.aggregated_offenses.compact.select { |offense| offense.is_a?(Packwerk::ReferenceOffense) } T.cast(reference_offenses, T::Array[Packwerk::ReferenceOffense]) - rescue SystemExit => e - # Packwerk should probably exit positively here rather than raising an error -- there should be no - # errors if the user has excluded all files being checked. - if e.message == 'No files found or given. Specify files or check the include and exclude glob in the config file.' - [] - else - raise - end end #