From 30ee1e7e7cbe36d58f43ebe341763f41591732f3 Mon Sep 17 00:00:00 2001 From: Yurick Hauschild Date: Thu, 17 Oct 2024 11:22:51 +0200 Subject: [PATCH 1/2] Try to find pnpm-lock.yaml file upwards on tree structure --- .../dependabot/npm_and_yarn/file_fetcher.rb | 14 ++++ .../npm_and_yarn/file_fetcher_spec.rb | 68 +++++++++++++++++++ .../github/contents_js_pnpm_workspace.json | 18 +++++ 3 files changed, 100 insertions(+) create mode 100644 npm_and_yarn/spec/fixtures/github/contents_js_pnpm_workspace.json diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/file_fetcher.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/file_fetcher.rb index eb9161a676a..c26d617d188 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn/file_fetcher.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/file_fetcher.rb @@ -227,6 +227,20 @@ def pnpm_lock return @pnpm_lock if defined?(@pnpm_lock) @pnpm_lock ||= T.let(fetch_file_if_present("pnpm-lock.yaml"), T.nilable(DependencyFile)) + + return @pnpm_lock if @pnpm_lock || directory == "/" + + # Loop through parent directories looking for a pnpm-lock + (1..directory.split("/").count).each do |i| + @pnpm_lock = fetch_file_from_host(("../" * i) + "pnpm-lock.yaml") + .tap { |f| f.support_file = true } + break if @pnpm_lock + rescue Dependabot::DependencyFileNotFound + # Ignore errors (pnpm_lock.yaml may not be present) + nil + end + + @pnpm_lock end sig { returns(T.nilable(DependencyFile)) } diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/file_fetcher_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/file_fetcher_spec.rb index 05409f79777..cb7e24082a1 100644 --- a/npm_and_yarn/spec/dependabot/npm_and_yarn/file_fetcher_spec.rb +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/file_fetcher_spec.rb @@ -328,6 +328,62 @@ .to_return(status: 404) end + context "when source points to nested project" do + let(:repo) { "dependabot-fixtures/projects/pnpm/workspace_v9" } + let(:directory) { "/packages/package1" } + + before do + stub_request(:get, File.join(url, "packages/package1?ref=sha")) + .with(headers: { "Authorization" => "token token" }) + .to_return( + status: 200, + body: fixture("github", "contents_js_pnpm_workspace.json"), + headers: json_header + ) + stub_request(:get, File.join(url, "packages/package1/package.json?ref=sha")) + .with(headers: { "Authorization" => "token token" }) + .to_return( + status: 200, + body: fixture("github", "package_json_content.json"), + headers: json_header + ) + # FileFetcher will iterate trying to find `.npmrc` upwards in the folder tree + stub_request(:get, File.join(url, "packages/.npmrc?ref=sha")) + .with(headers: { "Authorization" => "token token" }) + .to_return( + status: 404, + body: nil, + headers: json_header + ) + stub_request(:get, File.join(url, ".npmrc?ref=sha")) + .with(headers: { "Authorization" => "token token" }) + .to_return( + status: 200, + body: fixture("github", "package_json_content.json"), + headers: json_header + ) + # FileFetcher will iterate trying to find `pnpm-lock.yaml` upwards in the folder tree + stub_request(:get, File.join(url, "packages/pnpm-lock.yaml?ref=sha")) + .with(headers: { "Authorization" => "token token" }) + .to_return( + status: 404, + body: nil, + headers: json_header + ) + stub_request(:get, File.join(url, "pnpm-lock.yaml?ref=sha")) + .with(headers: { "Authorization" => "token token" }) + .to_return( + status: 200, + body: fixture("github", "pnpm_lock_quotes_content.json"), + headers: json_header + ) + end + + it "fetches the pnpm-lock.yaml file at the root of the monorepo" do + expect(file_fetcher_instance.files.map(&:name)).to include("../../pnpm-lock.yaml") + end + end + context "when using older than 5.4 lockfile format" do before do stub_request(:get, File.join(url, "pnpm-lock.yaml?ref=sha")) @@ -1192,6 +1248,12 @@ ".yarnrc?ref=sha" ).with(headers: { "Authorization" => "token token" }) .to_return(status: 404) + stub_request( + :get, + "https://api.github.com/repos/gocardless/bump/contents/" \ + "pnpm-lock.yaml?ref=sha" + ).with(headers: { "Authorization" => "token token" }) + .to_return(status: 404) end it "fetches package.json from the workspace dependencies" do @@ -1755,6 +1817,12 @@ ".yarnrc?ref=sha" ).with(headers: { "Authorization" => "token token" }) .to_return(status: 404) + stub_request( + :get, + "https://api.github.com/repos/gocardless/bump/contents/" \ + "pnpm-lock.yaml?ref=sha" + ).with(headers: { "Authorization" => "token token" }) + .to_return(status: 404) end it "fetches package.json from the workspace dependencies" do diff --git a/npm_and_yarn/spec/fixtures/github/contents_js_pnpm_workspace.json b/npm_and_yarn/spec/fixtures/github/contents_js_pnpm_workspace.json new file mode 100644 index 00000000000..e46a7defa04 --- /dev/null +++ b/npm_and_yarn/spec/fixtures/github/contents_js_pnpm_workspace.json @@ -0,0 +1,18 @@ +[ + { + "name": "package.json", + "path": "package.json", + "sha": "58166807d223462b6b44dd016e0b31edb390d3f4", + "size": 329, + "url": "https://api.github.com/repos/org/repo/contents/package.json?ref=main", + "html_url": "https://github.com/org/repo/blob/main/package.json", + "git_url": "https://api.github.com/repos/org/repo/git/blobs/58166807d223462b6b44dd016e0b31edb390d3f4", + "download_url": "https://raw.githubusercontent.com/org/repo/main/package.json?token=ABMwe0apDiKCctWHnEHnszRBAebVHjQnks5WJWD9wA%3D%3D", + "type": "file", + "_links": { + "self": "https://api.github.com/repos/org/repo/contents/package.json?ref=main", + "git": "https://api.github.com/repos/org/repo/git/blobs/58166807d223462b6b44dd016e0b31edb390d3f4", + "html": "https://github.com/org/repo/blob/main/package.json" + } + } +] From 3d6dfee3948e002257aa275886876182b25b005f Mon Sep 17 00:00:00 2001 From: Yurick Hauschild Date: Thu, 17 Oct 2024 11:30:04 +0200 Subject: [PATCH 2/2] Address linting changes --- npm_and_yarn/lib/dependabot/npm_and_yarn/file_fetcher.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/file_fetcher.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/file_fetcher.rb index c26d617d188..91e1fd9b9d5 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn/file_fetcher.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/file_fetcher.rb @@ -233,7 +233,7 @@ def pnpm_lock # Loop through parent directories looking for a pnpm-lock (1..directory.split("/").count).each do |i| @pnpm_lock = fetch_file_from_host(("../" * i) + "pnpm-lock.yaml") - .tap { |f| f.support_file = true } + .tap { |f| f.support_file = true } break if @pnpm_lock rescue Dependabot::DependencyFileNotFound # Ignore errors (pnpm_lock.yaml may not be present)