dependabot-common 0.239.0 → 0.241.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,24 +1,40 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
4
5
  require "dependabot/source"
5
6
 
6
7
  module Dependabot
7
8
  module MetadataFinders
8
9
  class Base
10
+ extend T::Sig
11
+ extend T::Helpers
12
+
9
13
  require "dependabot/metadata_finders/base/changelog_finder"
10
14
  require "dependabot/metadata_finders/base/release_finder"
11
15
  require "dependabot/metadata_finders/base/commits_finder"
12
16
 
13
- PACKAGE_MANAGERS_WITH_RELIABLE_DIRECTORIES = %w(npm_and_yarn pub).freeze
17
+ PACKAGE_MANAGERS_WITH_RELIABLE_DIRECTORIES = T.let(%w(npm_and_yarn pub).freeze, T::Array[String])
18
+
19
+ sig { returns(Dependabot::Dependency) }
20
+ attr_reader :dependency
14
21
 
15
- attr_reader :dependency, :credentials
22
+ sig { returns(T::Array[T::Hash[String, String]]) }
23
+ attr_reader :credentials
16
24
 
25
+ sig do
26
+ params(
27
+ dependency: Dependabot::Dependency,
28
+ credentials: T::Array[T::Hash[String, String]]
29
+ )
30
+ .void
31
+ end
17
32
  def initialize(dependency:, credentials:)
18
33
  @dependency = dependency
19
34
  @credentials = credentials
20
35
  end
21
36
 
37
+ sig { returns(T.nilable(String)) }
22
38
  def source_url
23
39
  if reliable_source_directory?
24
40
  source&.url_with_directory
@@ -27,106 +43,144 @@ module Dependabot
27
43
  end
28
44
  end
29
45
 
46
+ sig { returns(T.nilable(String)) }
30
47
  def homepage_url
31
48
  source_url
32
49
  end
33
50
 
51
+ sig { returns(T.nilable(String)) }
34
52
  def changelog_url
