lib/danger-packwerk/danger_packwerk.rb in danger-packwerk-0.2.3 vs lib/danger-packwerk/danger_packwerk.rb in danger-packwerk-0.3.0

- old
+ new

@@ -1,10 +1,11 @@ # typed: strict # frozen_string_literal: true require 'danger' require 'packwerk' +require 'parse_packwerk' require 'sorbet-runtime' require 'danger-packwerk/packwerk_wrapper' module DangerPackwerk # Note that Danger names the plugin (i.e. anything that inherits from `Danger::Plugin`) by taking the name of the class and gsubbing out "Danger" @@ -21,25 +22,36 @@ OffensesFormatter = T.type_alias { T.proc.params(offenses: T::Array[Packwerk::ReferenceOffense]).returns(String) } DEFAULT_OFFENSES_FORMATTER = T.let(->(offenses) { offenses.map(&:message).join("\n\n") }, OffensesFormatter) DEFAULT_FAIL = false DEFAULT_FAILURE_MESSAGE = 'Packwerk violations were detected! Please resolve them to unblock the build.' + class CommentGroupingStrategy < ::T::Enum + enums do + PerConstantPerLocation = new + PerConstantPerPack = new + end + end + + PerConstantPerPackGrouping = CommentGroupingStrategy::PerConstantPerPack + sig do params( max_comments: Integer, offenses_formatter: OffensesFormatter, fail_build: T::Boolean, failure_message: String, - on_failure: OnFailure + on_failure: OnFailure, + grouping_strategy: CommentGroupingStrategy ).void end def check( max_comments: DEFAULT_MAX_COMMENTS, offenses_formatter: DEFAULT_OFFENSES_FORMATTER, fail_build: DEFAULT_FAIL, failure_message: DEFAULT_FAILURE_MESSAGE, - on_failure: DEFAULT_ON_FAILURE + on_failure: DEFAULT_ON_FAILURE, + grouping_strategy: CommentGroupingStrategy::PerConstantPerLocation ) # This is important because by default, Danger will leave a concantenated list of all its messages if it can't find a commentable place in the # diff to leave its message. This is an especially bad UX because it will be a huge wall of text not connected to the source of the issue. # Furthermore, dismissing these ensures that something like moving a file from pack to pack does not trigger the danger message. That is, # the danger message will only be triggered by actual code that someone has actually written in their PR. @@ -73,14 +85,24 @@ packwerk_reference_offenses = PackwerkWrapper.get_offenses_for_files(targeted_files.to_a).compact # We group by the constant name, line number, and reference path. Any offenses with these same values should only differ on what type of violation # they are (privacy or dependency). We put privacy and dependency violation messages in the same comment since they would occur on the same line. packwerk_reference_offenses.group_by do |packwerk_reference_offense| - [ - packwerk_reference_offense.reference.constant.name, - packwerk_reference_offense.location.line, - packwerk_reference_offense.reference.relative_path - ] + case grouping_strategy + when CommentGroupingStrategy::PerConstantPerLocation + [ + packwerk_reference_offense.reference.constant.name, + packwerk_reference_offense.location.line, + packwerk_reference_offense.reference.relative_path + ] + when CommentGroupingStrategy::PerConstantPerPack + [ + packwerk_reference_offense.reference.constant.name, + ParsePackwerk.package_from_path(packwerk_reference_offense.reference.relative_path) + ] + else + T.absurd(grouping_strategy) + end end.each do |_group, unique_packwerk_reference_offenses| break if current_comment_count >= max_comments current_comment_count += 1