dependabot-common 0.139.0 → 0.140.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de2abf02275016c9c8d0ecd543e0646e08aa6551edec39a6567d8d5ac53af14f
4
- data.tar.gz: 5c9e219a03dbdeee3c9d3c8adab6ea0db8bf0c7331749149c43ae846290cc481
3
+ metadata.gz: 41a832731ce83e798f434d6266bd6947f107b939be2594febf5ccd5651793c5e
4
+ data.tar.gz: a3c195255893ba76b999aba1f664fbbc4e8bb1447b0d8f3d35d770798e894b38
5
5
  SHA512:
6
- metadata.gz: 381cf5957178c14ca1654367bac15f3e9626320afead493c142790eb374a593efaa039c512a384c6b749fc8a8fe9956957532d61c7a8c006e65dfb00a6f51b48
7
- data.tar.gz: 1e76b8f2721fbc1ceb99a96d06a38d6b4ada860a9daed49e96857c39d1d44351fa4b796d4ce434a3aac9001519147de6add25c06261463d8e5a31bf29fa97bc7
6
+ metadata.gz: 11779b84b2bea46d8ad47f9ce0857cb8cf29359687c6908d950637ea60411dd85f4bb108c7728cecb49c237acdb09c86706ce873216ef3f363bb9e91bf93fcc2
7
+ data.tar.gz: 8007aac05e097eb667545988474c792ba86e48eda770e1725629d19307ee46198828189b36f1603f05d53bf3ec3e3bcf4751c0d172af3891fceb94b94b7bb72e
@@ -5,23 +5,33 @@ require "pathname"
5
5
  module Dependabot
6
6
  class DependencyFile
7
7
  attr_accessor :name, :content, :directory, :type, :support_file,
8
- :symlink_target, :content_encoding, :deleted
8
+ :symlink_target, :content_encoding, :operation
9
9
 
10
10
  class ContentEncoding
11
11
  UTF_8 = "utf-8"
12
12
  BASE64 = "base64"
13
13
  end
14
14
 
15
+ class Operation
16
+ UPDATE = "update"
17
+ CREATE = "create"
18
+ DELETE = "delete"
19
+ end
20
+
15
21
  def initialize(name:, content:, directory: "/", type: "file",
16
22
  support_file: false, symlink_target: nil,
17
- content_encoding: ContentEncoding::UTF_8, deleted: false)
23
+ content_encoding: ContentEncoding::UTF_8, deleted: false, operation: Operation::UPDATE)
18
24
  @name = name
19
25
  @content = content
20
26
  @directory = clean_directory(directory)
21
27
  @symlink_target = symlink_target
22
28
  @support_file = support_file
23
29
  @content_encoding = content_encoding
24
- @deleted = deleted
30
+ @operation = operation
31
+
32
+ # Make deleted override the operation. Deleted is kept when operation
33
+ # was introduced to keep compatibility with downstream dependants.
34
+ @operation = Operation::DELETE if deleted
25
35
 
26
36
  # Type is used *very* sparingly. It lets the git_modules updater know that
27
37
  # a "file" is actually a submodule, and lets our Go updaters know which
@@ -44,7 +54,8 @@ module Dependabot
44
54
  "type" => type,
45
55
  "support_file" => support_file,
46
56
  "content_encoding" => content_encoding,
47
- "deleted" => deleted
57
+ "deleted" => deleted,
58
+ "operation" => operation
48
59
  }
49
60
 
50
61
  details["symlink_target"] = symlink_target if symlink_target
@@ -75,8 +86,16 @@ module Dependabot
75
86
  @support_file
76
87
  end
77
88
 
89
+ def deleted
90
+ @operation == Operation::DELETE
91
+ end
92
+
93
+ def deleted=(deleted)
94
+ @operation = deleted ? Operation::DELETE : Operation::UPDATE
95
+ end
96
+
78
97
  def deleted?
79
- @deleted
98
+ deleted
80
99
  end
81
100
 
82
101
  def binary?
@@ -27,12 +27,20 @@ module Dependabot
27
27
  )
28
28
  changed_paths = status.split("\n").map { |l| l.split(" ") }
29
29
  changed_paths.map do |type, path|
