From 024d60516ef49fd08ced6fff7670f9c418a387bd Mon Sep 17 00:00:00 2001 From: Zbynek Konecny Date: Sun, 26 Sep 2021 00:53:23 +0200 Subject: [PATCH 1/2] Support Gradle files with no top level build.gradle file --- gradle/lib/dependabot/gradle/file_fetcher.rb | 32 ++-- gradle/lib/dependabot/gradle/file_parser.rb | 2 +- gradle/lib/dependabot/gradle/file_updater.rb | 2 +- .../dependabot/gradle/file_fetcher_spec.rb | 147 +++++------------- .../github/contents_java_only_settings.json | 66 ++++++++ .../github/contents_java_subproject.json | 18 +++ 6 files changed, 144 insertions(+), 123 deletions(-) create mode 100644 gradle/spec/fixtures/github/contents_java_only_settings.json create mode 100644 gradle/spec/fixtures/github/contents_java_subproject.json diff --git a/gradle/lib/dependabot/gradle/file_fetcher.rb b/gradle/lib/dependabot/gradle/file_fetcher.rb index bcd3bba4e7..91ca9e657a 100644 --- a/gradle/lib/dependabot/gradle/file_fetcher.rb +++ b/gradle/lib/dependabot/gradle/file_fetcher.rb @@ -28,7 +28,7 @@ def self.required_files_message def fetch_files fetched_files = [] - fetched_files << buildfile + fetched_files << buildfile if buildfile fetched_files += subproject_buildfiles fetched_files += dependency_script_plugins check_required_files_present @@ -46,17 +46,23 @@ def buildfile def subproject_buildfiles return [] unless settings_file - subproject_paths = - SettingsFileParser. - new(settings_file: settings_file). - subproject_paths - - subproject_paths.map do |path| - fetch_file_from_host(File.join(path, @buildfile_name)) - rescue Dependabot::DependencyFileNotFound - # Gradle itself doesn't worry about missing subprojects, so we don't - nil - end.compact + @subproject_buildfiles ||= begin + subproject_paths = + SettingsFileParser. + new(settings_file: settings_file). + subproject_paths + + subproject_paths.map do |path| + if @buildfile_name + fetch_file_from_host(File.join(path, @buildfile_name)) + else + supported_file(SUPPORTED_BUILD_FILE_NAMES.map { |f| File.join(path, f) }) + end + rescue Dependabot::DependencyFileNotFound + # Gradle itself doesn't worry about missing subprojects, so we don't + nil + end.compact + end end # rubocop:disable Metrics/PerceivedComplexity @@ -83,7 +89,7 @@ def dependency_script_plugins # rubocop:enable Metrics/PerceivedComplexity def check_required_files_present - return if buildfile + return if buildfile || (@subproject_buildfiles && !@subproject_buildfiles.empty?) path = Pathname.new(File.join(directory, "build.gradle")).cleanpath.to_path path += "(.kts)?" diff --git a/gradle/lib/dependabot/gradle/file_parser.rb b/gradle/lib/dependabot/gradle/file_parser.rb index b452f3296f..451049db96 100644 --- a/gradle/lib/dependabot/gradle/file_parser.rb +++ b/gradle/lib/dependabot/gradle/file_parser.rb @@ -321,7 +321,7 @@ def script_plugin_files end def check_required_files - raise "No build.gradle or build.gradle.kts!" unless original_file + raise "No build.gradle or build.gradle.kts!" if dependency_files.empty? end def original_file diff --git a/gradle/lib/dependabot/gradle/file_updater.rb b/gradle/lib/dependabot/gradle/file_updater.rb index ef4c9f9818..296ceadd29 100644 --- a/gradle/lib/dependabot/gradle/file_updater.rb +++ b/gradle/lib/dependabot/gradle/file_updater.rb @@ -40,7 +40,7 @@ def updated_dependency_files private def check_required_files - raise "No build.gradle or build.gradle.kts!" unless original_file + raise "No build.gradle or build.gradle.kts!" if dependency_files.empty? end def original_file diff --git a/gradle/spec/dependabot/gradle/file_fetcher_spec.rb b/gradle/spec/dependabot/gradle/file_fetcher_spec.rb index 139636c5fe..6b9a636f73 100644 --- a/gradle/spec/dependabot/gradle/file_fetcher_spec.rb +++ b/gradle/spec/dependabot/gradle/file_fetcher_spec.rb @@ -17,6 +17,15 @@ let(:file_fetcher_instance) do described_class.new(source: source, credentials: credentials) end + def stub_content_request(path, fixture) + stub_request(:get, File.join(url, path)). + with(headers: { "Authorization" => "token token" }). + to_return( + status: 200, + body: fixture("github", fixture), + headers: { "content-type" => "application/json" } + ) + end let(:directory) { "/" } let(:github_url) { "https://api.github.com/" } let(:url) { github_url + "repos/gocardless/bump/contents/" } @@ -33,20 +42,8 @@ context "with a basic buildfile" do before do - stub_request(:get, url + "?ref=sha"). - with(headers: { "Authorization" => "token token" }). - to_return( - status: 200, - body: fixture("github", "contents_java.json"), - headers: { "content-type" => "application/json" } - ) - stub_request(:get, File.join(url, "build.gradle?ref=sha")). - with(headers: { "Authorization" => "token token" }). - to_return( - status: 200, - body: fixture("github", "contents_java_basic_buildfile.json"), - headers: { "content-type" => "application/json" } - ) + stub_content_request("?ref=sha", "contents_java.json") + stub_content_request("build.gradle?ref=sha", "contents_java_basic_buildfile.json") end it "fetches the buildfile" do @@ -57,27 +54,9 @@ context "with a settings.gradle" do before do - stub_request(:get, url + "?ref=sha"). - with(headers: { "Authorization" => "token token" }). - to_return( - status: 200, - body: fixture("github", "contents_java_with_settings.json"), - headers: { "content-type" => "application/json" } - ) - stub_request(:get, File.join(url, "settings.gradle?ref=sha")). - with(headers: { "Authorization" => "token token" }). - to_return( - status: 200, - body: fixture("github", "contents_java_simple_settings.json"), - headers: { "content-type" => "application/json" } - ) - stub_request(:get, File.join(url, "app/build.gradle?ref=sha")). - with(headers: { "Authorization" => "token token" }). - to_return( - status: 200, - body: fixture("github", "contents_java_basic_buildfile.json"), - headers: { "content-type" => "application/json" } - ) + stub_content_request("?ref=sha", "contents_java_with_settings.json") + stub_content_request("settings.gradle?ref=sha", "contents_java_simple_settings.json") + stub_content_request("app/build.gradle?ref=sha", "contents_java_basic_buildfile.json") end it "fetches the main buildfile and subproject buildfile" do @@ -101,22 +80,25 @@ end end + context "only a settings.gradle" do + before do + stub_content_request("?ref=sha", "contents_java_only_settings.json") + stub_content_request("app?ref=sha", "contents_java_subproject.json") + stub_content_request("settings.gradle?ref=sha", "contents_java_simple_settings.json") + stub_content_request("app/build.gradle?ref=sha", "contents_java_basic_buildfile.json") + end + + it "fetches the main buildfile and subproject buildfile" do + expect(file_fetcher_instance.files.count).to eq(1) + expect(file_fetcher_instance.files.map(&:name)). + to match_array(%w(app/build.gradle)) + end + end + context "with kotlin" do before do - stub_request(:get, url + "?ref=sha"). - with(headers: { "Authorization" => "token token" }). - to_return( - status: 200, - body: fixture("github", "contents_kotlin.json"), - headers: { "content-type" => "application/json" } - ) - stub_request(:get, File.join(url, "build.gradle.kts?ref=sha")). - with(headers: { "Authorization" => "token token" }). - to_return( - status: 200, - body: fixture("github", "contents_kotlin_basic_buildfile.json"), - headers: { "content-type" => "application/json" } - ) + stub_content_request("?ref=sha", "contents_kotlin.json") + stub_content_request("build.gradle.kts?ref=sha", "contents_kotlin_basic_buildfile.json") stub_request(:get, File.join(url, "settings.gradle.kts?ref=sha")). with(headers: { "Authorization" => "token token" }). to_return(status: 404) @@ -130,27 +112,9 @@ context "with a settings.gradle.kts" do before do - stub_request(:get, url + "?ref=sha"). - with(headers: { "Authorization" => "token token" }). - to_return( - status: 200, - body: fixture("github", "contents_kotlin_with_settings.json"), - headers: { "content-type" => "application/json" } - ) - stub_request(:get, File.join(url, "settings.gradle.kts?ref=sha")). - with(headers: { "Authorization" => "token token" }). - to_return( - status: 200, - body: fixture("github", "contents_kotlin_simple_settings.json"), - headers: { "content-type" => "application/json" } - ) - stub_request(:get, File.join(url, "app/build.gradle.kts?ref=sha")). - with(headers: { "Authorization" => "token token" }). - to_return( - status: 200, - body: fixture("github", "contents_kotlin_basic_buildfile.json"), - headers: { "content-type" => "application/json" } - ) + stub_content_request("?ref=sha", "contents_kotlin_with_settings.json") + stub_content_request("settings.gradle.kts?ref=sha", "contents_kotlin_simple_settings.json") + stub_content_request("app/build.gradle.kts?ref=sha", "contents_kotlin_basic_buildfile.json") end it "fetches the main buildfile and subproject buildfile" do @@ -164,30 +128,9 @@ context "with a script plugin" do before do - stub_request(:get, url + "?ref=sha"). - with(headers: { "Authorization" => "token token" }). - to_return( - status: 200, - body: fixture("github", "contents_java.json"), - headers: { "content-type" => "application/json" } - ) - stub_request(:get, File.join(url, "build.gradle?ref=sha")). - with(headers: { "Authorization" => "token token" }). - to_return( - status: 200, - body: fixture( - "github", - "contents_java_buildfile_with_script_plugins.json" - ), - headers: { "content-type" => "application/json" } - ) - stub_request(:get, File.join(url, "gradle/dependencies.gradle?ref=sha")). - with(headers: { "Authorization" => "token token" }). - to_return( - status: 200, - body: fixture("github", "contents_java_simple_settings.json"), - headers: { "content-type" => "application/json" } - ) + stub_content_request("?ref=sha", "contents_java.json") + stub_content_request("build.gradle?ref=sha", "contents_java_buildfile_with_script_plugins.json") + stub_content_request("gradle/dependencies.gradle?ref=sha", "contents_java_simple_settings.json") end it "fetches the buildfile and the dependencies script" do @@ -198,26 +141,14 @@ context "that can't be found" do before do - stub_request(:get, url + "?ref=sha"). - with(headers: { "Authorization" => "token token" }). - to_return( - status: 200, - body: fixture("github", "contents_java.json"), - headers: { "content-type" => "application/json" } - ) + stub_content_request("?ref=sha", "contents_java.json") stub_request( :get, File.join(url, "gradle/dependencies.gradle?ref=sha") ).with(headers: { "Authorization" => "token token" }). to_return(status: 404) - stub_request(:get, File.join(url, "gradle?ref=sha")). - with(headers: { "Authorization" => "token token" }). - to_return( - status: 200, - body: fixture("github", "contents_with_settings.json"), - headers: { "content-type" => "application/json" } - ) + stub_content_request("gradle?ref=sha", "contents_with_settings.json") end it "raises a DependencyFileNotFound error" do diff --git a/gradle/spec/fixtures/github/contents_java_only_settings.json b/gradle/spec/fixtures/github/contents_java_only_settings.json new file mode 100644 index 0000000000..6b4ca56bc4 --- /dev/null +++ b/gradle/spec/fixtures/github/contents_java_only_settings.json @@ -0,0 +1,66 @@ +[ + { + "name": ".gitignore", + "path": ".gitignore", + "sha": "a1fc39c070f4f8ba52f278c15cd4d2121d07c8a8", + "size": 308, + "url": "https://api.github.com/repos/dependabot-fixtures/gradle-with-settings/contents/.gitignore?ref=main", + "html_url": "https://github.com/dependabot-fixtures/gradle-with-settings/blob/main/.gitignore", + "git_url": "https://api.github.com/repos/dependabot-fixtures/gradle-with-settings/git/blobs/a1fc39c070f4f8ba52f278c15cd4d2121d07c8a8", + "download_url": "https://raw.githubusercontent.com/dependabot-fixtures/gradle-with-settings/main/.gitignore", + "type": "file", + "_links": { + "self": "https://api.github.com/repos/dependabot-fixtures/gradle-with-settings/contents/.gitignore?ref=main", + "git": "https://api.github.com/repos/dependabot-fixtures/gradle-with-settings/git/blobs/a1fc39c070f4f8ba52f278c15cd4d2121d07c8a8", + "html": "https://github.com/dependabot-fixtures/gradle-with-settings/blob/main/.gitignore" + } + }, + { + "name": "dependencies", + "path": "dependencies", + "sha": "5df7f650b80fef281199e7d1c6bf53c6a5280802", + "size": 0, + "url": "https://api.github.com/repos/dependabot-fixtures/gradle-with-settings/contents/dependencies?ref=main", + "html_url": "https://github.com/dependabot-fixtures/gradle-with-settings/tree/main/dependencies", + "git_url": "https://api.github.com/repos/dependabot-fixtures/gradle-with-settings/git/trees/5df7f650b80fef281199e7d1c6bf53c6a5280802", + "download_url": null, + "type": "dir", + "_links": { + "self": "https://api.github.com/repos/dependabot-fixtures/gradle-with-settings/contents/dependencies?ref=main", + "git": "https://api.github.com/repos/dependabot-fixtures/gradle-with-settings/git/trees/5df7f650b80fef281199e7d1c6bf53c6a5280802", + "html": "https://github.com/dependabot-fixtures/gradle-with-settings/tree/main/dependencies" + } + }, + { + "name": "pom.xml", + "path": "pom.xml", + "sha": "9a0a1f4bb5db4083b7f4ba9d8fee33675de8dc62", + "size": 15579, + "url": "https://api.github.com/repos/dependabot-fixtures/gradle-with-settings/contents/pom.xml?ref=main", + "html_url": "https://github.com/dependabot-fixtures/gradle-with-settings/blob/main/pom.xml", + "git_url": "https://api.github.com/repos/dependabot-fixtures/gradle-with-settings/git/blobs/9a0a1f4bb5db4083b7f4ba9d8fee33675de8dc62", + "download_url": "https://raw.githubusercontent.com/dependabot-fixtures/gradle-with-settings/main/pom.xml", + "type": "file", + "_links": { + "self": "https://api.github.com/repos/dependabot-fixtures/gradle-with-settings/contents/pom.xml?ref=main", + "git": "https://api.github.com/repos/dependabot-fixtures/gradle-with-settings/git/blobs/9a0a1f4bb5db4083b7f4ba9d8fee33675de8dc62", + "html": "https://github.com/dependabot-fixtures/gradle-with-settings/blob/main/pom.xml" + } + }, + { + "name": "settings.gradle", + "path": "settings.gradle", + "sha": "a9fc565d30dbca65176e111b6d9a24351e146b4c", + "size": 38, + "url": "https://api.github.com/repos/dependabot-fixtures/gradle-with-settings/contents/settings.gradle?ref=main", + "html_url": "https://github.com/dependabot-fixtures/gradle-with-settings/blob/main/settings.gradle", + "git_url": "https://api.github.com/repos/dependabot-fixtures/gradle-with-settings/git/blobs/a9fc565d30dbca65176e111b6d9a24351e146b4c", + "download_url": "https://raw.githubusercontent.com/dependabot-fixtures/gradle-with-settings/main/settings.gradle", + "type": "file", + "_links": { + "self": "https://api.github.com/repos/dependabot-fixtures/gradle-with-settings/contents/settings.gradle?ref=main", + "git": "https://api.github.com/repos/dependabot-fixtures/gradle-with-settings/git/blobs/a9fc565d30dbca65176e111b6d9a24351e146b4c", + "html": "https://github.com/dependabot-fixtures/gradle-with-settings/blob/main/settings.gradle" + } + } +] diff --git a/gradle/spec/fixtures/github/contents_java_subproject.json b/gradle/spec/fixtures/github/contents_java_subproject.json new file mode 100644 index 0000000000..0ddb6d13ee --- /dev/null +++ b/gradle/spec/fixtures/github/contents_java_subproject.json @@ -0,0 +1,18 @@ +[ + { + "name": "build.gradle", + "path": "app/build.gradle", + "sha": "f036f9f0357a50b02a422923f0bb0c3719eaf8ae", + "size": 2355, + "url": "https://api.github.com/repos/dependabot-fixtures/gradle/contents/build.gradle?ref=main", + "html_url": "https://github.com/dependabot-fixtures/gradle/blob/main/build.gradle", + "git_url": "https://api.github.com/repos/dependabot-fixtures/gradle/git/blobs/f036f9f0357a50b02a422923f0bb0c3719eaf8ae", + "download_url": "https://raw.githubusercontent.com/dependabot-fixtures/gradle/main/build.gradle", + "type": "file", + "_links": { + "self": "https://api.github.com/repos/dependabot-fixtures/gradle/contents/build.gradle?ref=main", + "git": "https://api.github.com/repos/dependabot-fixtures/gradle/git/blobs/f036f9f0357a50b02a422923f0bb0c3719eaf8ae", + "html": "https://github.com/dependabot-fixtures/gradle/blob/main/build.gradle" + } + } +] From cf754ff9cb6c7a0d2d5c1bf12a3af21064e12c34 Mon Sep 17 00:00:00 2001 From: Jurre Date: Thu, 7 Oct 2021 16:12:23 +0200 Subject: [PATCH 2/2] Gradle: Prefer method call over instance variable access in file fetcher --- gradle/lib/dependabot/gradle/file_fetcher.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/lib/dependabot/gradle/file_fetcher.rb b/gradle/lib/dependabot/gradle/file_fetcher.rb index 91ca9e657a..6743b0e512 100644 --- a/gradle/lib/dependabot/gradle/file_fetcher.rb +++ b/gradle/lib/dependabot/gradle/file_fetcher.rb @@ -89,7 +89,7 @@ def dependency_script_plugins # rubocop:enable Metrics/PerceivedComplexity def check_required_files_present - return if buildfile || (@subproject_buildfiles && !@subproject_buildfiles.empty?) + return if buildfile || (subproject_buildfiles && !subproject_buildfiles.empty?) path = Pathname.new(File.join(directory, "build.gradle")).cleanpath.to_path path += "(.kts)?"