35
- @changelog_finder ||= ChangelogFinder.new(
36
- dependency: dependency,
37
- source: source,
38
- credentials: credentials,
39
- suggested_changelog_url: suggested_changelog_url
53
+ @changelog_finder ||= T.let(
54
+ ChangelogFinder.new(
55
+ dependency: dependency,
56
+ source: source,
57
+ credentials: credentials,
58
+ suggested_changelog_url: suggested_changelog_url
59
+ ),
60
+ T.nilable(ChangelogFinder)
40
61
  )
41
62
  @changelog_finder.changelog_url
42
63
  end
43
64
 
65
+ sig { returns(T.nilable(String)) }
44
66
  def changelog_text
45
- @changelog_finder ||= ChangelogFinder.new(
46
- dependency: dependency,
47
- source: source,
48
- credentials: credentials,
49
- suggested_changelog_url: suggested_changelog_url
67
+ @changelog_finder ||= T.let(
68
+ ChangelogFinder.new(
69
+ dependency: dependency,
70
+ source: source,
71
+ credentials: credentials,
72
+ suggested_changelog_url: suggested_changelog_url
73
+ ),
74
+ T.nilable(ChangelogFinder)
50
75
  )
51
76
  @changelog_finder.changelog_text
52
77
  end
53
78
 
79
+ sig { returns(T.nilable(String)) }
54
80
  def upgrade_guide_url
55
- @changelog_finder ||= ChangelogFinder.new(
56
- dependency: dependency,
57
- source: source,
58
- credentials: credentials,
59
- suggested_changelog_url: suggested_changelog_url
81
+ @changelog_finder ||= T.let(
82
+ ChangelogFinder.new(
83
+ dependency: dependency,
84
+ source: source,
85
+ credentials: credentials,
86
+ suggested_changelog_url: suggested_changelog_url
87
+ ),
88
+ T.nilable(ChangelogFinder)
60
89
  )
61
90
  @changelog_finder.upgrade_guide_url
62
91
  end
63
92
 
93
+ sig { returns(T.nilable(String)) }
64
94
  def upgrade_guide_text
65
- @changelog_finder ||= ChangelogFinder.new(
66
- dependency: dependency,
67
- source: source,
68
- credentials: credentials,
69
- suggested_changelog_url: suggested_changelog_url
95
+ @changelog_finder ||= T.let(
96
+ ChangelogFinder.new(
97
+ dependency: dependency,
98
+ source: source,
99
+ credentials: credentials,
100
+ suggested_changelog_url: suggested_changelog_url
101
+ ),
102
+ T.nilable(ChangelogFinder)
70
103
  )
71
104
  @changelog_finder.upgrade_guide_text
72
105
  end
73
106
 
107
+ sig { returns(T.nilable(String)) }
74
108
  def releases_url
75
- @release_finder ||= ReleaseFinder.new(
76
- dependency: dependency,
77
- source: source,
78
- credentials: credentials
109
+ @release_finder ||= T.let(
110
+ ReleaseFinder.new(
111
+ dependency: dependency,
112
+ source: source,
113
+ credentials: credentials
114
+ ),
115
+ T.nilable(ReleaseFinder)
79
116
  )
80
117
  @release_finder.releases_url
81
118
  end
82
119
 
120
+ sig { returns(T.nilable(String)) }
83
121
  def releases_text
84
- @release_finder ||= ReleaseFinder.new(
85
- dependency: dependency,
86
- source: source,
87
- credentials: credentials
122
+ @release_finder ||= T.let(
123
+ ReleaseFinder.new(
124
+ dependency: dependency,
125
+ source: source,
126
+ credentials: credentials
127
+ ),
128
+ T.nilable(ReleaseFinder)
88
129
  )
89
130
  @release_finder.releases_text
90
131
  end
91
132
 
133
+ sig { returns(T.nilable(String)) }
92
134
  def commits_url
93
- @commits_finder ||= CommitsFinder.new(
94
- dependency: dependency,
95
- source: source,
96
- credentials: credentials
135
+ @commits_finder ||= T.let(
136
+ CommitsFinder.new(
137
+ dependency: dependency,
138
+ source: source,
139
+ credentials: credentials
140
+ ),
141
+ T.nilable(CommitsFinder)
97
142
  )
98
143
  @commits_finder.commits_url
99
144
  end
100
145
 
146
+ sig { returns(T::Array[T::Hash[Symbol, String]]) }
101
147
  def commits
102
- @commits_finder ||= CommitsFinder.new(
103
- dependency: dependency,
104
- source: source,
105
- credentials: credentials
148
+ @commits_finder ||= T.let(
149
+ CommitsFinder.new(
150
+ dependency: dependency,
151
+ source: source,
152
+ credentials: credentials
153
+ ),
154
+ T.nilable(CommitsFinder)
106
155
  )
107
156
  @commits_finder.commits
108
157
  end
109
158
 
159
+ sig { overridable.returns(T.nilable(String)) }
110
160
  def maintainer_changes
111
161
  nil
112
162
  end
113
163
 
114
164
  private
115
165
 
166
+ sig { overridable.returns(T.nilable(String)) }
116
167
  def suggested_changelog_url
117
168
  nil
118
169
  end
119
170
 
171
+ sig { returns(T.nilable(Dependabot::Source)) }
120
172
  def source
121
173
  return @source if defined?(@source)
122
174
 
123
- @source = look_up_source
175
+ @source = T.let(look_up_source, T.nilable(Dependabot::Source))
124
176
  end
125
177
 
178
+ sig { overridable.returns(Dependabot::Source) }
126
179
  def look_up_source
127
180
  raise NotImplementedError
128
181
  end
129
182
 
183
+ sig { returns(T::Boolean) }
130
184
  def reliable_source_directory?
131
185
  MetadataFinders::Base::PACKAGE_MANAGERS_WITH_RELIABLE_DIRECTORIES
132
186
  .include?(dependency.package_manager)
@@ -48,6 +48,11 @@ module Dependabot
48
48
  @max_length = max_length
49
49
  end
50
50
 
51
+ sig { overridable.returns(String) }
52
+ def new_branch_name
53
+ raise NotImplementedError
54
+ end
55
+
51
56
  private
52
57
 
53
58
  sig { params(ref_name: String).returns(String) }
@@ -1,14 +1,30 @@
1
- # typed: true
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
4
5
  require "dependabot/pull_request_creator/branch_namer/base"
5
6
 
6
7
  module Dependabot
7
8
  class PullRequestCreator
8
9
  class BranchNamer
9
10
  class DependencyGroupStrategy < Base
10
- def initialize(dependencies:, files:, target_branch:, dependency_group:,
11
- separator: "/", prefix: "dependabot", max_length: nil, includes_security_fixes:)
11
+ extend T::Sig
12
+
13
+ sig do
14
+ params(
15
+ dependencies: T::Array[Dependabot::Dependency],
16
+ files: T::Array[Dependabot::DependencyFile],
17
+ target_branch: T.nilable(String),
18
+ dependency_group: Dependabot::DependencyGroup,
19
+ includes_security_fixes: T::Boolean,
20
+ separator: String,
21
+ prefix: String,
22
+ max_length: T.nilable(Integer)
23
+ )
24
+ .void
25
+ end
26
+ def initialize(dependencies:, files:, target_branch:, dependency_group:, includes_security_fixes:,
27
+ separator: "/", prefix: "dependabot", max_length: nil)
12
28
  super(
13
29
  dependencies: dependencies,
14
30
  files: files,
@@ -22,14 +38,17 @@ module Dependabot
22
38
  @includes_security_fixes = includes_security_fixes
23
39
  end
24
40
 
41
+ sig { override.returns(String) }
25
42
  def new_branch_name
26
43
  sanitize_branch_name(File.join(prefixes, group_name_with_dependency_digest))
27
44
  end
28
45
 
29
46
  private
30
47
 
48
+ sig { returns(Dependabot::DependencyGroup) }
31
49
  attr_reader :dependency_group
32
50
 
51
+ sig { returns(T::Array[String]) }
33
52
  def prefixes
34
53
  [
35
54
  prefix,
@@ -45,6 +64,7 @@ module Dependabot
45
64
  #
46
65
  # Let's append a short hash digest of the dependency changes so that we can
47
66
  # meet this guarantee.
67
+ sig { returns(String) }
48
68
  def group_name_with_dependency_digest
49
69
  if @includes_security_fixes
50
70
  "group-security-#{package_manager}-#{dependency_digest}"
@@ -53,16 +73,22 @@ module Dependabot
53
73
  end
54
74
  end
55
75
 
76
+ sig { returns(T.nilable(String)) }
56
77
  def dependency_digest
57
- @dependency_digest ||= Digest::MD5.hexdigest(dependencies.map do |dependency|
58
- "#{dependency.name}-#{dependency.removed? ? 'removed' : dependency.version}"
59
- end.sort.join(",")).slice(0, 10)
78
+ @dependency_digest ||= T.let(
79
+ Digest::MD5.hexdigest(dependencies.map do |dependency|
80
+ "#{dependency.name}-#{dependency.removed? ? 'removed' : dependency.version}"
81
+ end.sort.join(",")).slice(0, 10),
82
+ T.nilable(String)
83
+ )
60
84
  end
61
85
 
86
+ sig { returns(String) }
62
87
  def package_manager
63
88
  T.must(dependencies.first).package_manager
64
89
  end
65
90
 
91
+ sig { returns(String) }
66
92
  def directory
67
93
  T.must(files.first).directory.tr(" ", "-")
68
94
  end
@@ -1,7 +1,8 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "digest"
5
+ require "sorbet-runtime"
5
6
 
6
7
  require "dependabot/metadata_finders"
7
8
  require "dependabot/pull_request_creator/branch_namer/base"
@@ -10,30 +11,37 @@ module Dependabot
10
11
  class PullRequestCreator
11
12
  class BranchNamer
12
13
  class SoloStrategy < Base
14
+ extend T::Sig
15
+
16
+ sig { override.returns(String) }
13
17
  def new_branch_name
14
18
  @name ||=
15
- begin
16
- dependency_name_part =
17
- if dependencies.count > 1 && updating_a_property?
18
- property_name
19
- elsif dependencies.count > 1 && updating_a_dependency_set?
20
- dependency_set.fetch(:group)
21
- else
22
- dependencies
23
- .map(&:name)
24
- .join("-and-")
25
- .tr(":[]", "-")
26
- .tr("@", "")
27
- end
28
-
29
- "#{dependency_name_part}-#{branch_version_suffix}"
30
- end
19
+ T.let(
20
+ begin
21
+ dependency_name_part =
22
+ if dependencies.count > 1 && updating_a_property?
23
+ property_name
24
+ elsif dependencies.count > 1 && updating_a_dependency_set?
25
+ dependency_set.fetch(:group)
26
+ else
27
+ dependencies
28
+ .map(&:name)
29
+ .join("-and-")
30
+ .tr(":[]", "-")
31
+ .tr("@", "")
32
+ end
33
+
34
+ "#{dependency_name_part}-#{branch_version_suffix}"
35
+ end,
36
+ T.nilable(String)
37
+ )
31
38
 
32
39
  sanitize_branch_name(File.join(prefixes, @name))
33
40
  end
34
41
 
35
42
  private
36
43
 
44
+ sig { returns(T::Array[String]) }
37
45
  def prefixes
38
46
  [
39
47
  prefix,
@@ -43,46 +51,58 @@ module Dependabot
43
51
  ].compact
44
52
  end
45
53
 
54
+ sig { returns(String) }
46
55
  def package_manager
47
56
  T.must(dependencies.first).package_manager
48
57
  end
49
58
 
59
+ sig { returns(T::Boolean) }
50
60
  def updating_a_property?
51
61
  T.must(dependencies.first)
52
62
  .requirements
53
63
  .any? { |r| r.dig(:metadata, :property_name) }
54
64
  end
55
65
 
66
+ sig { returns(T::Boolean) }
56
67
  def updating_a_dependency_set?
57
68
  T.must(dependencies.first)
58
69
  .requirements
59
70
  .any? { |r| r.dig(:metadata, :dependency_set) }
60
71
  end
61
72
 
73
+ sig { returns(String) }
62
74
  def property_name
63
- @property_name ||= T.must(dependencies.first).requirements
64
- .find { |r| r.dig(:metadata, :property_name) }
65
- &.dig(:metadata, :property_name)
75
+ @property_name ||=
76
+ T.let(T.must(dependencies.first).requirements
77
+ .find { |r| r.dig(:metadata, :property_name) }
78
+ &.dig(:metadata, :property_name),
79
+ T.nilable(String))
66
80
 
67
81
  raise "No property name!" unless @property_name
68
82
 
69
83
  @property_name
70
84
  end
71
85
 
86
+ sig { returns(T::Hash[Symbol, String]) }
72
87
  def dependency_set
73
- @dependency_set ||= T.must(dependencies.first).requirements
74
- .find { |r| r.dig(:metadata, :dependency_set) }
75
- &.dig(:metadata, :dependency_set)
88
+ @dependency_set ||=
89
+ T.let(
90
+ T.must(dependencies.first).requirements
91
+ .find { |r| r.dig(:metadata, :dependency_set) }
92
+ &.dig(:metadata, :dependency_set),
93
+ T.nilable(T::Hash[String, String])
94
+ )
76
95
 
77
96
  raise "No dependency set!" unless @dependency_set
78
97
 
79
98
  @dependency_set
80
99
  end
81
100
 
101
+ sig { returns(T.nilable(String)) }
82
102
  def branch_version_suffix
83
- dep = dependencies.first
103
+ dep = T.must(dependencies.first)
84
104
 
85
- if T.must(dep).removed?
105
+ if dep.removed?
86
106
  "-removed"
87
107
  elsif library? && ref_changed?(dep) && new_ref(dep)
88
108
  new_ref(dep)
@@ -93,6 +113,7 @@ module Dependabot
93
113
  end
94
114
  end
95
115
 
116
+ sig { params(dependency: Dependabot::Dependency).returns(String) }
96
117
  def sanitized_requirement(dependency)
97
118
  new_library_requirement(dependency)
98
119
  .delete(" ")
@@ -111,13 +132,14 @@ module Dependabot
111
132
  .gsub(",", "-and-")
112
133
  end
113
134
 
135
+ sig { params(dependency: Dependabot::Dependency).returns(T.nilable(String)) }
114
136
  def new_version(dependency)
115
137
  # Version looks like a git SHA and we could be updating to a specific
116
138
  # ref in which case we return that otherwise we return a shorthand sha
117
- if dependency.version.match?(/^[0-9a-f]{40}$/)
139
+ if dependency.version&.match?(/^[0-9a-f]{40}$/)
118
140
  return new_ref(dependency) if ref_changed?(dependency) && new_ref(dependency)
119
141
 
120
- dependency.version[0..6]
142
+ T.must(dependency.version)[0..6]
121
143
  elsif dependency.version == dependency.previous_version &&
122
144
  package_manager == "docker"
123
145
  dependency.requirements
@@ -128,13 +150,15 @@ module Dependabot
128
150
  end
129
151
  end
130
152
 
153
+ sig { params(dependency: Dependabot::Dependency).returns(T.nilable(String)) }
131
154
  def previous_ref(dependency)
132
- previous_refs = dependency.previous_requirements.filter_map do |r|
155
+ previous_refs = T.must(dependency.previous_requirements).filter_map do |r|
133
156
  r.dig(:source, "ref") || r.dig(:source, :ref)
134
157
  end.uniq
135
158
  previous_refs.first if previous_refs.count == 1
136
159
  end
137
160
 
161
+ sig { params(dependency: Dependabot::Dependency).returns(T.nilable(String)) }
138
162
  def new_ref(dependency)
139
163
  new_refs = dependency.requirements.filter_map do |r|
140
164
  r.dig(:source, "ref") || r.dig(:source, :ref)
@@ -142,20 +166,22 @@ module Dependabot
142
166
  new_refs.first if new_refs.count == 1
143
167
  end
144
168
 
169
+ sig { params(dependency: Dependabot::Dependency).returns(T::Boolean) }
145
170
  def ref_changed?(dependency)
146
171
  # We could go from multiple previous refs (nil) to a single new ref
147
172
  previous_ref(dependency) != new_ref(dependency)
148
173
  end
149
174
 
175
+ sig { params(dependency: Dependabot::Dependency).returns(T.untyped) }
150
176
  def new_library_requirement(dependency)
151
177
  updated_reqs =
152
- dependency.requirements - dependency.previous_requirements
178
+ dependency.requirements - T.must(dependency.previous_requirements)
153
179
 
154
180
  gemspec =
155
181
  updated_reqs.find { |r| r[:file].match?(%r{^[^/]*\.gemspec$}) }
156
182
  return gemspec[:requirement] if gemspec
157
183
 
158
- updated_reqs.first[:requirement]
184
+ updated_reqs.first&.fetch(:requirement)
159
185
  end
160
186
 
161
187
  # TODO: Bring this in line with existing library checks that we do in the
@@ -163,12 +189,14 @@ module Dependabot
163
189
  # `requirements_update_strategy`.
164
190
  #
165
191
  # TODO re-use in MessageBuilder
192
+ sig { returns(T::Boolean) }
166
193
  def library?
167
194
  dependencies.any? { |d| !d.appears_in_lockfile? }
168
195
  end
169
196
 
197
+ sig { params(dependency: Dependabot::Dependency).returns(T::Boolean) }
170
198
  def requirements_changed?(dependency)
171
- (dependency.requirements - dependency.previous_requirements).any?
199
+ (dependency.requirements - T.must(dependency.previous_requirements)).any?
172
200
  end
173
201
  end
174
202
  end
@@ -1,7 +1,8 @@
1
- # typed: true
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "digest"
5
+ require "sorbet-runtime"
5
6
 
6
7
  require "dependabot/metadata_finders"
7
8
  require "dependabot/pull_request_creator"
@@ -11,9 +12,45 @@ require "dependabot/pull_request_creator/branch_namer/dependency_group_strategy"
11
12
  module Dependabot
12
13
  class PullRequestCreator
13
14
  class BranchNamer
14
- attr_reader :dependencies, :files, :target_branch, :separator, :prefix, :max_length, :dependency_group,
15
- :includes_security_fixes
15
+ extend T::Sig
16
16
 
17
+ sig { returns(T::Array[Dependabot::Dependency]) }
18
+ attr_reader :dependencies
19
+
20
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
21
+ attr_reader :files
22
+
23
+ sig { returns(T.nilable(String)) }
24
+ attr_reader :target_branch
25
+
26
+ sig { returns(String) }
27
+ attr_reader :separator
28
+
29
+ sig { returns(String) }
30
+ attr_reader :prefix
31
+
32
+ sig { returns(T.nilable(Integer)) }
33
+ attr_reader :max_length
34
+
35
+ sig { returns(T.nilable(Dependabot::DependencyGroup)) }
36
+ attr_reader :dependency_group
37
+
38
+ sig { returns(T::Boolean) }
39
+ attr_reader :includes_security_fixes
40
+
41
+ sig do
42
+ params(
43
+ dependencies: T::Array[Dependabot::Dependency],
44
+ files: T::Array[Dependabot::DependencyFile],
45
+ target_branch: T.nilable(String),
46
+ dependency_group: T.nilable(Dependabot::DependencyGroup),
47
+ separator: String,
48
+ prefix: String,
49
+ max_length: T.nilable(Integer),
50
+ includes_security_fixes: T::Boolean
51
+ )
52
+ .void
53
+ end
17
54
  def initialize(dependencies:, files:, target_branch:, dependency_group: nil,
18
55
  separator: "/", prefix: "dependabot", max_length: nil, includes_security_fixes: false)
19
56
  @dependencies = dependencies
@@ -26,14 +63,16 @@ module Dependabot
26
63
  @includes_security_fixes = includes_security_fixes
27
64
  end
28
65
 
66
+ sig { returns(String) }
29
67
  def new_branch_name
30
68
  strategy.new_branch_name
31
69
  end
32
70
 
33
71
  private
34
72
 
73
+ sig { returns(Dependabot::PullRequestCreator::BranchNamer::Base) }
35
74
  def strategy
36
- @strategy ||=
75
+ @strategy ||= T.let(
37
76
  if dependency_group.nil?
38
77
  SoloStrategy.new(
39
78
  dependencies: dependencies,
@@ -48,13 +87,15 @@ module Dependabot
48
87
  dependencies: dependencies,
49
88
  files: files,
50
89
  target_branch: target_branch,
51
- dependency_group: dependency_group,
90
+ dependency_group: T.must(dependency_group),
91
+ includes_security_fixes: includes_security_fixes,
52
92
  separator: separator,
53
93
  prefix: prefix,
54
- max_length: max_length,
55
- includes_security_fixes: includes_security_fixes
94
+ max_length: max_length
56
95
  )
57
- end
96
+ end,
97
+ T.nilable(Dependabot::PullRequestCreator::BranchNamer::Base)
98
+ )
58
99
  end
59
100
  end
60
101
  end
@@ -150,7 +150,7 @@ module Dependabot
150
150
  end
151
151
 
152
152
  def approvers_hash
153
- @approvers_hash ||= approvers&.transform_keys(&:to_sym) || {}
153
+ @approvers_hash ||= approvers || {}
154
154
  end
155
155
 
156
156
  def default_branch