30
- deleted = type == "D"
30
+ # The following types are possible to be returned:
31
+ # M = Modified = Default for DependencyFile
32
+ # D = Deleted
33
+ # ?? = Untracked = Created
34
+ operation = Dependabot::DependencyFile::Operation::UPDATE
35
+ operation = Dependabot::DependencyFile::Operation::DELETE if type == "D"
36
+ operation = Dependabot::DependencyFile::Operation::CREATE if type == "??"
31
37
  encoding = ""
32
- encoded_content = File.read(path) unless deleted
38
+ encoded_content = File.read(path) unless operation == Dependabot::DependencyFile::Operation::DELETE
33
39
  if binary_file?(path)
34
40
  encoding = Dependabot::DependencyFile::ContentEncoding::BASE64
35
- encoded_content = Base64.encode64(encoded_content) unless deleted
41
+ if operation != Dependabot::DependencyFile::Operation::DELETE
42
+ encoded_content = Base64.encode64(encoded_content)
43
+ end
36
44
  end
37
45
 
38
46
  project_root =
@@ -44,7 +52,7 @@ module Dependabot
44
52
  name: file_path.to_s,
45
53
  content: encoded_content,
46
54
  directory: base_directory,
47
- deleted: deleted,
55
+ operation: operation,
48
56
  content_encoding: encoding
49
57
  )
50
58
  end
@@ -177,7 +177,7 @@ module Dependabot
177
177
  sha: file.content
178
178
  }
179
179
  else
180
- content = if file.deleted?
180
+ content = if file.operation == Dependabot::DependencyFile::Operation::DELETE
181
181
  { sha: nil }
182
182
  elsif file.binary?
183
183
  sha = github_client_for_source.create_blob(
@@ -91,23 +91,26 @@ module Dependabot
91
91
  )
92
92
  end
93
93
 
94
+ # @param [DependencyFile] file
95
+ def file_action(file)
96
+ if file.operation == Dependabot::DependencyFile::Operation::DELETE
97
+ "delete"
98
+ elsif file.operation == Dependabot::DependencyFile::Operation::CREATE
99
+ "create"
100
+ else
101
+ "update"
102
+ end
103
+ end
104
+
94
105
  def create_commit
95
106
  return create_submodule_update_commit if files.count == 1 && files.first.type == "submodule"
96
107
 
97
108
  actions = files.map do |file|
98
- if file.type == "symlink"
99
- {
100
- action: "update",
101
- file_path: file.symlink_target,
102
- content: file.content
103
- }
104
- else
105
- {
106
- action: "update",
107
- file_path: file.path,
108
- content: file.content
109
- }
110
- end
109
+ {
110
+ action: file_action(file),
111
+ file_path: file.type == "symlink" ? file.symlink_target : file.path,
112
+ content: file.content
113
+ }
111
114
  end
112
115
 
113
116
  gitlab_client_for_source.create_commit(
@@ -15,6 +15,8 @@ module Dependabot
15
15
  (?:issue|pull)s?/(?<number>\d+)
16
16
  }x.freeze
