diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/file_updater/npm_lockfile_updater.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/file_updater/npm_lockfile_updater.rb index 462c773b1f3..70755c7584f 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn/file_updater/npm_lockfile_updater.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/file_updater/npm_lockfile_updater.rb @@ -429,10 +429,9 @@ def handle_missing_package(package_name, error_message) reg = NpmAndYarn::UpdateChecker::RegistryFinder.new( dependency: missing_dep, credentials: credentials, - npmrc_file: dependency_files. - find { |f| f.name.end_with?(".npmrc") }, - yarnrc_file: dependency_files. - find { |f| f.name.end_with?(".yarnrc") } + npmrc_file: dependency_files. find { |f| f.name.end_with?(".npmrc") }, + yarnrc_file: dependency_files. find { |f| f.name.end_with?(".yarnrc") }, + yarnrc_yml_file: dependency_files.find { |f| f.name.end_with?(".yarnrc.yml") } ).registry return if UpdateChecker::RegistryFinder.central_registry?(reg) && !package_name.start_with?("@") diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/file_updater/yarn_lockfile_updater.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/file_updater/yarn_lockfile_updater.rb index 0b7ba03f657..37347612a69 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn/file_updater/yarn_lockfile_updater.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/file_updater/yarn_lockfile_updater.rb @@ -474,7 +474,8 @@ def handle_missing_package(package_name, error_message, yarn_lock) dependency: missing_dep, credentials: credentials, npmrc_file: npmrc_file, - yarnrc_file: yarnrc_file + yarnrc_file: yarnrc_file, + yarnrc_yml_file: yarnrc_yml_file ).registry return if UpdateChecker::RegistryFinder.central_registry?(reg) && !package_name.start_with?("@") @@ -578,6 +579,10 @@ def yarnrc_file def npmrc_file dependency_files.find { |f| f.name == ".npmrc" } end + + def yarnrc_yml_file + dependency_files.find { |f| f.name.end_with?(".yarnrc.yml") } + end end end end diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/update_checker/latest_version_finder.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/update_checker/latest_version_finder.rb index 2f377dfc1b8..6aa68418e9c 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn/update_checker/latest_version_finder.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/update_checker/latest_version_finder.rb @@ -371,7 +371,8 @@ def registry_finder dependency: dependency, credentials: credentials, npmrc_file: npmrc_file, - yarnrc_file: yarnrc_file + yarnrc_file: yarnrc_file, + yarnrc_yml_file: yarnrc_yml_file ) end @@ -395,6 +396,10 @@ def yarnrc_file dependency_files.find { |f| f.name.end_with?(".yarnrc") } end + def yarnrc_yml_file + dependency_files.find { |f| f.name.end_with?(".yarnrc.yml") } + end + # TODO: Remove need for me def git_dependency? # ignored_version/raise_on_ignored are irrelevant. diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/update_checker/library_detector.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/update_checker/library_detector.rb index 3f39cb56682..79df0709520 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn/update_checker/library_detector.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/update_checker/library_detector.rb @@ -65,7 +65,8 @@ def registry dependency: nil, credentials: credentials, npmrc_file: dependency_files.find { |f| f.name.end_with?(".npmrc") }, - yarnrc_file: dependency_files.find { |f| f.name.end_with?(".yarnrc") } + yarnrc_file: dependency_files.find { |f| f.name.end_with?(".yarnrc") }, + yarnrc_yml_file: dependency_files.find { |f| f.name.end_with?(".yarnrc.yml") } ).registry_from_rc(project_name) end end diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/update_checker/registry_finder.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/update_checker/registry_finder.rb index 1f0e9b58e57..4d4dfcc9c60 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn/update_checker/registry_finder.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/update_checker/registry_finder.rb @@ -25,11 +25,12 @@ class RegistryFinder /['"](?@[^:]+):registry['"]\s((['"](?.*)['"])|(?.*))/.freeze def initialize(dependency:, credentials:, npmrc_file: nil, - yarnrc_file: nil) + yarnrc_file: nil, yarnrc_yml_file: nil) @dependency = dependency @credentials = credentials @npmrc_file = npmrc_file @yarnrc_file = yarnrc_file + @yarnrc_yml_file = yarnrc_yml_file end def registry @@ -59,7 +60,7 @@ def registry_from_rc(dependency_name) private - attr_reader :dependency, :credentials, :npmrc_file, :yarnrc_file + attr_reader :dependency, :credentials, :npmrc_file, :yarnrc_file, :yarnrc_yml_file def first_registry_with_dependency_details @first_registry_with_dependency_details ||= @@ -214,6 +215,8 @@ def global_registry return Regexp.last_match[:registry].strip end + return parsed_yarnrc_yml["npmRegistryServer"] if parsed_yarnrc_yml&.key?("npmRegistryServer") + "https://registry.npmjs.org" end @@ -230,6 +233,11 @@ def scoped_registry(scope) return Regexp.last_match[:registry].strip end + if parsed_yarnrc_yml + yarn_berry_registry = parsed_yarnrc_yml.dig("npmScopes", scope.delete_prefix("@"), "npmRegistryServer") + return yarn_berry_registry if yarn_berry_registry + end + global_registry end @@ -245,6 +253,13 @@ def registry_source_url sources.find { |s| s[:type] == "registry" }&.fetch(:url) end + + def parsed_yarnrc_yml + return unless yarnrc_yml_file + return @parsed_yarnrc_yml if defined? @parsed_yarnrc_yml + + @parsed_yarnrc_yml = YAML.safe_load(yarnrc_yml_file.content) + end end end end diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/update_checker/registry_finder_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/update_checker/registry_finder_spec.rb index 5c7d0c546ba..f9b0d35fcdc 100644 --- a/npm_and_yarn/spec/dependabot/npm_and_yarn/update_checker/registry_finder_spec.rb +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/update_checker/registry_finder_spec.rb @@ -9,11 +9,13 @@ dependency: dependency, credentials: credentials, npmrc_file: npmrc_file, - yarnrc_file: yarnrc_file + yarnrc_file: yarnrc_file, + yarnrc_yml_file: yarnrc_yml_file ) end let(:npmrc_file) { nil } let(:yarnrc_file) { nil } + let(:yarnrc_yml_file) { nil } let(:credentials) do [{ "type" => "git_source", @@ -62,6 +64,14 @@ it { is_expected.to eq("http://example.com") } end + context "with a global yarn berry registry" do + let(:yarnrc_yml_file) do + Dependabot::DependencyFile.new(name: ".yarnrc.yml", content: 'npmRegistryServer: "https://example.com"') + end + + it { is_expected.to eq("https://example.com") } + end + context "with a scoped npm registry" do let(:dependency_name) { "@dependabot/some_dep" } let(:npmrc_file) { Dependabot::DependencyFile.new(name: ".npmrc", content: "@dependabot:registry=http://example.com") } @@ -82,6 +92,20 @@ it { is_expected.to eq("http://example.com") } end + + context "with a scoped yarn berry registry" do + let(:dependency_name) { "@dependabot/some_dep" } + let(:yarnrc_yml_content) do + <<~YARNRC + npmScopes: + dependabot: + npmRegistryServer: "https://example.com" + YARNRC + end + let(:yarnrc_yml_file) { Dependabot::DependencyFile.new(name: ".yarnrc", content: yarnrc_yml_content) } + + it { is_expected.to eq("https://example.com") } + end end describe "registry" do @@ -221,6 +245,34 @@ end end + context "with a .yarnrc.yml file" do + let(:yarnrc_yml_file) do + project_dependency_files(project_name).find { |f| f.name == ".yarnrc.yml" } + end + let(:project_name) { "yarn_berry/yarnrc_global_registry" } + + before do + url = "https://npm-proxy.fury.io/password/dependabot/etag" + body = fixture("gemfury_responses", "gemfury_response_etag.json") + + stub_request(:get, url).to_return(status: 200, body: body) + end + + it { is_expected.to eq("npm-proxy.fury.io/password/dependabot") } + + context "that can't be reached" do + before do + url = "https://npm-proxy.fury.io/password/dependabot/etag" + stub_request(:get, url).to_return(status: 401, body: "") + end + + # Since this registry is declared at the global registry, in the absence + # of other information we should still us it (and *not* flaa back to + # registry.npmjs.org) + it { is_expected.to eq("npm-proxy.fury.io/password/dependabot") } + end + end + context "with a private registry source" do let(:source) do { type: "registry", url: "https://npm.fury.io/dependabot" } diff --git a/npm_and_yarn/spec/fixtures/projects/yarn_berry/yarnrc_global_registry/.yarn/install-state.gz b/npm_and_yarn/spec/fixtures/projects/yarn_berry/yarnrc_global_registry/.yarn/install-state.gz new file mode 100644 index 00000000000..78726d4c661 Binary files /dev/null and b/npm_and_yarn/spec/fixtures/projects/yarn_berry/yarnrc_global_registry/.yarn/install-state.gz differ diff --git a/npm_and_yarn/spec/fixtures/projects/yarn_berry/yarnrc_global_registry/.yarnrc.yml b/npm_and_yarn/spec/fixtures/projects/yarn_berry/yarnrc_global_registry/.yarnrc.yml new file mode 100644 index 00000000000..ff019a31cd7 --- /dev/null +++ b/npm_and_yarn/spec/fixtures/projects/yarn_berry/yarnrc_global_registry/.yarnrc.yml @@ -0,0 +1 @@ +npmRegistryServer: "https://npm-proxy.fury.io/password/dependabot/" diff --git a/npm_and_yarn/spec/fixtures/projects/yarn_berry/yarnrc_global_registry/package.json b/npm_and_yarn/spec/fixtures/projects/yarn_berry/yarnrc_global_registry/package.json new file mode 100644 index 00000000000..3137db2d682 --- /dev/null +++ b/npm_and_yarn/spec/fixtures/projects/yarn_berry/yarnrc_global_registry/package.json @@ -0,0 +1,22 @@ +{ + "name": "{{ name }}", + "version": "1.0.0", + "description": "", + "main": "index.js", + "repository": { + "type": "git", + "url": "git+https://github.com/waltfy/PROTO_TEST.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/waltfy/PROTO_TEST/issues" + }, + "homepage": "https://github.com/waltfy/PROTO_TEST#readme", + "dependencies": { + "fetch-factory": "^0.0.1" + }, + "devDependencies": { + "etag": "^1.0.0" + } +} diff --git a/npm_and_yarn/spec/fixtures/projects/yarn_berry/yarnrc_global_registry/yarn.lock b/npm_and_yarn/spec/fixtures/projects/yarn_berry/yarnrc_global_registry/yarn.lock new file mode 100644 index 00000000000..fa119fdb809 --- /dev/null +++ b/npm_and_yarn/spec/fixtures/projects/yarn_berry/yarnrc_global_registry/yarn.lock @@ -0,0 +1,97 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 6 + cacheKey: 8 + +"encoding@npm:^0.1.11": + version: 0.1.12 + resolution: "encoding@npm:0.1.12" + dependencies: + iconv-lite: ~0.4.13 + checksum: 96df688a93821e866bea19dd689863b1f9e07ef1c15321dde1fbcb8008ed7c785c48b248c4def01367780d2637c459b8ffa988de9647afe4200b003b1ac369ef + languageName: node + linkType: hard + +"es6-promise@npm:^3.0.2": + version: 3.3.1 + resolution: "es6-promise@npm:3.3.1" + checksum: ce4044009c2b78db18b15212338eb711cd8a4d485961bc9ec18bb24e8c1e91c96d3295b0fcf63066fc0fa1b0ade36da05e6657827d4336dece382be2429b8398 + languageName: node + linkType: hard + +"etag@npm:^1.0.0": + version: 1.7.0 + resolution: "etag@npm:1.7.0" + checksum: a76e03c51881902070fa3ecd4bd5c5b9286657ea467ada24bf866c1bdd545d08b65191d085b70fdc859caea2d68ff99c4f6936d2fa2026fd2fcc796d013e1978 + languageName: node + linkType: hard + +"fetch-factory@npm:^0.0.1": + version: 0.0.1 + resolution: "fetch-factory@npm:0.0.1" + dependencies: + es6-promise: ^3.0.2 + isomorphic-fetch: ^2.1.1 + lodash: ^3.10.1 + checksum: ff7fe6fdb8dd22080ff2d10495d0701068aac2d4d2c7c00baa675d9efa0d9b472deee7de0a60a2094446ec907833fdf0322ddaa814e1c594de5796b1e08157d9 + languageName: node + linkType: hard + +"iconv-lite@npm:~0.4.13": + version: 0.4.15 + resolution: "iconv-lite@npm:0.4.15" + checksum: 858ed660b795386d1ab85c43962d34519d46511d61432f6a74c1488dce2b6023f7eaec82f35f1e94eb20f2cfb36c6ad07e3814f9551a4b7c6058a162bbab382e + languageName: node + linkType: hard + +"is-stream@npm:^1.0.1": + version: 1.1.0 + resolution: "is-stream@npm:1.1.0" + checksum: 063c6bec9d5647aa6d42108d4c59723d2bd4ae42135a2d4db6eadbd49b7ea05b750fd69d279e5c7c45cf9da753ad2c00d8978be354d65aa9f6bb434969c6a2ae + languageName: node + linkType: hard + +"isomorphic-fetch@npm:^2.1.1": + version: 2.2.1 + resolution: "isomorphic-fetch@npm:2.2.1" + dependencies: + node-fetch: ^1.0.1 + whatwg-fetch: ">=0.10.0" + checksum: bb5daa7c3785d6742f4379a81e55b549a469503f7c9bf9411b48592e86632cf5e8fe8ea878dba185c0f33eb7c510c23abdeb55aebfdf5d3c70f031ced68c5424 + languageName: node + linkType: hard + +"lodash@npm:^3.10.1": + version: 3.10.1 + resolution: "lodash@npm:3.10.1" + checksum: 53065d3712a2fd90b55690c5af19f9625a5bbb2b7876ff76d782ee1dc22618fd4dff191d44a8e165a17b5b81a851c3e884d3b5b25e314422fbe24bb299542685 + languageName: node + linkType: hard + +"node-fetch@npm:^1.0.1": + version: 1.6.3 + resolution: "node-fetch@npm:1.6.3" + dependencies: + encoding: ^0.1.11 + is-stream: ^1.0.1 + checksum: cd8e3990065538141796c4f4d67dc9a9969880d9c4b9c6ad61cd5d140d9839bb04c099d53c16910dbef77ae73f390554370e2208862754ca71e1f6e445cb52f0 + languageName: node + linkType: hard + +"whatwg-fetch@npm:>=0.10.0": + version: 2.0.2 + resolution: "whatwg-fetch@npm:2.0.2" + checksum: 686d167f497d894d9dddb7f91d042ab927775a9c877015945261406ad64248e464c7fcfddc5a41e400102e3f68934da4762b7b8fadced8fc126b0a88f5e3bd0f + languageName: node + linkType: hard + +"{{ name }}@workspace:.": + version: 0.0.0-use.local + resolution: "{{ name }}@workspace:." + dependencies: + etag: ^1.0.0 + fetch-factory: ^0.0.1 + languageName: unknown + linkType: soft