dependabot-npm_and_yarn 0.91.8 → 0.92.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,14 +1,6 @@
1
- const lockfileParser = require("../lib/lockfile-parser");
2
- const updater = require("../lib/updater");
3
- const subdependencyUpdater = require("../lib/subdependency-updater");
4
- const peerDependencyChecker = require("../lib/peer-dependency-checker");
1
+ #!/usr/bin/env node
5
2
 
6
- const functionMap = {
7
- parseLockfile: lockfileParser.parse,
8
- update: updater.updateDependencyFiles,
9
- updateSubdependency: subdependencyUpdater.updateDependencyFile,
10
- checkPeerDependencies: peerDependencyChecker.checkPeerDependencies
11
- };
3
+ const functionMap = require("../lib");
12
4
 
13
5
  function output(obj) {
14
6
  process.stdout.write(JSON.stringify(obj));
@@ -0,0 +1,11 @@
1
+ const lockfileParser = require("../lib/lockfile-parser");
2
+ const updater = require("../lib/updater");
3
+ const subdependencyUpdater = require("../lib/subdependency-updater");
4
+ const peerDependencyChecker = require("../lib/peer-dependency-checker");
5
+
6
+ module.exports = {
7
+ parseLockfile: lockfileParser.parse,
8
+ update: updater.updateDependencyFiles,
9
+ updateSubdependency: subdependencyUpdater.updateDependencyFile,
10
+ checkPeerDependencies: peerDependencyChecker.checkPeerDependencies
11
+ };
@@ -1,17 +1,12 @@
1
1
  {
2
- "name": "dependabot-core",
2
+ "name": "@dependabot/yarn",
3
3
  "version": "0.0.0",
4
4
  "private": true,
5
5
  "dependencies": {
6
- "@dependabot/yarn-lib": "1.13.0",
7
- "semver": "5.6.0"
6
+ "@dependabot/yarn-lib": "^1.13.0",
7
+ "semver": "^5.6.0"
8
8
  },
9
- "devDependencies": {
10
- "eslint": "5.12.1",
11
- "eslint-plugin-prettier": "3.0.1",
12
- "fs-extra": "7.0.1",
13
- "jest": "23.6.0",
14
- "nock": "10.0.6",
15
- "prettier": "1.16.0"
9
+ "bin": {
10
+ "dependabot-yarn": "./bin/run.js"
16
11
  }
17
12
  }
@@ -3,5 +3,5 @@ const fs = require("fs");
3
3
 
4
4
  module.exports = {
5
5
  loadFixture: fixturePath =>
6
- fs.readFileSync(path.join("test", "fixtures", fixturePath)).toString()
6
+ fs.readFileSync(path.join(__dirname, "fixtures", fixturePath)).toString()
7
7
  };
@@ -23,10 +23,16 @@ describe("updater", () => {
23
23
  afterEach(() => fs.removeSync(tempDir));
24
24
 
25
25
  async function copyDependencies(sourceDir, destDir) {
26
- const srcPackageJson = `test/fixtures/updater/${sourceDir}/package.json`;
26
+ const srcPackageJson = path.join(
27
+ __dirname,
28
+ `fixtures/updater/${sourceDir}/package.json`
29
+ );
27
30
  await fs.copy(srcPackageJson, `${destDir}/package.json`);
28
31
 
29
- const srcYarnLock = `test/fixtures/updater/${sourceDir}/yarn.lock`;
32
+ const srcYarnLock = path.join(
33
+ __dirname,
34
+ `fixtures/updater/${sourceDir}/yarn.lock`
35
+ );
30
36
  await fs.copy(srcYarnLock, `${destDir}/yarn.lock`);
31
37
  }
32
38
 
@@ -48,8 +48,8 @@ module Dependabot
48
48
  UNREACHABLE_GIT =
49
49
  /ls-remote (?:(-h -t)|(--tags --heads)) (?<url>.*)/.freeze
50
50
  FORBIDDEN_PACKAGE =
51
- /(403 Forbidden|401 Unauthorized): (?<package_req>.*)/.freeze
52
- MISSING_PACKAGE = /404 Not Found: (?<package_req>.*)/.freeze
51
+ %r{(?<package_req>[^/]+) - (Forbidden|Unauthorized)}.freeze
52
+ MISSING_PACKAGE = %r{(?<package_req>[^/]+) - Not found}.freeze
53
53
  INVALID_PACKAGE = /Can't install (?<package_req>.*): Missing/.freeze
54
54
 
55
55
  def top_level_dependencies
@@ -69,12 +69,19 @@ module Dependabot
69
69
  end
70
70
  end
71
71
 
72
+ def lockfile_dependencies(lockfile)
73
+ @lockfile_dependencies ||= {}
74
+ @lockfile_dependencies[lockfile.name] ||=
75
+ NpmAndYarn::FileParser.new(
76
+ dependency_files: [lockfile, *package_files],
77
+ source: nil,
78
+ credentials: credentials
79
+ ).parse
80
+ end
81
+
72
82
  def dependency_up_to_date?(lockfile, dependency)
73
- existing_dep = NpmAndYarn::FileParser.new(
74
- dependency_files: [lockfile, *package_files],
75
- source: nil,
76
- credentials: credentials
77
- ).parse.find { |dep| dep.name == dependency.name }
83
+ existing_dep = lockfile_dependencies(lockfile).
84
+ find { |dep| dep.name == dependency.name }
78
85
 
79
86
  # If the dependency is missing but top level it should be treated as
80
87
  # not up to date
@@ -167,19 +174,9 @@ module Dependabot
167
174
  package_name =
168
175
  error.message.match(MISSING_PACKAGE).
169
176
  named_captures["package_req"].
170
- split(/(?<=\w)\@/).first
177
+ gsub("%2f", "/")
171
178
  handle_missing_package(package_name, error, lockfile)
172
179
  end
173
- names = dependencies.map(&:name)
174
- if names.any? { |name| error.message.include?("#{name}@") } &&
175
- error.message.start_with?("No matching vers") &&
176
- resolvable_before_update?(lockfile)
177
- # This happens if a new version has been published that relies on
178
- # but npm is having consistency issues. We raise a bespoke error
179
- # so we can capture and ignore it if we're trying to create a new
180
- # PR (which will be created successfully at a later date).
181
- raise Dependabot::InconsistentRegistryResponse, error.message
182
- end
183
180
 
184
181
  # When the package.json doesn't include a name or version, or name
185
182
  # has non url-friendly characters
@@ -188,24 +185,43 @@ module Dependabot
188
185
  raise_resolvability_error(error, lockfile)
189
186
  end
190
187
 
191
- if error.message.start_with?("No matching vers", "404 Not Found") ||
192
- error.message.include?("not match any file(s) known to git") ||
193
- error.message.include?("Non-registry package missing package") ||
194
- error.message.include?("Cannot read property 'match' of ") ||
195
- error.message.include?("Invalid tag name")
196
- # This happens if a new version has been published that relies on
197
- # subdependencies that have not yet been published.
198
- raise if resolvable_before_update?(lockfile)
188
+ # TODO: Move this logic to the version resolver and check if a new
189
+ # version and all of its subdependencies are resolvable
190
+
191
+ # Make sure the error in question matches the current list of
192
+ # dependencies or matches an existing scoped package, this handles the
193
+ # case where a new version (e.g. @angular-devkit/build-angular) relies
194
+ # on a added dependency which hasn't been published yet under the same
195
+ # scope (e.g. @angular-devkit/build-optimizer)
196
+ #
197
+ # This seems to happen when big monorepo projects publish all of their
198
+ # packages sequentially, which might take enough time for Dependabot
199
+ # to hear about a new version before all of its dependencies have been
200
+ # published
201
+ #
202
+ # OR
203
+ #
204
+ # This happens if a new version has been published but npm is having
205
+ # consistency issues and the version isn't fully available on all
206
+ # queries
207
+ if error.message.start_with?("No matching vers") &&
208
+ dependencies_in_error_message?(error.message) &&
209
+ resolvable_before_update?(lockfile)
199
210
 
200
- raise_resolvability_error(error, lockfile)
211
+ # Raise a bespoke error so we can capture and ignore it if
212
+ # we're trying to create a new PR (which will be created
213
+ # successfully at a later date)
214
+ raise Dependabot::InconsistentRegistryResponse, error.message
201
215
  end
216
+
202
217
  if error.message.match?(FORBIDDEN_PACKAGE)
203
218
  package_name =
204
219
  error.message.match(FORBIDDEN_PACKAGE).
205
220
  named_captures["package_req"].
206
- split(/(?<=\w)\@/).first
221
+ gsub("%2f", "/")
207
222
  handle_missing_package(package_name, error, lockfile)
208
223
  end
224
+
209
225
  if error.message.match?(UNREACHABLE_GIT)
210
226
  dependency_url =
211
227
  error.message.match(UNREACHABLE_GIT).
@@ -213,7 +229,23 @@ module Dependabot
213
229
 
214
230
  raise Dependabot::GitDependenciesNotReachable, dependency_url
215
231
  end
216
- raise
232
+
233
+ if error.message.start_with?("No matching vers", "404 Not Found") ||
234
+ error.message.include?("not match any file(s) known to git") ||
235
+ error.message.include?("Non-registry package missing package") ||
236
+ error.message.include?("Cannot read property 'match' of ") ||
237
+ error.message.include?("Invalid tag name")
238
+
239
+ unless resolvable_before_update?(lockfile)
240
+ raise_resolvability_error(error, lockfile)
241
+ end
242
+
243
+ # Dependabot has probably messed something up with the update and we
244
+ # want to hear about it
245
+ raise error
246
+ end
247
+
248
+ raise error
217
249
  end
218
250
  # rubocop:enable Metrics/AbcSize
219
251
  # rubocop:enable Metrics/CyclomaticComplexity
@@ -228,11 +260,8 @@ module Dependabot
228
260
  end
229
261
 
230
262
  def handle_missing_package(package_name, error, lockfile)
231
- missing_dep = NpmAndYarn::FileParser.new(
232
- dependency_files: dependency_files,
233
- source: nil,
234
- credentials: credentials
235
- ).parse.find { |dep| dep.name == package_name }
263
+ missing_dep = lockfile_dependencies(lockfile).
264
+ find { |dep| dep.name == package_name }
236
265
 
237
266
  raise_resolvability_error(error, lockfile) unless missing_dep
238
267
 
@@ -283,6 +312,15 @@ module Dependabot
283
312
  end
284
313
  end
285
314
 
315
+ def dependencies_in_error_message?(message)
316
+ names = dependencies.map { |dep| dep.name.split("/").first }
317
+ # Example foramt: No matching version found for
318
+ # @dependabot/dummy-pkg-b@^1.3.0
319
+ names.any? do |name|
320
+ message.match?(%r{#{Regexp.quote(name)}[\/@]})
321
+ end
322
+ end
323
+
286
324
  def write_temporary_dependency_files(lockfile_name,
287
325
  update_package_json: true)
288
326
  write_lockfiles(lockfile_name)
@@ -177,34 +177,46 @@ module Dependabot
177
177
  package_name =
178
178
  error.message.match(/package "(?<package_req>.*)?"/).
179
179
  named_captures["package_req"].
180
- split(/(?<=\w)\@/).first
180
+ split(/(?<=\w)\@/).first.
181
+ gsub("%2f", "/")
181
182
  handle_missing_package(package_name, error, yarn_lock)
182
183
  end
183
184
 
184
185
  if error.message.match?(%r{/[^/]+: Not found})
185
186
  package_name =
186
187
  error.message.match(%r{/(?<package_name>[^/]+): Not found}).
187
- named_captures["package_name"]
188
+ named_captures["package_name"].
189
+ gsub("%2f", "/")
188
190
  handle_missing_package(package_name, error, yarn_lock)
189
191
  end
190
192
 
191
- if error.message.start_with?("Couldn't find any versions") ||
192
- error.message.include?(": Not found")
193
-
194
- names = dependencies.map(&:name)
195
- if names.any? { |name| error.message.include?(%("#{name}")) }
196
- # This happens if a new version has been published but npm is
197
- # having consistency issues. We raise a bespoke error so we can
198
- # capture and ignore it if we're trying to create a new PR
199
- # (which will be created successfully at a later date).
200
- raise Dependabot::InconsistentRegistryResponse, error.message
201
- end
202
-
203
- # This happens if a new version has been published that relies on
204
- # subdependencies that have not yet been published.
205
- raise error if resolvable_before_update?(yarn_lock)
206
-
207
- raise_resolvability_error(error, yarn_lock)
193
+ # TODO: Move this logic to the version resolver and check if a new
194
+ # version and all of its subdependencies are resolvable
195
+
196
+ # Make sure the error in question matches the current list of
197
+ # dependencies or matches an existing scoped package, this handles the
198
+ # case where a new version (e.g. @angular-devkit/build-angular) relies
199
+ # on a added dependency which hasn't been published yet under the same
200
+ # scope (e.g. @angular-devkit/build-optimizer)
201
+ #
202
+ # This seems to happen when big monorepo projects publish all of their
203
+ # packages sequentially, which might take enough time for Dependabot
204
+ # to hear about a new version before all of its dependencies have been
205
+ # published
206
+ #
207
+ # OR
208
+ #
209
+ # This happens if a new version has been published but npm is having
210
+ # consistency issues and the version isn't fully available on all
211
+ # queries
212
+ if error.message.start_with?("Couldn't find any versions") &&
213
+ dependencies_in_error_message?(error.message) &&
214
+ resolvable_before_update?(yarn_lock)
215
+
216
+ # Raise a bespoke error so we can capture and ignore it if
217
+ # we're trying to create a new PR (which will be created
218
+ # successfully at a later date)
219
+ raise Dependabot::InconsistentRegistryResponse, error.message
208
220
  end
209
221
 
210
222
  if error.message.include?("Workspaces can only be enabled in priva")
@@ -219,10 +231,22 @@ module Dependabot
219
231
  end
220
232
 
221
233
  if error.message.match?(TIMEOUT_FETCHING_PACKAGE)
222
- handle_timeout(error.message)
234
+ handle_timeout(error.message, yarn_lock)
223
235
  end
224
236
 
225
- raise
237
+ if error.message.start_with?("Couldn't find any versions") ||
238
+ error.message.include?(": Not found")
239
+
240
+ unless resolvable_before_update?(yarn_lock)
241
+ raise_resolvability_error(error, yarn_lock)
242
+ end
243
+
244
+ # Dependabot has probably messed something up with the update and we
245
+ # want to hear about it
246
+ raise error
247
+ end
248
+
249
+ raise error
226
250
  end
227
251
  # rubocop:enable Metrics/AbcSize
228
252
  # rubocop:enable Metrics/CyclomaticComplexity
@@ -230,16 +254,34 @@ module Dependabot
230
254
  # rubocop:enable Metrics/MethodLength
231
255
 
232
256
  def resolvable_before_update?(yarn_lock)
233
- SharedHelpers.in_a_temporary_directory do
234
- write_temporary_dependency_files(update_package_json: false)
235
- lockfile_name = Pathname.new(yarn_lock.name).basename.to_s
236
- path = Pathname.new(yarn_lock.name).dirname.to_s
237
- run_previous_yarn_update(path: path, lockfile_name: lockfile_name)
257
+ @resolvable_before_update ||= {}
258
+ if @resolvable_before_update.key?(yarn_lock.name)
259
+ return @resolvable_before_update[yarn_lock.name]
238
260
  end
239
261
 
240
- true
241
- rescue SharedHelpers::HelperSubprocessFailed
242
- false
262
+ @resolvable_before_update[yarn_lock.name] =
263
+ begin
264
+ SharedHelpers.in_a_temporary_directory do
265
+ write_temporary_dependency_files(update_package_json: false)
266
+ lockfile_name = Pathname.new(yarn_lock.name).basename.to_s
267
+ path = Pathname.new(yarn_lock.name).dirname.to_s
268
+ run_previous_yarn_update(path: path,
269
+ lockfile_name: lockfile_name)
270
+ end
271
+
272
+ true
273
+ rescue SharedHelpers::HelperSubprocessFailed
274
+ false
275
+ end
276
+ end
277
+
278
+ def dependencies_in_error_message?(message)
279
+ names = dependencies.map { |dep| dep.name.split("/").first }
280
+ # Example format: Couldn't find any versions for
281
+ # "@dependabot/dummy-pkg-b" that matches "^1.3.0"
282
+ names.any? do |name|
283
+ message.match?(%r{"#{Regexp.quote(name)}["\/]})
284
+ end
243
285
  end
244
286
 
245
287
  def write_temporary_dependency_files(update_package_json: true)
@@ -368,12 +410,19 @@ module Dependabot
368
410
  content.lines.reject { |l| l.match?(/\s*integrity sha/) }.join
369
411
  end
370
412
 
413
+ def lockfile_dependencies(lockfile)
414
+ @lockfile_dependencies ||= {}
415
+ @lockfile_dependencies[lockfile.name] ||=
416
+ NpmAndYarn::FileParser.new(
417
+ dependency_files: [lockfile, *package_files],
418
+ source: nil,
419
+ credentials: credentials
420
+ ).parse
421
+ end
422
+
371
423
  def handle_missing_package(package_name, error, yarn_lock)
372
- missing_dep = NpmAndYarn::FileParser.new(
373
- dependency_files: dependency_files,
374
- source: nil,
375
- credentials: credentials
376
- ).parse.find { |dep| dep.name == package_name }
424
+ missing_dep = lockfile_dependencies(yarn_lock).
425
+ find { |dep| dep.name == package_name }
377
426
 
378
427
  raise_resolvability_error(error, yarn_lock) unless missing_dep
379
428
 
@@ -406,7 +455,7 @@ module Dependabot
406
455
  raise Dependabot::DependencyFileNotResolvable, msg
407
456
  end
408
457
 
409
- def handle_timeout(message)
458
+ def handle_timeout(message, yarn_lock)
410
459
  url = message.match(TIMEOUT_FETCHING_PACKAGE).named_captures["url"]
411
460
  return if url.start_with?("https://registry.npmjs.org")
412
461
 
@@ -414,11 +463,8 @@ module Dependabot
414
463
  message.match(TIMEOUT_FETCHING_PACKAGE).
415
464
  named_captures["package"].gsub("%2f", "/").gsub("%2F", "/")
416
465
 
417
- dep = NpmAndYarn::FileParser.new(
418
- dependency_files: dependency_files,
419
- source: nil,
420
- credentials: credentials
421
- ).parse.find { |d| d.name == package_name }
466
+ dep = lockfile_dependencies(yarn_lock).
467
+ find { |d| d.name == package_name }
422
468
  return unless dep
423
469
 
424
470
  raise PrivateSourceTimedOut, url.gsub(%r{https?://}, "")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-npm_and_yarn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.91.8
4
+ version: 0.92.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-20 00:00:00.000000000 Z
11
+ date: 2019-01-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dependabot-core
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.91.8
19
+ version: 0.92.2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.91.8
26
+ version: 0.92.2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: byebug
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -143,14 +143,14 @@ executables: []
143
143
  extensions: []
144
144
  extra_rdoc_files: []
145
145
  files:
146
+ - helpers/.eslintrc
146
147
  - helpers/build
147
- - helpers/npm/.eslintrc
148
148
  - helpers/npm/bin/run.js
149
149
  - helpers/npm/lib/helpers.js
150
+ - helpers/npm/lib/index.js
150
151
  - helpers/npm/lib/peer-dependency-checker.js
151
152
  - helpers/npm/lib/subdependency-updater.js
152
153
  - helpers/npm/lib/updater.js
153
- - helpers/npm/package-lock.json
154
154
  - helpers/npm/package.json
155
155
  - helpers/npm/test/fixtures/npm-left-pad.json
156
156
  - helpers/npm/test/fixtures/updater/original/package-lock.json
@@ -158,11 +158,12 @@ files:
158
158
  - helpers/npm/test/fixtures/updater/updated/package-lock.json
159
159
  - helpers/npm/test/helpers.js
160
160
  - helpers/npm/test/updater.test.js
161
- - helpers/npm/yarn.lock
162
- - helpers/yarn/.eslintrc
161
+ - helpers/package.json
162
+ - helpers/yarn.lock
163
163
  - helpers/yarn/bin/run.js
164
164
  - helpers/yarn/lib/fix-duplicates.js
165
165
  - helpers/yarn/lib/helpers.js
166
+ - helpers/yarn/lib/index.js
166
167
  - helpers/yarn/lib/lockfile-parser.js
167
168
  - helpers/yarn/lib/peer-dependency-checker.js
168
169
  - helpers/yarn/lib/replace-lockfile-declaration.js
@@ -178,7 +179,6 @@ files:
178
179
  - helpers/yarn/test/fixtures/yarnpkg-left-pad.json
179
180
  - helpers/yarn/test/helpers.js
180
181
  - helpers/yarn/test/updater.test.js
181
- - helpers/yarn/yarn.lock
182
182
  - lib/dependabot/npm_and_yarn.rb
183
183
  - lib/dependabot/npm_and_yarn/dependency_files_filterer.rb
184
184
  - lib/dependabot/npm_and_yarn/file_fetcher.rb