17
17
  MENTION_REGEX = %r{(?<![A-Za-z0-9`~])@#{GITHUB_USERNAME}/?}.freeze
18
+ # regex to match a team mention on github
19
+ TEAM_MENTION_REGEX = %r{(?<![A-Za-z0-9`~])@(?<org>#{GITHUB_USERNAME})/(?<team>#{GITHUB_USERNAME})/?}.freeze
18
20
  # End of string
19
21
  EOS_REGEX = /\z/.freeze
20
22
  COMMONMARKER_OPTIONS = %i(
@@ -35,8 +37,10 @@ module Dependabot
35
37
  text, :LIBERAL_HTML_TAG, COMMONMARKER_EXTENSIONS
36
38
  )
37
39
 
40
+ sanitize_team_mentions(doc)
38
41
  sanitize_mentions(doc)
39
42
  sanitize_links(doc)
43
+
40
44
  mode = unsafe ? :UNSAFE : :DEFAULT
41
45
  doc.to_html(([mode] + COMMONMARKER_OPTIONS), COMMONMARKER_EXTENSIONS)
42
46
  end
@@ -62,6 +66,26 @@ module Dependabot
62
66
  end
63
67
  end
64
68
 
69
+ # When we come across something that looks like a team mention (e.g. @dependabot/reviewers),
70
+ # we replace it with a text node.
71
+ # This is because there are ecosystems that have packages that follow the same pattern
72
+ # (e.g. @angular/angular-cli), and we don't want to create an invalid link, since
73
+ # team mentions link to `https://github.com/org/:organization_name/teams/:team_name`.
74
+ def sanitize_team_mentions(doc)
75
+ doc.walk do |node|
76
+ if node.type == :text &&
77
+ node.string_content.match?(TEAM_MENTION_REGEX)
78
+
79
+ nodes = build_team_mention_nodes(node.string_content)
80
+
81
+ nodes.each do |n|
82
+ node.insert_before(n)
83
+ end
84
+ node.delete
85
+ end
86
+ end
87
+ end
88
+
65
89
  def sanitize_links(doc)
66
90
  doc.walk do |node|
67
91
  if node.type == :link && node.url.match?(GITHUB_REF_REGEX)
@@ -87,7 +111,7 @@ module Dependabot
87
111
 
88
112
  def replace_github_host(text)
89
113
  text.gsub(
90
- "github.com", github_redirection_service || "github.com"
114
+ /(www\.)?github.com/, github_redirection_service || "github.com"
91
115
  )
92
116
  end
93
117
 
@@ -117,6 +141,30 @@ module Dependabot
117
141
  nodes
118
142
  end
119
143
 
144
+ def build_team_mention_nodes(text)
145
+ nodes = []
146
+
147
+ scan = StringScanner.new(text)
148
+ until scan.eos?
149
+ line = scan.scan_until(TEAM_MENTION_REGEX) ||
150
+ scan.scan_until(EOS_REGEX)
151
+ line_match = line.match(TEAM_MENTION_REGEX)
152
+ mention = line_match&.to_s
153
+ text_node = CommonMarker::Node.new(:text)
154
+
155
+ if mention
156
+ text_node.string_content = line_match.pre_match
157
+ nodes << text_node
158
+ nodes += build_mention_link_text_nodes(mention.to_s)
159
+ else
160
+ text_node.string_content = line
161
+ nodes << text_node
162
+ end
163
+ end
164
+
165
+ nodes
166
+ end
167
+
120
168
  def build_mention_link_text_nodes(text)
121
169
  code_node = CommonMarker::Node.new(:code)
122
170
  code_node.string_content = insert_zero_width_space_in_mention(text)
@@ -132,7 +132,7 @@ module Dependabot
132
132
  sha: file.content
133
133
  }
134
134
  else
135
- content = if file.deleted?
135
+ content = if file.operation == Dependabot::DependencyFile::Operation::DELETE
136
136
  { sha: nil }
137
137
  elsif file.binary?
138
138
  sha = github_client_for_source.create_blob(
@@ -62,10 +62,21 @@ module Dependabot
62
62
  gitlab_client_for_source.commit(source.repo, old_commit)
63
63
  end
64
64
 
65
+ # @param [DependencyFile] file
66
+ def file_action(file)
67
+ if file.operation == Dependabot::DependencyFile::Operation::DELETE
68
+ "delete"
69
+ elsif file.operation == Dependabot::DependencyFile::Operation::CREATE
70
+ "create"
71
+ else
72
+ "update"
73
+ end
74
+ end
75
+
65
76
  def create_commit
66
77
  actions = files.map do |file|
67
78
  {
68
- action: "update",
79
+ action: file_action(file),
69
80
  file_path: file.type == "symlink" ? file.symlink_target : file.path,
70
81
  content: file.content
71
82
  }
@@ -161,47 +161,21 @@ module Dependabot
161
161
  reset_global_git_config(backup_git_config_path)
162
162
  end
163
163
 
164
+ def self.credential_helper_path
165
+ File.join(__dir__, "../../bin/git-credential-store-immutable")
166
+ end
167
+
168
+ # rubocop:disable Metrics/AbcSize
169
+ # rubocop:disable Metrics/PerceivedComplexity
164
170
  def self.configure_git_to_use_https_with_credentials(credentials)
165
171
  File.open(GIT_CONFIG_GLOBAL_PATH, "w") do |file|
166
172
  file << "# Generated by dependabot/dependabot-core"
167
173
  end
168
- configure_git_to_use_https
169
- configure_git_credentials(credentials)
170
- end
171
-
172
- def self.configure_git_to_use_https
173
- # NOTE: we use --global here (rather than --system) so that Dependabot
174
- # can be run without privileged access
175
- run_shell_command(
176
- "git config --global --replace-all url.https://github.com/."\
177
- "insteadOf ssh://git@github.com/"
178
- )
179
- run_shell_command(
180
- "git config --global --add url.https://github.com/."\
181
- "insteadOf ssh://git@github.com:"
182
- )
183
- run_shell_command(
184
- "git config --global --add url.https://github.com/."\
185
- "insteadOf git@github.com:"
186
- )
187
- run_shell_command(
188
- "git config --global --add url.https://github.com/."\
189
- "insteadOf git@github.com/"
190
- )
191
- run_shell_command(
192
- "git config --global --add url.https://github.com/."\
193
- "insteadOf git://github.com/"
194
- )
195
- end
196
174
 
197
- # rubocop:disable Metrics/PerceivedComplexity
198
- def self.configure_git_credentials(credentials)
199
175
  # Then add a file-based credential store that loads a file in this repo.
200
176
  # Under the hood this uses git credential-store, but it's invoked through
201
177
  # a wrapper binary that only allows non-mutating commands. Without this,
202
178
  # whenever the credentials are deemed to be invalid, they're erased.
203
- credential_helper_path =
204
- File.join(__dir__, "../../bin/git-credential-store-immutable")
205
179
  run_shell_command(
206
180
  "git config --global credential.helper "\
207
181
  "'!#{credential_helper_path} --file #{Dir.pwd}/git.store'",
@@ -219,6 +193,9 @@ module Dependabot
219
193
  github_credentials.find { |c| !c["password"]&.start_with?("v1.") } ||
220
194
  github_credentials.first
221
195
 
196
+ # Make sure we always have https alternatives for github.com.
197
+ configure_git_to_use_https("github.com") if github_credential.nil?
198
+
222
199
  deduped_credentials = credentials -
223
200
  github_credentials +
224
201
  [github_credential].compact
@@ -234,13 +211,40 @@ module Dependabot
234
211
  "@#{cred.fetch('host')}"
235
212
 
236
213
  git_store_content += authenticated_url + "\n"
214
+ configure_git_to_use_https(cred.fetch("host"))
237
215
  end
238
216
 
239
217
  # Save the file
240
218
  File.write("git.store", git_store_content)
241
219
  end
220
+ # rubocop:enable Metrics/AbcSize
242
221
  # rubocop:enable Metrics/PerceivedComplexity
243
222
 
223
+ def self.configure_git_to_use_https(host)
224
+ # NOTE: we use --global here (rather than --system) so that Dependabot
225
+ # can be run without privileged access
226
+ run_shell_command(
227
+ "git config --global --replace-all url.https://#{host}/."\
228
+ "insteadOf ssh://git@#{host}/"
229
+ )
230
+ run_shell_command(
231
+ "git config --global --add url.https://#{host}/."\
232
+ "insteadOf ssh://git@#{host}:"
233
+ )
234
+ run_shell_command(
235
+ "git config --global --add url.https://#{host}/."\
236
+ "insteadOf git@#{host}:"
237
+ )
238
+ run_shell_command(
239
+ "git config --global --add url.https://#{host}/."\
240
+ "insteadOf git@#{host}/"
241
+ )
242
+ run_shell_command(
243
+ "git config --global --add url.https://#{host}/."\
244
+ "insteadOf git://#{host}/"
245
+ )
246
+ end
247
+
244
248
  def self.reset_git_repo(path)
245
249
  Dir.chdir(path) do
246
250
  run_shell_command("git reset HEAD --hard")
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dependabot
4
- VERSION = "0.139.0"
4
+ VERSION = "0.140.2"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-common
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.139.0
4
+ version: 0.140.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-30 00:00:00.000000000 Z
11
+ date: 2021-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport