danger-packwerk 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +47 -32
- data/lib/danger-packwerk/basic_reference_offense.rb +19 -19
- data/lib/danger-packwerk/check/default_formatter.rb +3 -3
- data/lib/danger-packwerk/{danger_deprecated_references_yml_changes.rb → danger_package_todo_yml_changes.rb} +25 -25
- data/lib/danger-packwerk/packwerk_wrapper.rb +10 -0
- data/lib/danger-packwerk/private/{deprecated_references.rb → package_todo.rb} +8 -8
- data/lib/danger-packwerk/private.rb +1 -1
- data/lib/danger-packwerk/version.rb +1 -1
- data/lib/danger-packwerk.rb +4 -2
- data/sorbet/rbi/gems/{packwerk@2.2.1.rbi → packwerk@2.2.1-7e8e7a50705833b41fe40c201eadb85ff9a1a422.rbi} +852 -231
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf8895f7ae2e94e0b1d09e146176b6777ba8f952fe03381380071114fcec2bd4
|
4
|
+
data.tar.gz: 2e68e2096375433cfad68d85ca8d5eac7855dcb542b34f79417a53b1e4c9eb1b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bfbe7e86650ac170c89c014f7519d0d40abdb3d864b995d8cdb5ef2478ec3e4fe6f2e3afc4854dbc216e622a8adc99761bd7d9a420167553db6b70084446740f
|
7
|
+
data.tar.gz: b6729e1b52a5f25ae5da573d706bb1f3fc4217c750976dcd51aafd7611a5c7f53b4851727e3fd20cb66065570d2a99b0c4a4c367572c84fc08fb6918dfdfeb6b
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
`danger-packwerk` integrates [`packwerk`](https://github.com/Shopify/packwerk) with [`danger`](https://github.com/danger/danger) to provide inline comments in PRs related to boundaries in a Rails application.
|
4
4
|
|
5
|
-
## Installation
|
5
|
+
## Installation and Basic Usage
|
6
6
|
Step 1: Add this line to your `Gemfile` (to whatever group your CI uses, as it is not needed in production) and `bundle install`:
|
7
7
|
|
8
8
|
```ruby
|
@@ -13,41 +13,50 @@ Step 2: Add these to your `Dangerfile`:
|
|
13
13
|
|
14
14
|
```ruby
|
15
15
|
packwerk.check
|
16
|
-
|
16
|
+
package_todo_yml_changes.check
|
17
17
|
```
|
18
18
|
|
19
19
|
That's it for basic usage!
|
20
20
|
|
21
|
-
## Usage
|
21
|
+
## Advanced Usage
|
22
22
|
|
23
23
|
There are currently two danger checks that ship with `danger-packwerk`:
|
24
24
|
1) One that runs `bin/packwerk check` and leaves inline comments in source code on new violations
|
25
|
-
2) One that looks at changes to `
|
25
|
+
2) One that looks at changes to `package_todo.yml` files and leaves inline comments on added violations.
|
26
26
|
|
27
27
|
In upcoming iterations, we will include other danger checks, including:
|
28
28
|
1) A danger check that detects changes to `package.yml` files and posts user-configurable messages on the `package.yml` files that are modified.
|
29
29
|
2) A danger check that detects changes to `packwerk.yml` files and allows you to specify the action taken when that happens.
|
30
30
|
|
31
31
|
## packwerk.check
|
32
|
-

|
33
|
+

|
33
34
|
|
34
|
-
Without any configuration, `packwerk.check` should just work. By default, it will post a maximum of 15 messages in a PR
|
35
|
+
Without any configuration, `packwerk.check` should just work. By default, it will post a maximum of 15 messages in a PR and it will not fail the build.
|
35
36
|
|
36
37
|
`packwerk.check` can be configured to in the following ways:
|
37
38
|
|
38
39
|
### Change the message that displays in the markdown
|
39
|
-
|
40
|
+
To customize the message in the GitHub comment, pass in `offenses_formatter` to `packwerk.check` in your `Dangerfile`. Here's a simple example:
|
40
41
|
```ruby
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
class MyFormatter
|
43
|
+
extend T::Sig
|
44
|
+
include DangerPackwerk::Check::OffensesFormatter
|
45
|
+
# Packwerk::ReferenceOffense: https://github.com/Shopify/packwerk/blob/main/lib/packwerk/reference_offense.rb
|
46
|
+
sig { override.params(offenses: T::Array[Packwerk::ReferenceOffense], repo_link: String, org_name: String).returns(String) }
|
47
|
+
def format_offenses(offenses, repo_link, org_name)
|
48
|
+
# your logic here
|
45
49
|
end
|
46
|
-
|
50
|
+
end
|
51
|
+
|
52
|
+
packwerk.check(offenses_formatter: MyFormatter.new)
|
47
53
|
```
|
48
54
|
|
49
|
-
|
50
|
-
|
55
|
+
If you'd like to keep the default messaging but add some context customized to your organization, you can pass that in as follows:
|
56
|
+
```ruby
|
57
|
+
custom_help_message = "Need help? Check out our internal docs [here](www.example.com)"
|
58
|
+
packwerk.check(offenses_formatter: DangerPackwerk::Check::DefaultFormatter.new(custom_help_message: custom_help_message))
|
59
|
+
```
|
51
60
|
|
52
61
|
### Fail the build on new violations
|
53
62
|
Simply pass in `fail_build: true` into `check`, as such:
|
@@ -75,42 +84,48 @@ packwerk.check(
|
|
75
84
|
)
|
76
85
|
```
|
77
86
|
|
78
|
-
##
|
79
|
-

|
80
89
|
|
81
|
-
Without any configuration, `
|
90
|
+
Without any configuration, `package_todo_yml_changes.check` should just work. By default, it will post a maximum of 15 messages in a PR, using default messaging defined within this gem.
|
82
91
|
|
83
|
-
`
|
92
|
+
`package_todo_yml_changes.check` can be configured to in the following ways:
|
84
93
|
|
85
94
|
### Change the message that displays in the markdown
|
86
|
-
|
95
|
+
To customize the message in the GitHub comment, pass in `offenses_formatter` to `package_todo_yml_changes.check` in your `Dangerfile`. Here's a simple example:
|
87
96
|
```ruby
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
97
|
+
class MyFormatter
|
98
|
+
extend T::Sig
|
99
|
+
include DangerPackwerk::Update::OffensesFormatter
|
100
|
+
# DangerPackwerk::BasicReferenceOffense
|
101
|
+
sig { override.params(offenses: T::Array[DangerPackwerk::BasicReferenceOffense], repo_link: String, org_name: String).returns(String) }
|
102
|
+
def format_offenses(offenses, repo_link, org_name)
|
103
|
+
# your logic here
|
92
104
|
end
|
93
|
-
|
105
|
+
end
|
106
|
+
|
107
|
+
package_todo_yml_changes.check(offenses_formatter: MyFormatter.new)
|
94
108
|
```
|
95
109
|
|
96
|
-
|
97
|
-
|
98
|
-
Need help?
|
99
|
-
|
110
|
+
If you'd like to keep the default messaging but add some context customized to your organization, you can pass that in as follows:
|
111
|
+
```ruby
|
112
|
+
custom_help_message = "Need help? Check out our internal docs [here](www.example.com)"
|
113
|
+
package_todo_yml_changes.check(offenses_formatter: DangerPackwerk::Update::DefaultFormatter.new(custom_help_message: custom_help_message))
|
114
|
+
```
|
100
115
|
|
101
116
|
### Change the max number of comments that will display
|
102
117
|
If you do not change this, the default max is 15. More information about why we chose this number in the source code.
|
103
118
|
```ruby
|
104
|
-
|
119
|
+
package_todo_yml_changes.check(max_comments: 3)
|
105
120
|
```
|
106
121
|
|
107
122
|
### Do something extra before we leave comments
|
108
123
|
Maybe you want to notify slack or do something else before we leave comments.
|
109
124
|
|
110
125
|
```ruby
|
111
|
-
|
112
|
-
# violation_diff is a DangerPackwerk::ViolationDiff and
|
113
|
-
before_comment: -> (violation_diff,
|
126
|
+
package_todo_yml_changes.check(
|
127
|
+
# violation_diff is a DangerPackwerk::ViolationDiff and changed_package_todo_ymls is a T::Array[String]
|
128
|
+
before_comment: -> (violation_diff, changed_package_todo_ymls) do
|
114
129
|
# Notify slack or otherwise do something extra!
|
115
130
|
end
|
116
131
|
)
|
@@ -4,8 +4,8 @@ module DangerPackwerk
|
|
4
4
|
#
|
5
5
|
# We call this BasicReferenceOffense as it is intended to have a subset of the interface of Packwerk::ReferenceOffense, located here:
|
6
6
|
# https://github.com/Shopify/packwerk/blob/a22862b59f7760abf22bda6804d41a52d05301d8/lib/packwerk/reference_offense.rb#L1
|
7
|
-
# However, we cannot actually construct a Packwerk::ReferenceOffense from `
|
8
|
-
# constructed in packwerk when packwerk parses the AST and actually outputs `
|
7
|
+
# However, we cannot actually construct a Packwerk::ReferenceOffense from `package_todo.yml` alone, since they are normally
|
8
|
+
# constructed in packwerk when packwerk parses the AST and actually outputs `package_todo.yml`, a process in which some information,
|
9
9
|
# such as the location where the constant is defined, is lost.
|
10
10
|
#
|
11
11
|
class BasicReferenceOffense < T::Struct
|
@@ -41,21 +41,21 @@ module DangerPackwerk
|
|
41
41
|
const :type, String
|
42
42
|
const :file_location, Location
|
43
43
|
|
44
|
-
sig { params(
|
45
|
-
def self.from(
|
46
|
-
|
44
|
+
sig { params(package_todo_yml: String).returns(T::Array[BasicReferenceOffense]) }
|
45
|
+
def self.from(package_todo_yml)
|
46
|
+
package_todo_yml_pathname = Pathname.new(package_todo_yml)
|
47
47
|
|
48
|
-
from_package = ParsePackwerk.package_from_path(
|
48
|
+
from_package = ParsePackwerk.package_from_path(package_todo_yml_pathname)
|
49
49
|
from_package_name = from_package.name
|
50
|
-
violations = Private::
|
50
|
+
violations = Private::PackageTodo.from(package_todo_yml_pathname).violations
|
51
51
|
|
52
52
|
# See the larger comment below for more information on why we need this information.
|
53
53
|
# This is a small optimization that lets us find the location of referenced files within
|
54
|
-
# a `
|
54
|
+
# a `package_todo.yml` file. Getting this now allows us to avoid reading through the file
|
55
55
|
# once for every referenced file in the inner loop below.
|
56
56
|
file_reference_to_line_number_index = T.let({}, T::Hash[String, T::Array[Integer]])
|
57
57
|
all_referenced_files = violations.flat_map(&:files).uniq
|
58
|
-
|
58
|
+
package_todo_yml_pathname.readlines.each_with_index do |line, index|
|
59
59
|
# We can use `find` here to exit early since each line will include one path that is unique to that file.
|
60
60
|
# Paths should not be substrings of each other, since they are all paths relative to the root.
|
61
61
|
file_on_line = all_referenced_files.find { |file| line.include?(file) }
|
@@ -69,24 +69,24 @@ module DangerPackwerk
|
|
69
69
|
violations.flat_map do |violation|
|
70
70
|
#
|
71
71
|
# We identify two locations associated with this violation.
|
72
|
-
# First, we find the reference to the constant within the `
|
73
|
-
# We know that each constant reference can occur only once per `
|
72
|
+
# First, we find the reference to the constant within the `package_todo.yml` file.
|
73
|
+
# We know that each constant reference can occur only once per `package_todo.yml` file
|
74
74
|
# The reason for this is that we know that only one file in the codebase can define a constant, and packwerk's constant_resolver will actually
|
75
75
|
# raise if this assumption is not true: https://github.com/Shopify/constant_resolver/blob/e78af0c8d5782b06292c068cfe4176e016c51b34/lib/constant_resolver.rb#L74
|
76
76
|
#
|
77
|
-
# Second, we find the reference to the specific file that references the constant within the `
|
78
|
-
# This can occur multiple times per `
|
77
|
+
# Second, we find the reference to the specific file that references the constant within the `package_todo.yml` file.
|
78
|
+
# This can occur multiple times per `package_todo.yml` file, but we know that the very first reference to the file after the class name key will be the one we care
|
79
79
|
# about, so we take the first instance that occurs after the class is listed.
|
80
80
|
#
|
81
|
-
# Note though that since one constant reference in a `
|
81
|
+
# Note though that since one constant reference in a `package_todo.yml` can be both a privacy and a dependency violation AND it can occur in many files,
|
82
82
|
# we need to group them. That is -- if `MyPrivateConstant` is both a dependency and a privacy violation AND it occurs in 10 files, that would represent 20 violations.
|
83
83
|
# Therefore we will group all of those 20 into one message to the user rather than providing 20 messages.
|
84
84
|
#
|
85
|
-
_line, class_name_line_number =
|
85
|
+
_line, class_name_line_number = package_todo_yml_pathname.readlines.each_with_index.find do |line, _index|
|
86
86
|
# If you have a class `::MyClass`, then you can get a false match if another constant in the file
|
87
87
|
# is named `MyOtherClass::MyClassThing`. Therefore we include quotes in our match to ensure that we match
|
88
88
|
# the constant and only the constant.
|
89
|
-
# Right now `packwerk` `
|
89
|
+
# Right now `packwerk` `package_todo.yml` files typically use double quotes, but sometimes folks linters change this to single quotes.
|
90
90
|
# To be defensive, we match against either.
|
91
91
|
class_name_with_quote_boundaries = /["|']#{violation.class_name}["|']:/
|
92
92
|
line.match?(class_name_with_quote_boundaries)
|
@@ -94,16 +94,16 @@ module DangerPackwerk
|
|
94
94
|
|
95
95
|
if class_name_line_number.nil?
|
96
96
|
debug_info = { class_name: violation.class_name, to_package_name: violation.to_package_name, type: violation.type }
|
97
|
-
raise "Unable to find reference to violation #{debug_info} in #{
|
97
|
+
raise "Unable to find reference to violation #{debug_info} in #{package_todo_yml}"
|
98
98
|
end
|
99
99
|
|
100
100
|
violation.files.map do |file|
|
101
101
|
file_line_numbers = file_reference_to_line_number_index.fetch(file, [])
|
102
102
|
file_line_number = file_line_numbers.select { |index| index > class_name_line_number }.min
|
103
|
-
raise "Unable to find reference to violation #{{ file: file, to_package_name: violation.to_package_name, type: violation.type }} in #{
|
103
|
+
raise "Unable to find reference to violation #{{ file: file, to_package_name: violation.to_package_name, type: violation.type }} in #{package_todo_yml}" if file_line_number.nil?
|
104
104
|
|
105
105
|
# We add one to the line number since `each_with_index` is zero-based indexed but Github line numbers are one-based indexed
|
106
|
-
file_location = Location.new(file:
|
106
|
+
file_location = Location.new(file: package_todo_yml, line_number: file_line_number + 1)
|
107
107
|
|
108
108
|
BasicReferenceOffense.new(
|
109
109
|
class_name: violation.class_name,
|
@@ -45,7 +45,7 @@ module DangerPackwerk
|
|
45
45
|
team_to_work_with = constant_source_package_ownership_info.owning_team ? constant_source_package_ownership_info.markdown_link_to_github_members_no_tag : 'the pack owner'
|
46
46
|
privacy_violation_message = "- Does API in #{constant_source_package.name}/public support this use case?\n - If not, can we work with #{team_to_work_with} to create and use a public API?\n - If `#{constant_name}` should already be public, try `bin/packs make_public #{constant_location}`."
|
47
47
|
|
48
|
-
if violation_types.include?(
|
48
|
+
if violation_types.include?(::DangerPackwerk::DEPENDENCY_VIOLATION_TYPE) && violation_types.include?(::DangerPackwerk::PRIVACY_VIOLATION_TYPE)
|
49
49
|
<<~MESSAGE
|
50
50
|
**Packwerk Violation**
|
51
51
|
- Type: Privacy :lock: + Dependency :knot:
|
@@ -65,7 +65,7 @@ module DangerPackwerk
|
|
65
65
|
|
66
66
|
_#{@custom_help_message}_
|
67
67
|
MESSAGE
|
68
|
-
elsif violation_types.include?(
|
68
|
+
elsif violation_types.include?(::DangerPackwerk::DEPENDENCY_VIOLATION_TYPE)
|
69
69
|
<<~MESSAGE
|
70
70
|
**Packwerk Violation**
|
71
71
|
- Type: Dependency :knot:
|
@@ -84,7 +84,7 @@ module DangerPackwerk
|
|
84
84
|
|
85
85
|
_#{@custom_help_message}_
|
86
86
|
MESSAGE
|
87
|
-
else # violation_types.include?(
|
87
|
+
else # violation_types.include?(::DangerPackwerk::PRIVACY_VIOLATION_TYPE)
|
88
88
|
<<~MESSAGE
|
89
89
|
**Packwerk Violation**
|
90
90
|
- Type: Privacy :lock:
|
@@ -9,7 +9,7 @@ require 'danger-packwerk/violation_diff'
|
|
9
9
|
require 'open3'
|
10
10
|
|
11
11
|
module DangerPackwerk
|
12
|
-
class
|
12
|
+
class DangerPackageTodoYmlChanges < Danger::Plugin
|
13
13
|
extend T::Sig
|
14
14
|
|
15
15
|
# We choose 5 here because violation additions tend to fall into a bimodal distribution, where most PRs only add a handful (<10) of new violations,
|
@@ -17,8 +17,8 @@ module DangerPackwerk
|
|
17
17
|
# Therefore we hope to capture the majority case of people making changes to code while not spamming PRs that do a big rename.
|
18
18
|
# We set a max (rather than unlimited) to avoid GitHub rate limiting and general spam if a PR does some sort of mass rename.
|
19
19
|
DEFAULT_MAX_COMMENTS = 5
|
20
|
-
BeforeComment = T.type_alias { T.proc.params(violation_diff: ViolationDiff,
|
21
|
-
DEFAULT_BEFORE_COMMENT = T.let(->(violation_diff,
|
20
|
+
BeforeComment = T.type_alias { T.proc.params(violation_diff: ViolationDiff, changed_package_todo_ymls: T::Array[String]).void }
|
21
|
+
DEFAULT_BEFORE_COMMENT = T.let(->(violation_diff, changed_package_todo_ymls) {}, BeforeComment)
|
22
22
|
|
23
23
|
sig do
|
24
24
|
params(
|
@@ -36,13 +36,13 @@ module DangerPackwerk
|
|
36
36
|
repo_link = github.pr_json[:base][:repo][:html_url]
|
37
37
|
org_name = github.pr_json[:base][:repo][:owner][:login]
|
38
38
|
|
39
|
-
|
39
|
+
changed_package_todo_ymls = (git.modified_files + git.added_files + git.deleted_files).grep(PACKAGE_TODO_PATTERN)
|
40
40
|
|
41
41
|
violation_diff = get_violation_diff
|
42
42
|
|
43
43
|
before_comment.call(
|
44
44
|
violation_diff,
|
45
|
-
|
45
|
+
changed_package_todo_ymls.to_a
|
46
46
|
)
|
47
47
|
|
48
48
|
current_comment_count = 0
|
@@ -67,16 +67,16 @@ module DangerPackwerk
|
|
67
67
|
added_violations = T.let([], T::Array[BasicReferenceOffense])
|
68
68
|
removed_violations = T.let([], T::Array[BasicReferenceOffense])
|
69
69
|
|
70
|
-
git.added_files.grep(
|
70
|
+
git.added_files.grep(PACKAGE_TODO_PATTERN).each do |added_package_todo_yml_file|
|
71
71
|
# Since the file is added, we know on the base commit there are no violations related to this pack,
|
72
72
|
# and that all violations from this file are new
|
73
|
-
added_violations += BasicReferenceOffense.from(
|
73
|
+
added_violations += BasicReferenceOffense.from(added_package_todo_yml_file)
|
74
74
|
end
|
75
75
|
|
76
|
-
git.deleted_files.grep(
|
76
|
+
git.deleted_files.grep(PACKAGE_TODO_PATTERN).each do |deleted_package_todo_yml_file|
|
77
77
|
# Since the file is deleted, we know on the HEAD commit there are no violations related to this pack,
|
78
78
|
# and that all violations from this file are deleted
|
79
|
-
deleted_violations = get_violations_before_patch_for(
|
79
|
+
deleted_violations = get_violations_before_patch_for(deleted_package_todo_yml_file)
|
80
80
|
removed_violations += deleted_violations
|
81
81
|
end
|
82
82
|
|
@@ -84,13 +84,13 @@ module DangerPackwerk
|
|
84
84
|
renamed_files_before = git.renamed_files.map { |before_after_file| before_after_file[:before] }
|
85
85
|
renamed_files_after = git.renamed_files.map { |before_after_file| before_after_file[:after] }
|
86
86
|
|
87
|
-
git.modified_files.grep(
|
88
|
-
# We skip over modified files if one of the modified files is a renamed `
|
87
|
+
git.modified_files.grep(PACKAGE_TODO_PATTERN).each do |modified_package_todo_yml_file|
|
88
|
+
# We skip over modified files if one of the modified files is a renamed `package_todo.yml` file.
|
89
89
|
# This allows us to rename packs while ignoring "new violations" in those renamed packs.
|
90
|
-
next if renamed_files_before.include?(
|
90
|
+
next if renamed_files_before.include?(modified_package_todo_yml_file)
|
91
91
|
|
92
|
-
head_commit_violations = BasicReferenceOffense.from(
|
93
|
-
base_commit_violations = get_violations_before_patch_for(
|
92
|
+
head_commit_violations = BasicReferenceOffense.from(modified_package_todo_yml_file)
|
93
|
+
base_commit_violations = get_violations_before_patch_for(modified_package_todo_yml_file)
|
94
94
|
added_violations += head_commit_violations - base_commit_violations
|
95
95
|
removed_violations += base_commit_violations - head_commit_violations
|
96
96
|
end
|
@@ -128,9 +128,9 @@ module DangerPackwerk
|
|
128
128
|
|
129
129
|
private
|
130
130
|
|
131
|
-
sig { params(
|
132
|
-
def get_violations_before_patch_for(
|
133
|
-
# The strategy to get the violations before this PR is to reverse the patch on each `
|
131
|
+
sig { params(package_todo_yml_file: String).returns(T::Array[BasicReferenceOffense]) }
|
132
|
+
def get_violations_before_patch_for(package_todo_yml_file)
|
133
|
+
# The strategy to get the violations before this PR is to reverse the patch on each `package_todo.yml`.
|
134
134
|
# A previous strategy attempted to use `git merge-base --fork-point`, but there are many situations where it returns
|
135
135
|
# empty values. That strategy is fickle because it depends on the state of the `reflog` within the CI suite, which appears
|
136
136
|
# to not be reliable to depend on.
|
@@ -139,24 +139,24 @@ module DangerPackwerk
|
|
139
139
|
# the PR without needing to use git commands that interpret the branch history based on local git history.
|
140
140
|
#
|
141
141
|
# We apply the patch to the original file so that we can seamlessly reverse the patch applied to that file (since patches are coupled to
|
142
|
-
# the files they modify). After parsing the violations from that `
|
142
|
+
# the files they modify). After parsing the violations from that `package_todo.yml` file with the patch reversed,
|
143
143
|
# we use a temporary copy of the original file to rewrite to it with the original contents.
|
144
144
|
# Note that practically speaking, we don't need to rewrite the original contents (since we already fetched the
|
145
145
|
# original contents above and the CI file system should be ephemeral). However, we do this anyways in case we later change these
|
146
146
|
# assumptions, or another client's environment is different and expects these files not to be mutated.
|
147
147
|
|
148
148
|
# Keep track of the original file contents. If the original file has been deleted, then we delete the file after inverting the patch at the end, rather than rewriting it.
|
149
|
-
|
149
|
+
package_todo_yml_file_copy = (File.read(package_todo_yml_file) if File.exist?(package_todo_yml_file))
|
150
150
|
|
151
151
|
Tempfile.create do |patch_file|
|
152
|
-
# Normally we'd use `git.diff_for_file(
|
152
|
+
# Normally we'd use `git.diff_for_file(package_todo_yml_file).patch` here, but there is a bug where it does not work for deleted files yet.
|
153
153
|
# I have a fix for that here: https://github.com/danger/danger/pull/1357
|
154
154
|
# Until that lands, I'm just using the underlying implementation of that method to get the diff for a file.
|
155
155
|
# Note that I might want to use a safe escape operator, `&.patch` and return gracefully if the patch cannot be found.
|
156
156
|
# However I'd be interested in why that ever happens, so for now going to proceed as is.
|
157
157
|
# (Note that better yet we'd have observability into these so I can just log under those circumstances rather than surfacing an error to the user,
|
158
158
|
# but we don't have that quite yet.)
|
159
|
-
patch_for_file = git.diff[
|
159
|
+
patch_for_file = git.diff[package_todo_yml_file].patch
|
160
160
|
# This appears to be a known issue that patches require new lines at the end. It seems like this is an issue with Danger that
|
161
161
|
# it gives us a patch without a newline.
|
162
162
|
# https://stackoverflow.com/questions/18142870/git-error-fatal-corrupt-patch-at-line-36
|
@@ -165,13 +165,13 @@ module DangerPackwerk
|
|
165
165
|
# https://git-scm.com/docs/git-apply
|
166
166
|
_stdout, _stderr, _status = Open3.capture3("git apply --reverse #{patch_file.path}")
|
167
167
|
# https://www.rubyguides.com/2019/05/ruby-tempfile/
|
168
|
-
BasicReferenceOffense.from(
|
168
|
+
BasicReferenceOffense.from(package_todo_yml_file)
|
169
169
|
end
|
170
170
|
ensure
|
171
|
-
if
|
172
|
-
File.write(
|
171
|
+
if package_todo_yml_file_copy
|
172
|
+
File.write(package_todo_yml_file, package_todo_yml_file_copy)
|
173
173
|
else
|
174
|
-
File.delete(
|
174
|
+
File.delete(package_todo_yml_file)
|
175
175
|
end
|
176
176
|
end
|
177
177
|
end
|
@@ -60,6 +60,16 @@ module DangerPackwerk
|
|
60
60
|
def show_stale_violations(offense_collection, for_files)
|
61
61
|
''
|
62
62
|
end
|
63
|
+
|
64
|
+
sig { override.params(strict_mode_violations: T::Array[::Packwerk::ReferenceOffense]).returns(::String) }
|
65
|
+
def show_strict_mode_violations(strict_mode_violations)
|
66
|
+
''
|
67
|
+
end
|
68
|
+
|
69
|
+
sig { override.returns(::String) }
|
70
|
+
def identifier
|
71
|
+
'offenses_aggregator'
|
72
|
+
end
|
63
73
|
end
|
64
74
|
end
|
65
75
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module DangerPackwerk
|
4
4
|
module Private
|
5
5
|
#
|
6
|
-
# The `Violation` and `
|
6
|
+
# The `Violation` and `PackageTodo` classes come from Gusto's private `ParsePackwerk` gem.
|
7
7
|
# Until we decide to open source that gem, we inline these as a private implementation detail of `DangerPackwerk` for now.
|
8
8
|
#
|
9
9
|
class Violation < T::Struct
|
@@ -25,22 +25,22 @@ module DangerPackwerk
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
class
|
28
|
+
class PackageTodo < T::Struct
|
29
29
|
extend T::Sig
|
30
30
|
|
31
31
|
const :pathname, Pathname
|
32
32
|
const :violations, T::Array[Violation]
|
33
33
|
|
34
|
-
sig { params(pathname: Pathname).returns(
|
34
|
+
sig { params(pathname: Pathname).returns(PackageTodo) }
|
35
35
|
def self.from(pathname)
|
36
36
|
if pathname.exist?
|
37
|
-
|
37
|
+
package_todo_loaded_yml = YAML.load_file(pathname)
|
38
38
|
|
39
39
|
all_violations = []
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
symbol_usage =
|
40
|
+
package_todo_loaded_yml&.each_key do |to_package_name|
|
41
|
+
package_todo_per_package = package_todo_loaded_yml[to_package_name]
|
42
|
+
package_todo_per_package.each_key do |class_name|
|
43
|
+
symbol_usage = package_todo_per_package[class_name]
|
44
44
|
files = symbol_usage['files']
|
45
45
|
violations = symbol_usage['violations']
|
46
46
|
all_violations << Violation.new(type: 'dependency', to_package_name: to_package_name, class_name: class_name, files: files) if violations.include? 'dependency'
|
data/lib/danger-packwerk.rb
CHANGED
@@ -5,10 +5,12 @@
|
|
5
5
|
require 'sorbet-runtime'
|
6
6
|
|
7
7
|
module DangerPackwerk
|
8
|
-
|
8
|
+
PACKAGE_TODO_PATTERN = T.let(/.*?package_todo\.yml\z/.freeze, Regexp)
|
9
|
+
DEPENDENCY_VIOLATION_TYPE = 'dependency'
|
10
|
+
PRIVACY_VIOLATION_TYPE = 'privacy'
|
9
11
|
|
10
12
|
require 'danger-packwerk/danger_packwerk'
|
11
|
-
require 'danger-packwerk/
|
13
|
+
require 'danger-packwerk/danger_package_todo_yml_changes'
|
12
14
|
require 'danger-packwerk/check/offenses_formatter'
|
13
15
|
require 'danger-packwerk/check/default_formatter'
|
14
16
|
require 'danger-packwerk/update/offenses_formatter'
|